Bug 1195158. Part 3 - connect listeners. r=cpearce.
authorJW Wang <jwwang@mozilla.com>
Mon, 07 Sep 2015 11:38:34 +0800
changeset 293805 778e3577ee7de91c77893aa71c717eb9589fa33e
parent 293804 642778802ad866e07951194bc6cc8558f248d783
child 293806 36369d9491bc9d5db73e66da98ad583d4bc82b1a
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1195158
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1195158. Part 3 - connect listeners. r=cpearce. a. MediaMetadataManager is connected to MediaDecoderReader::mTimedMetadataEvent to receive TimedMetadata events. b. OggReader publish TimedMetadata events through MediaDecoderReader::mTimedMetadataEvent. c. MDSM calls MediaMetadataManager::DispatchMetadataIfNeeded to publish metadata if playback positoin reaches the publish time. d. MediaDecoder is connected to MediaMetadataManager::mTimedMetadataEvent to receive TimedMetadata events. e. MediaDecoder updates its metadata when TimedMetadata events are received.
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -453,16 +453,18 @@ void MediaDecoder::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mShuttingDown)
     return;
 
   mShuttingDown = true;
 
+  mTimedMetadataListener.Disconnect();
+
   // This changes the decoder state to SHUTDOWN and does other things
   // necessary to unblock the state machine thread if it's blocked, so
   // the asynchronous shutdown in nsDestroyStateMachine won't deadlock.
   if (mDecoderStateMachine) {
     mDecoderStateMachine->DispatchShutdown();
   }
 
   // Force any outstanding seek and byterange requests to complete
@@ -540,16 +542,18 @@ nsresult MediaDecoder::InitializeStateMa
 }
 
 void MediaDecoder::SetStateMachineParameters()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mMinimizePreroll) {
     mDecoderStateMachine->DispatchMinimizePrerollUntilPlaybackStarts();
   }
