Bug 1195158. Part 3 - connect listeners. r=cpearce.
authorJW Wang <jwwang@mozilla.com>
Mon, 07 Sep 2015 11:38:34 +0800
changeset 290888 778e3577ee7de91c77893aa71c717eb9589fa33e
parent 290887 642778802ad866e07951194bc6cc8558f248d783
child 290889 36369d9491bc9d5db73e66da98ad583d4bc82b1a
push id5188
push userdburns@mozilla.com
push dateTue, 08 Sep 2015 12:16:07 +0000
reviewerscpearce
bugs1195158
milestone43.0a1
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();