Bug 1312337. Part 3 - employ DecoderAllocPolicy for controlling decoder creation. draft
authorJW Wang <jwwang@mozilla.com>
Thu, 27 Oct 2016 15:16:06 +0800
changeset 432042 f98cf5d779e0fccb6fe632d5f1b2ce08d240af09
parent 432041 9725e72bb2f515529ed3e09fade96a3214a7a043
child 432043 d4083d2aa33d643f9744f04a750421318f4dfcd4
push id34177
push userjwwang@mozilla.com
push dateTue, 01 Nov 2016 05:20:21 +0000
bugs1312337
milestone52.0a1
Bug 1312337. Part 3 - employ DecoderAllocPolicy for controlling decoder creation. MozReview-Commit-ID: JdDq1Y8oFn4
dom/media/MediaFormatReader.cpp
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -161,35 +161,44 @@ void
 DecoderAllocPolicy::operator=(std::nullptr_t)
 {
   delete this;
 }
 
 class MediaFormatReader::DecoderFactory
 {
   using InitPromise = MediaDataDecoder::InitPromise;
+  using TokenPromise = DecoderAllocPolicy::Promise;
+  using Token = DecoderAllocPolicy::Token;
 
 public:
   explicit DecoderFactory(MediaFormatReader* aOwner) : mOwner(aOwner) {}
   void CreateDecoder(TrackType aTrack);
 
 private:
+  class Wrapper;
+
   enum class Stage : int8_t
   {
     None,
+    WaitForToken,
+    CreateDecoder,
     WaitForInit
   };
 
   struct Data
   {
     Stage mStage = Stage::None;
+    RefPtr<Token> mToken;
     RefPtr<MediaDataDecoder> mDecoder;
+    MozPromiseRequestHolder<TokenPromise> mTokenPromise;
     MozPromiseRequestHolder<InitPromise> mInitPromise;
     ~Data()
     {
+      mTokenPromise.DisconnectIfExists();
       mInitPromise.DisconnectIfExists();
       if (mDecoder) {
         mDecoder->Shutdown();
       }
     }
   } mAudio, mVideo;
 
   void RunStage(TrackType aTrack);
@@ -202,34 +211,98 @@ private:
 void
 MediaFormatReader::DecoderFactory::CreateDecoder(TrackType aTrack)
 {
   MOZ_ASSERT(aTrack == TrackInfo::kAudioTrack ||
              aTrack == TrackInfo::kVideoTrack);
   RunStage(aTrack);
 }
 
+class MediaFormatReader::DecoderFactory::Wrapper : public MediaDataDecoder
+{
+  using Token = DecoderAllocPolicy::Token;
+
+public:
+  Wrapper(already_AddRefed<MediaDataDecoder> aDecoder,
+          already_AddRefed<Token> aToken)
+    : mDecoder(aDecoder), mToken(aToken) {}
+
+  RefPtr<InitPromise> Init() override { return mDecoder->Init(); }
+  void Input(MediaRawData* aSample) override { mDecoder->Input(aSample); }
+  void Flush() override { mDecoder->Flush(); }
+  void Drain() override { mDecoder->Drain(); }
+  bool IsHardwareAccelerated(nsACString& aFailureReason) const override
+  {
+    return mDecoder->IsHardwareAccelerated(aFailureReason);
+  }
+  const char* GetDescriptionName() const override
+  {
+    return mDecoder->GetDescriptionName();
+  }
+  void SetSeekThreshold(const media::TimeUnit& aTime) override
+  {
+    mDecoder->SetSeekThreshold(aTime);
+  }
+  void Shutdown() override
+  {
+    mDecoder->Shutdown();
+    mDecoder = nullptr;
+    mToken = nullptr;
+  }
+
+private:
+  RefPtr<MediaDataDecoder> mDecoder;
+  RefPtr<Token> mToken;
+};
+
 void
 MediaFormatReader::DecoderFactory::RunStage(TrackType aTrack)
 {
   auto& data = aTrack == TrackInfo::kAudioTrack ? mAudio : mVideo;
 
   switch (data.mStage) {
     case Stage::None: {
+      MOZ_ASSERT(!data.mToken);
+      data.mTokenPromise.Begin(DecoderAllocPolicy::Instance().Alloc(aTrack)->Then(
+        mOwner->OwnerThread(), __func__,
+        [this, &data, aTrack] (Token* aToken) {
+          data.mTokenPromise.Complete();
+          data.mToken = aToken;
+          data.mStage = Stage::CreateDecoder;
+          RunStage(aTrack);
+        },
+        [&data] () {
+          data.mTokenPromise.Complete();
+          data.mStage = Stage::None;
+        }));
+      data.mStage = Stage::WaitForToken;
+      break;
+    }
+
+    case Stage::WaitForToken: {
+      MOZ_ASSERT(!data.mToken);
+      MOZ_ASSERT(data.mTokenPromise.Exists());
+      break;
+    }
+
+    case Stage::CreateDecoder: {
+      MOZ_ASSERT(data.mToken);
       MOZ_ASSERT(!data.mDecoder);
       MOZ_ASSERT(!data.mInitPromise.Exists());
 
       MediaResult rv = DoCreateDecoder(aTrack);
       if (NS_FAILED(rv)) {
         NS_WARNING("Error constructing decoders");
+        data.mToken = nullptr;
         data.mStage = Stage::None;
         mOwner->NotifyError(aTrack, rv);
         return;
       }
 
+      data.mDecoder = new Wrapper(data.mDecoder.forget(), data.mToken.forget());
       DoInitDecoder(aTrack);
       data.mStage = Stage::WaitForInit;
       break;
     }
 
     case Stage::WaitForInit: {
       MOZ_ASSERT(data.mDecoder);
       MOZ_ASSERT(data.mInitPromise.Exists());