Bug 1219142. Part 1 - add AbstractMediaDecoder::DataArrivedEvent() to publish events. r=jya. draft
authorJW Wang <jwwang@mozilla.com>
Tue, 17 Nov 2015 09:46:45 +0800
changeset 309374 016f8182123566ed757ed01c44168b89b5ee8324
parent 309373 81ada12d1bb2ad3b0ede8336dc6bb5fb995931b2
child 309375 67b7bf155619bfcad42f8b369c0893b052c03610
push id7586
push userjwwang@mozilla.com
push dateTue, 17 Nov 2015 10:36:52 +0000
reviewersjya
bugs1219142
milestone45.0a1
Bug 1219142. Part 1 - add AbstractMediaDecoder::DataArrivedEvent() to publish events. r=jya.
dom/media/AbstractMediaDecoder.h
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderReader.cpp
dom/media/MediaDecoderReader.h
--- a/dom/media/AbstractMediaDecoder.h
+++ b/dom/media/AbstractMediaDecoder.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef AbstractMediaDecoder_h_
 #define AbstractMediaDecoder_h_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/StateMirroring.h"
 
+#include "MediaEventSource.h"
 #include "MediaInfo.h"
 #include "nsISupports.h"
 #include "nsDataHashtable.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla
 {
 
@@ -63,16 +64,25 @@ public:
   // Increments the parsed, decoded and dropped frame counters by the passed in
   // counts.
   // Can be called on any thread.
   virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded,
                                    uint32_t aDropped) = 0;
 
   virtual AbstractCanonical<media::NullableTimeUnit>* CanonicalDurationOrNull() { return nullptr; };
 
+  // Return an event that will be notified when data arrives in MediaResource.
+  // MediaDecoderReader will register with this event to receive notifications
+  // in order to udpate buffer ranges.
+  // Return null if this decoder doesn't support the event.
+  virtual MediaEventSource<void>* DataArrivedEvent()
+  {
+    return nullptr;
+  }
+
 protected:
   virtual void UpdateEstimatedMediaDuration(int64_t aDuration) {};
 public:
   void DispatchUpdateEstimatedMediaDuration(int64_t aDuration)
   {
     nsCOMPtr<nsIRunnable> r =
       NS_NewRunnableMethodWithArg<int64_t>(this, &AbstractMediaDecoder::UpdateEstimatedMediaDuration,
                                            aDuration);
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -1442,20 +1442,23 @@ void MediaDecoder::AddSizeOfResources(Re
     aSizes->mByteSize += GetResource()->SizeOfIncludingThis(aSizes->mMallocSizeOf);
   }
 }
 
 void
 MediaDecoder::NotifyDataArrived() {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (mDecoderStateMachine) {
-    mDecoderStateMachine->DispatchNotifyDataArrived();
+  // Don't publish events since task queues might be shutting down.
+  if (mShuttingDown) {
+    return;
   }
 
+  mDataArrivedEvent.Notify();
+
   // ReadyState computation depends on MediaDecoder::CanPlayThrough, which
   // depends on the download rate.
   UpdateReadyState();
 }
 
 // Provide access to the state machine object
 MediaDecoderStateMachine*
 MediaDecoder::GetStateMachine() const {
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -815,16 +815,21 @@ protected:
   /******
    * The following member variables can be accessed from any thread.
    ******/
 
   // Media data resource.
   RefPtr<MediaResource> mResource;
 
 private:
+  MediaEventSource<void>*
+  DataArrivedEvent() override { return &mDataArrivedEvent; }
+
+  MediaEventProducer<void> mDataArrivedEvent;
+
   // The state machine object for handling the decoding. It is safe to
   // call methods of this object from other threads. Its internal data
   // is synchronised on a monitor. The lifetime of this object is
   // after mPlayState is LOADING and before mPlayState is SHUTDOWN. It
   // is safe to access it during this period.
   //
   // Explicitly prievate to force access via accessors.
   RefPtr<MediaDecoderStateMachine> mDecoderStateMachine;
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -74,16 +74,21 @@ MediaDecoderReader::MediaDecoderReader(A
   , mHitAudioDecodeError(false)
   , mShutdown(false)
   , mAudioDiscontinuity(false)
   , mVideoDiscontinuity(false)
 {
   MOZ_COUNT_CTOR(MediaDecoderReader);
   MOZ_ASSERT(NS_IsMainThread());
 
+  if (mDecoder && mDecoder->DataArrivedEvent()) {
+    mDataArrivedListener = mDecoder->DataArrivedEvent()->Connect(
+      mTaskQueue, this, &MediaDecoderReader::NotifyDataArrived);
+  }
+
   // Dispatch initialization that needs to happen on that task queue.
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(this, &MediaDecoderReader::InitializationTask);
   mTaskQueue->Dispatch(r.forget());
 }
 
 void
 MediaDecoderReader::InitializationTask()
 {
@@ -355,16 +360,18 @@ RefPtr<ShutdownPromise>
 MediaDecoderReader::Shutdown()
 {
   MOZ_ASSERT(OnTaskQueue());
   mShutdown = true;
 
   mBaseAudioPromise.RejectIfExists(END_OF_STREAM, __func__);
   mBaseVideoPromise.RejectIfExists(END_OF_STREAM, __func__);
 
+  mDataArrivedListener.DisconnectIfExists();
+
   ReleaseMediaResources();
   mDuration.DisconnectIfConnected();
   mBuffered.DisconnectAll();
 
   // Shut down the watch manager before shutting down our task queue.
   mWatchManager.Shutdown();
 
   RefPtr<ShutdownPromise> p;
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -423,13 +423,15 @@ private:
   // of Request{Audio,Video}Data.
   MozPromiseHolder<AudioDataPromise> mBaseAudioPromise;
   MozPromiseHolder<VideoDataPromise> mBaseVideoPromise;
 
   // Flags whether a the next audio/video sample comes after a "gap" or
   // "discontinuity" in the stream. For example after a seek.
   bool mAudioDiscontinuity;
   bool mVideoDiscontinuity;
+
+  MediaEventListener mDataArrivedListener;
 };
 
 } // namespace mozilla
 
 #endif