+  mTimedMetadataListener = mDecoderStateMachine->TimedMetadataEvent().Connect(
+    AbstractThread::MainThread(), this, &MediaDecoder::OnMetadataUpdate);
 }
 
 void MediaDecoder::SetMinimizePrerollUntilPlaybackStarts()
 {
   MOZ_ASSERT(NS_IsMainThread());
   DECODER_LOG("SetMinimizePrerollUntilPlaybackStarts()");
   mMinimizePreroll = true;
 
@@ -639,16 +643,27 @@ void MediaDecoder::QueueMetadata(const T
                                  nsAutoPtr<MediaInfo> aInfo,
                                  nsAutoPtr<MetadataTags> aTags)
 {
   MOZ_ASSERT(OnDecodeTaskQueue());
   GetReentrantMonitor().AssertCurrentThreadIn();
   mDecoderStateMachine->QueueMetadata(aPublishTime, aInfo, aTags);
 }
 
+void MediaDecoder::OnMetadataUpdate(TimedMetadata&& aMetadata)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  RemoveMediaTracks();
+  MetadataLoaded(nsAutoPtr<MediaInfo>(new MediaInfo(*aMetadata.mInfo)),
+                 Move(aMetadata.mTags),
+                 MediaDecoderEventVisibility::Observable);
+  FirstFrameLoaded(Move(aMetadata.mInfo),
+                   MediaDecoderEventVisibility::Observable);
+}
+
 void MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
                                   nsAutoPtr<MetadataTags> aTags,
                                   MediaDecoderEventVisibility aEventVisibility)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mShuttingDown) {
     return;
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -193,16 +193,17 @@ destroying the MediaDecoder object.
 
 #include "nsISupports.h"
 #include "nsCOMPtr.h"
 #include "nsIObserver.h"
 #include "nsAutoPtr.h"
 #include "nsITimer.h"
 #include "MediaResource.h"
 #include "MediaDecoderOwner.h"
+#include "MediaEventSource.h"
 #include "MediaStreamGraph.h"
 #include "AbstractMediaDecoder.h"
 #include "DecodedStream.h"
 #include "necko-config.h"
 #ifdef MOZ_EME
 #include "mozilla/CDMProxy.h"
 #endif
 #include "TimeUnits.h"
@@ -984,16 +985,18 @@ protected:
   // Ensures our media stream has been pinned.
   void PinForSeek();
 
   // Ensures our media stream has been unpinned.
   void UnpinForSeek();
 
   const char* PlayStateStr();
 
+  void OnMetadataUpdate(TimedMetadata&& aMetadata);
+
   // This should only ever be accessed from the main thread.
   // It is set in Init and cleared in Shutdown when the element goes away.
   // The decoder does not add a reference the element.
   MediaDecoderOwner* mOwner;
 
   // Counters related to decode and presentation of frames.
   FrameStatistics mFrameStats;
 
@@ -1054,16 +1057,19 @@ protected:
   const int mHeuristicDormantTimeout;
 
   // True if MediaDecoder is in dormant by heuristic.
   bool mIsHeuristicDormant;
 
   // Timer to schedule updating dormant state.
   nsCOMPtr<nsITimer> mDormantTimer;
 
+  // A listener to receive metadata updates from MDSM.
+  MediaEventListener mTimedMetadataListener;
+
 protected:
   // Whether the state machine is shut down.
   Mirror<bool> mStateMachineIsShutdown;
 
   // Buffered range, mirrored from the reader.
   Mirror<media::TimeIntervals> mBuffered;
 
   // NextFrameStatus, mirrored from the state machine.
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -284,16 +284,18 @@ MediaDecoderStateMachine::MediaDecoderSt
   timeBeginPeriod(1);
 #endif
 
   mAudioQueueListener = AudioQueue().PopEvent().Connect(
     mTaskQueue, this, &MediaDecoderStateMachine::OnAudioPopped);
   mVideoQueueListener = VideoQueue().PopEvent().Connect(
     mTaskQueue, this, &MediaDecoderStateMachine::OnVideoPopped);
 
+  mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
+
   nsRefPtr<MediaDecoderStateMachine> self = this;
   auto audioSinkCreator = [self] () {
     MOZ_ASSERT(self->OnTaskQueue());
     return new DecodedAudioDataSink(
       self->mAudioQueue, self->GetMediaTime(),
       self->mInfo.mAudio, self->mDecoder->GetAudioChannel());
   };
   mAudioSink = new AudioSinkWrapper(mTaskQueue, audioSinkCreator);
@@ -2190,16 +2192,17 @@ MediaDecoderStateMachine::FinishShutdown
 
   // The reader's listeners hold references to the state machine,
   // creating a cycle which keeps the state machine and its shared
   // thread pools alive. So break it here.
 
   // Prevent dangling pointers by disconnecting the listeners.
   mAudioQueueListener.Disconnect();
   mVideoQueueListener.Disconnect();
+  mMetadataManager.Disconnect();
 
   // Disconnect canonicals and mirrors before shutting down our task queue.
   mBuffered.DisconnectIfConnected();
   mEstimatedDuration.DisconnectIfConnected();
   mExplicitDuration.DisconnectIfConnected();
   mPlayState.DisconnectIfConnected();
   mNextPlayState.DisconnectIfConnected();
   mLogicallySeeking.DisconnectIfConnected();
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -152,16 +152,20 @@ public:
 
   void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
   // Remove an output stream added with AddOutputStream.
   void RemoveOutputStream(MediaStream* aStream);
 
   // Set/Unset dormant state.
   void SetDormant(bool aDormant);
 
+  TimedMetadataEventSource& TimedMetadataEvent() {
+    return mMetadataManager.TimedMetadataEvent();
+  }
+
 private:
   // Initialization that needs to happen on the task queue. This is the first
   // task that gets run on the task queue, and is dispatched from the MDSM
   // constructor immediately after the task queue is created.
   void InitializationTask();
 
   void DispatchAudioCaptured();
   void DispatchAudioUncaptured();