Bug 1208371 - Add `NotifyPrincipalHandleChanged` to MediaStreamTrackListener. r?mt,jesup
MozReview-Commit-ID: Hq0XtqIiMAO
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -306,16 +306,82 @@ MediaStreamGraphImpl::UpdateCurrentTimeF
for (uint32_t j = 0; j < stream->mListeners.Length(); ++j) {
MediaStreamListener* l = stream->mListeners[j];
l->NotifyEvent(this, MediaStreamListener::EVENT_FINISHED);
}
}
}
}
+template<typename C, typename Chunk>
+void
+MediaStreamGraphImpl::ProcessChunkMetadataForInterval(MediaStream* aStream,
+ TrackID aTrackID,
+ C& aSegment,
+ StreamTime aStart,
+ StreamTime aEnd)
+{
+ MOZ_ASSERT(aStream);
+ MOZ_ASSERT(IsTrackIDExplicit(aTrackID));
+
+ StreamTime offset = 0;
+ for (typename C::ConstChunkIterator chunk(aSegment);
+ !chunk.IsEnded(); chunk.Next()) {
+ if (offset >= aEnd) {
+ break;
+ }
+ offset += chunk->GetDuration();
+ if (chunk->IsNull() || offset < aStart) {
+ continue;
+ }
+ PrincipalHandle principalHandle = chunk->GetPrincipalHandle();
+ if (principalHandle != aSegment.GetLastPrincipalHandle()) {
+ aSegment.SetLastPrincipalHandle(principalHandle);
+ STREAM_LOG(LogLevel::Debug, ("MediaStream %p track %d, principalHandle "
+ "changed in %sChunk with duration %lld",
+ aStream, aTrackID,
+ aSegment.GetType() == MediaSegment::AUDIO
+ ? "Audio" : "Video",
+ (long long) chunk->GetDuration()));
+ for (const TrackBound<MediaStreamTrackListener>& listener : aStream->mTrackListeners) {
+ if (listener.mTrackID == aTrackID) {
+ listener.mListener->NotifyPrincipalHandleChanged(this, principalHandle);
+ }
+ }
+ }
+ }
+}
+
+void
+MediaStreamGraphImpl::ProcessChunkMetadata(GraphTime aPrevCurrentTime)
+{
+ for (MediaStream* stream : AllStreams()) {
+ StreamTime iterationStart = stream->GraphTimeToStreamTime(aPrevCurrentTime);
+ StreamTime iterationEnd = stream->GraphTimeToStreamTime(mProcessedTime);
+ for (StreamBuffer::TrackIter tracks(stream->mBuffer);
+ !tracks.IsEnded(); tracks.Next()) {
+ MediaSegment* segment = tracks->GetSegment();
+ if (!segment) {
+ continue;
+ }
+ if (tracks->GetType() == MediaSegment::AUDIO) {
+ AudioSegment* audio = static_cast<AudioSegment*>(segment);
+ ProcessChunkMetadataForInterval<AudioSegment, AudioChunk>(
+ stream, tracks->GetID(), *audio, iterationStart, iterationEnd);
+ } else if (tracks->GetType() == MediaSegment::VIDEO) {
+ VideoSegment* video = static_cast<VideoSegment*>(segment);
+ ProcessChunkMetadataForInterval<VideoSegment, VideoChunk>(
+ stream, tracks->GetID(), *video, iterationStart, iterationEnd);
+ } else {
+ MOZ_CRASH("Unknown track type");
+ }
+ }
+ }
+}
+
GraphTime
MediaStreamGraphImpl::WillUnderrun(MediaStream* aStream,
GraphTime aEndBlockingDecisions)
{
// Finished streams can't underrun. ProcessedMediaStreams also can't cause
// underrun currently, since we'll always be able to produce data for them
// unless they block on some other stream.
if (aStream->mFinished || aStream->AsProcessedStream()) {
@@ -1419,16 +1485,18 @@ MediaStreamGraphImpl::OneIteration(Graph
Process();
GraphTime oldProcessedTime = mProcessedTime;
mProcessedTime = stateEnd;
UpdateCurrentTimeForStreams(oldProcessedTime);
+ ProcessChunkMetadata(oldProcessedTime);
+
// Process graph messages queued from RunMessageAfterProcessing() on this
// thread during the iteration.
RunMessagesInQueue();
return UpdateMainThreadState();
}
void
@@ -2243,16 +2311,24 @@ MediaStream::RemoveListener(MediaStreamL
void
MediaStream::AddTrackListenerImpl(already_AddRefed<MediaStreamTrackListener> aListener,
TrackID aTrackID)
{
TrackBound<MediaStreamTrackListener>* l = mTrackListeners.AppendElement();
l->mListener = aListener;
l->mTrackID = aTrackID;
+
+ StreamBuffer::Track* track = FindTrack(aTrackID);
+ if (!track) {
+ return;
+ }
+ PrincipalHandle lastPrincipalHandle =
+ track->GetSegment()->GetLastPrincipalHandle();
+ l->mListener->NotifyPrincipalHandleChanged(Graph(), lastPrincipalHandle);
}
void
MediaStream::AddTrackListener(MediaStreamTrackListener* aListener,
TrackID aTrackID)
{
class Message : public ControlMessage {
public:
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -237,16 +237,19 @@ class MediaStreamTrackListener
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaStreamTrackListener)
public:
virtual void NotifyQueuedChanges(MediaStreamGraph* aGraph,
StreamTime aTrackOffset,
const MediaSegment& aQueuedMedia) {}
+ virtual void NotifyPrincipalHandleChanged(MediaStreamGraph* aGraph,
+ const PrincipalHandle& aNewPrincipalHandle) {}
+
virtual void NotifyEnded() {}
virtual void NotifyRemoved() {}
protected:
virtual ~MediaStreamTrackListener() {}
};
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -257,16 +257,31 @@ public:
*/
bool ShouldUpdateMainThread();
// The following methods are the various stages of RunThread processing.
/**
* Advance all stream state to mStateComputedTime.
*/
void UpdateCurrentTimeForStreams(GraphTime aPrevCurrentTime);
/**
+ * Process chunks for all streams and raise events for properties that have
+ * changed, such as principalId.
+ */
+ void ProcessChunkMetadata(GraphTime aPrevCurrentTime);
+ /**
+ * Process chunks for the given stream and interval, and raise events for
+ * properties that have changed, such as principalId.
+ */
+ template<typename C, typename Chunk>
+ void ProcessChunkMetadataForInterval(MediaStream* aStream,
+ TrackID aTrackID,
+ C& aSegment,
+ StreamTime aStart,
+ StreamTime aEnd);
+ /**
* Process graph messages in mFrontMessageQueue.
*/
void RunMessagesInQueue();
/**
* Update stream processing order and recompute stream blocking until
* aEndBlockingDecisions.
*/
void UpdateGraph(GraphTime aEndBlockingDecisions);