Bug 1202296 - Hide the MFTDecoder within MFTManager so that we can recreate it opaquely. r=cpearce
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 10 Sep 2015 13:38:17 -0400
changeset 294446 8a7d924a0f3435f0d9626a05449dcbe35c4f0a95
parent 294445 9a09b707e39b5e6b8cb443b16f28e64c6844bde9
child 294447 e7e0427710e1b21ec0db81f47db472de0934e38a
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
bugs1202296
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 1202296 - Hide the MFTDecoder within MFTManager so that we can recreate it opaquely. r=cpearce
dom/media/platforms/wmf/WMFAudioMFTManager.cpp
dom/media/platforms/wmf/WMFAudioMFTManager.h
dom/media/platforms/wmf/WMFDecoderModule.cpp
dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
dom/media/platforms/wmf/WMFMediaDataDecoder.h
dom/media/platforms/wmf/WMFVideoMFTManager.cpp
dom/media/platforms/wmf/WMFVideoMFTManager.h
--- a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
@@ -108,73 +108,73 @@ WMFAudioMFTManager::GetMediaSubtypeGUID(
   MOZ_ASSERT(mStreamType != Unknown);
   switch (mStreamType) {
     case AAC: return MFAudioFormat_AAC;
     case MP3: return MFAudioFormat_MP3;
     default: return GUID_NULL;
   };
 }
 
-already_AddRefed<MFTDecoder>
+bool
 WMFAudioMFTManager::Init()
 {
-  NS_ENSURE_TRUE(mStreamType != Unknown, nullptr);
+  NS_ENSURE_TRUE(mStreamType != Unknown, false);
 
   RefPtr<MFTDecoder> decoder(new MFTDecoder());
 
   HRESULT hr = decoder->Create(GetMFTGUID());
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   // Setup input/output media types
   RefPtr<IMFMediaType> inputType;
 
   hr = wmf::MFCreateMediaType(byRef(inputType));
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = inputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = inputType->SetGUID(MF_MT_SUBTYPE, GetMediaSubtypeGUID());
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = inputType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, mAudioRate);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = inputType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, mAudioChannels);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   if (mStreamType == AAC) {
     hr = inputType->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 0x0); // Raw AAC packet
-    NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+    NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
     hr = inputType->SetBlob(MF_MT_USER_DATA,
                             mUserData.Elements(),
                             mUserData.Length());
-    NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+    NS_ENSURE_TRUE(SUCCEEDED(hr), false);
   }
 
   RefPtr<IMFMediaType> outputType;
   hr = wmf::MFCreateMediaType(byRef(outputType));
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = outputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = outputType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = outputType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = decoder->SetMediaTypes(inputType, outputType);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   mDecoder = decoder;
 
-  return decoder.forget();
+  return true;
 }
 
 HRESULT
 WMFAudioMFTManager::Input(MediaRawData* aSample)
 {
   return mDecoder->Input(aSample->Data(),
                          uint32_t(aSample->Size()),
                          aSample->mTime);
--- a/dom/media/platforms/wmf/WMFAudioMFTManager.h
+++ b/dom/media/platforms/wmf/WMFAudioMFTManager.h
@@ -14,17 +14,17 @@
 
 namespace mozilla {
 
 class WMFAudioMFTManager : public MFTManager {
 public:
   WMFAudioMFTManager(const AudioInfo& aConfig);
   ~WMFAudioMFTManager();
 
-  virtual already_AddRefed<MFTDecoder> Init() override;
+  bool Init();
 
   virtual HRESULT Input(MediaRawData* aSample) override;
 
   // Note WMF's AAC decoder sometimes output negatively timestamped samples,
   // presumably they're the preroll samples, and we strip them. We may return
   // a null aOutput in this case.
   virtual HRESULT Output(int64_t aStreamOffset,
                          nsRefPtr<MediaData>& aOutput) override;
@@ -34,19 +34,16 @@ public:
   virtual TrackInfo::TrackType GetType() override {
     return TrackInfo::kAudioTrack;
   }
 
 private:
 
   HRESULT UpdateOutputType();
 
-  // IMFTransform wrapper that performs the decoding.
-  RefPtr<MFTDecoder> mDecoder;
-
   uint32_t mAudioChannels;
   uint32_t mAudioRate;
   nsTArray<BYTE> mUserData;
 
   // The offset, at which playback started since the
   // last discontinuity.
   media::TimeUnit mAudioTimeOffset;
   // The number of audio frames that we've played since the last
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -92,42 +92,39 @@ WMFDecoderModule::CreateVideoDecoder(con
                                      MediaDataDecoderCallback* aCallback)
 {
   nsAutoPtr<WMFVideoMFTManager> manager(
     new WMFVideoMFTManager(aConfig,
                            aLayersBackend,
                            aImageContainer,
                            sDXVAEnabled));
 
-  nsRefPtr<MFTDecoder> mft = manager->Init();
-
-  if (!mft) {
+  if (!manager->Init()) {
     return nullptr;
   }
 
   nsRefPtr<MediaDataDecoder> decoder =
-    new WMFMediaDataDecoder(manager.forget(), mft, aVideoTaskQueue, aCallback);
+    new WMFMediaDataDecoder(manager.forget(), aVideoTaskQueue, aCallback);
 
   return decoder.forget();
 }
 
 already_AddRefed<MediaDataDecoder>
 WMFDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
                                      FlushableTaskQueue* aAudioTaskQueue,
                                      MediaDataDecoderCallback* aCallback)
 {
   nsAutoPtr<WMFAudioMFTManager> manager(new WMFAudioMFTManager(aConfig));
-  nsRefPtr<MFTDecoder> mft = manager->Init();
 
-  if (!mft) {
+  if (!manager->Init()) {
     return nullptr;
   }
 
   nsRefPtr<MediaDataDecoder> decoder =
-    new WMFMediaDataDecoder(manager.forget(), mft, aAudioTaskQueue, aCallback);
+    new WMFMediaDataDecoder(manager.forget(), aAudioTaskQueue, aCallback);
   return decoder.forget();
 }
 
 bool
 WMFDecoderModule::SupportsMimeType(const nsACString& aMimeType)
 {
   return aMimeType.EqualsLiteral("video/mp4") ||
          aMimeType.EqualsLiteral("video/avc") ||
--- a/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
+++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
@@ -13,41 +13,36 @@
 #include "mozilla/Logging.h"
 
 PRLogModuleInfo* GetDemuxerLog();
 #define LOG(...) MOZ_LOG(GetDemuxerLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
 
 namespace mozilla {
 
 WMFMediaDataDecoder::WMFMediaDataDecoder(MFTManager* aMFTManager,
-                                         MFTDecoder* aDecoder,
                                          FlushableTaskQueue* aTaskQueue,
                                          MediaDataDecoderCallback* aCallback)
   : mTaskQueue(aTaskQueue)
   , mCallback(aCallback)
-  , mDecoder(aDecoder)
   , mMFTManager(aMFTManager)
   , mMonitor("WMFMediaDataDecoder")
   , mIsFlushing(false)
   , mIsShutDown(false)
 {
 }
 
 WMFMediaDataDecoder::~WMFMediaDataDecoder()
 {
 }
 
 nsRefPtr<MediaDataDecoder::InitPromise>
 WMFMediaDataDecoder::Init()
 {
   MOZ_ASSERT(!mIsShutDown);
-
-  return mDecoder ?
-           InitPromise::CreateAndResolve(mMFTManager->GetType(), __func__) :
-           InitPromise::CreateAndReject(MediaDataDecoder::DecoderFailureReason::INIT_ERROR, __func__);
+  return InitPromise::CreateAndResolve(mMFTManager->GetType(), __func__);
 }
 
 // A single telemetry sample is reported for each MediaDataDecoder object
 // that has detected error or produced output successfully.
 static void
 SendTelemetry(unsigned long hr)
 {
   // Collapse the error codes into a range of 0-0xff that can be viewed in
@@ -99,17 +94,16 @@ WMFMediaDataDecoder::ProcessShutdown()
 {
   if (mMFTManager) {
     mMFTManager->Shutdown();
     mMFTManager = nullptr;
     if (!mRecordedError && mHasSuccessfulOutput) {
       SendTelemetry(S_OK);
     }
   }
-  mDecoder = nullptr;
 }
 
 // Inserts data into the decoder's pipeline.
 nsresult
 WMFMediaDataDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
@@ -172,18 +166,18 @@ WMFMediaDataDecoder::ProcessOutput()
       mRecordedError = true;
     }
   }
 }
 
 void
 WMFMediaDataDecoder::ProcessFlush()
 {
-  if (mDecoder) {
-    mDecoder->Flush();
+  if (mMFTManager) {
+    mMFTManager->Flush();
   }
   MonitorAutoLock mon(mMonitor);
   mIsFlushing = false;
   mon.NotifyAll();
 }
 
 nsresult
 WMFMediaDataDecoder::Flush()
@@ -205,21 +199,19 @@ WMFMediaDataDecoder::Flush()
 void
 WMFMediaDataDecoder::ProcessDrain()
 {
   bool isFlushing;
   {
     MonitorAutoLock mon(mMonitor);
     isFlushing = mIsFlushing;
   }
-  if (!isFlushing && mDecoder) {
+  if (!isFlushing && mMFTManager) {
     // Order the decoder to drain...
-    if (FAILED(mDecoder->SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0))) {
-      NS_WARNING("Failed to send DRAIN command to MFT");
-    }
+    mMFTManager->Drain();
     // Then extract all available output.
     ProcessOutput();
   }
   mCallback->DrainComplete();
 }
 
 nsresult
 WMFMediaDataDecoder::Drain()
--- a/dom/media/platforms/wmf/WMFMediaDataDecoder.h
+++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.h
@@ -17,52 +17,59 @@ namespace mozilla {
 
 // Encapsulates the initialization of the MFTDecoder appropriate for decoding
 // a given stream, and the process of converting the IMFSample produced
 // by the MFT into a MediaData object.
 class MFTManager {
 public:
   virtual ~MFTManager() {}
 
-  // Creates an initializs the MFTDecoder.
-  // Returns nullptr on failure.
-  virtual already_AddRefed<MFTDecoder> Init() = 0;
-
   // Submit a compressed sample for decoding.
   // This should forward to the MFTDecoder after performing
   // any required sample formatting.
   virtual HRESULT Input(MediaRawData* aSample) = 0;
 
   // Produces decoded output, if possible. Blocks until output can be produced,
   // or until no more is able to be produced.
   // Returns S_OK on success, or MF_E_TRANSFORM_NEED_MORE_INPUT if there's not
   // enough data to produce more output. If this returns a failure code other
   // than MF_E_TRANSFORM_NEED_MORE_INPUT, an error will be reported to the
   // MP4Reader.
   virtual HRESULT Output(int64_t aStreamOffset,
                          nsRefPtr<MediaData>& aOutput) = 0;
 
+  void Flush() { mDecoder->Flush(); }
+
+  void Drain()
+  {
+    if (FAILED(mDecoder->SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0))) {
+      NS_WARNING("Failed to send DRAIN command to MFT");
+    }
+  }
+
   // Destroys all resources.
   virtual void Shutdown() = 0;
 
   virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const { return false; }
 
   virtual TrackInfo::TrackType GetType() = 0;
 
+protected:
+  // IMFTransform wrapper that performs the decoding.
+  RefPtr<MFTDecoder> mDecoder;
 };
 
 // Decodes audio and video using Windows Media Foundation. Samples are decoded
 // using the MFTDecoder created by the MFTManager. This class implements
 // the higher-level logic that drives mapping the MFT to the async
 // MediaDataDecoder interface. The specifics of decoding the exact stream
 // type are handled by MFTManager and the MFTDecoder it creates.
 class WMFMediaDataDecoder : public MediaDataDecoder {
 public:
   WMFMediaDataDecoder(MFTManager* aOutputSource,
-                      MFTDecoder* aDecoder,
                       FlushableTaskQueue* aAudioTaskQueue,
                       MediaDataDecoderCallback* aCallback);
   ~WMFMediaDataDecoder();
 
   virtual nsRefPtr<MediaDataDecoder::InitPromise> Init() override;
 
   virtual nsresult Input(MediaRawData* aSample);
 
@@ -92,17 +99,16 @@ private:
   // all available output.
   void ProcessDrain();
 
   void ProcessShutdown();
 
   RefPtr<FlushableTaskQueue> mTaskQueue;
   MediaDataDecoderCallback* mCallback;
 
-  RefPtr<MFTDecoder> mDecoder;
   nsAutoPtr<MFTManager> mMFTManager;
 
   // The last offset into the media resource that was passed into Input().
   // This is used to approximate the decoder's position in the media resource.
   int64_t mLastStreamOffset;
 
   // For access to and waiting on mIsFlushing
   Monitor mMonitor;
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -177,44 +177,44 @@ WMFVideoMFTManager::InitializeDXVA(bool 
   } else {
     NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
   }
   mDXVA2Manager = event->mDXVA2Manager;
 
   return mDXVA2Manager != nullptr;
 }
 
-already_AddRefed<MFTDecoder>
+bool
 WMFVideoMFTManager::Init()
 {
-  RefPtr<MFTDecoder> decoder = InitInternal(/* aForceD3D9 = */ false);
+  bool success = InitInternal(/* aForceD3D9 = */ false);
 
   // If initialization failed with d3d11 DXVA then try falling back
   // to d3d9.
-  if (!decoder && mDXVA2Manager && mDXVA2Manager->IsD3D11()) {
+  if (!success && mDXVA2Manager && mDXVA2Manager->IsD3D11()) {
     mDXVA2Manager = nullptr;
     nsCString d3d11Failure = mDXVAFailureReason;
-    decoder = InitInternal(true);
+    success = InitInternal(true);
     mDXVAFailureReason.Append(NS_LITERAL_CSTRING("; "));
     mDXVAFailureReason.Append(d3d11Failure);
   }
 
-  return decoder.forget();
+  return success;
 }
 
-already_AddRefed<MFTDecoder>
+bool
 WMFVideoMFTManager::InitInternal(bool aForceD3D9)
 {
   mUseHwAccel = false; // default value; changed if D3D setup succeeds.
   bool useDxva = InitializeDXVA(aForceD3D9);
 
   RefPtr<MFTDecoder> decoder(new MFTDecoder());
 
   HRESULT hr = decoder->Create(GetMFTGUID());
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   RefPtr<IMFAttributes> attr(decoder->GetAttributes());
   UINT32 aware = 0;
   if (attr) {
     attr->GetUINT32(MF_SA_D3D_AWARE, &aware);
     attr->SetUINT32(CODECAPI_AVDecNumWorkerThreads,
       WMFDecoderModule::GetNumDecoderThreads());
     hr = attr->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE);
@@ -243,28 +243,28 @@ WMFVideoMFTManager::InitInternal(bool aF
     }
     else {
       mDXVAFailureReason.AssignLiteral("Decoder returned false for MF_SA_D3D_AWARE");
     }
   }
 
   mDecoder = decoder;
   hr = SetDecoderMediaTypes();
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   LOG("Video Decoder initialized, Using DXVA: %s", (mUseHwAccel ? "Yes" : "No"));
 
   // Just in case ConfigureVideoFrameGeometry() does not set these
   mVideoInfo = VideoInfo();
   mVideoStride = 0;
   mVideoWidth = 0;
   mVideoHeight = 0;
   mPictureRegion.SetEmpty();
 
-  return decoder.forget();
+  return true;
 }
 
 HRESULT
 WMFVideoMFTManager::SetDecoderMediaTypes()
 {
   // Setup the input/output media types.
   RefPtr<IMFMediaType> inputType;
   HRESULT hr = wmf::MFCreateMediaType(byRef(inputType));
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.h
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.h
@@ -20,17 +20,17 @@ class DXVA2Manager;
 class WMFVideoMFTManager : public MFTManager {
 public:
   WMFVideoMFTManager(const VideoInfo& aConfig,
                      mozilla::layers::LayersBackend aLayersBackend,
                      mozilla::layers::ImageContainer* aImageContainer,
                      bool aDXVAEnabled);
   ~WMFVideoMFTManager();
 
-  virtual already_AddRefed<MFTDecoder> Init() override;
+  bool Init();
 
   virtual HRESULT Input(MediaRawData* aSample) override;
 
   virtual HRESULT Output(int64_t aStreamOffset,
                          nsRefPtr<MediaData>& aOutput) override;
 
   virtual void Shutdown() override;
 
@@ -39,17 +39,17 @@ public:
   virtual TrackInfo::TrackType GetType() override {
     return TrackInfo::kVideoTrack;
   }
 
 private:
 
   bool InitializeDXVA(bool aForceD3D9);
 
-  already_AddRefed<MFTDecoder> InitInternal(bool aForceD3D9);
+  bool InitInternal(bool aForceD3D9);
 
   HRESULT ConfigureVideoFrameGeometry();
 
   HRESULT CreateBasicVideoFrame(IMFSample* aSample,
                                 int64_t aStreamOffset,
                                 VideoData** aOutVideoData);
 
   HRESULT CreateD3DVideoFrame(IMFSample* aSample,
@@ -62,17 +62,16 @@ private:
 
   // Video frame geometry.
   VideoInfo mVideoInfo;
   uint32_t mVideoStride;
   uint32_t mVideoWidth;
   uint32_t mVideoHeight;
   nsIntRect mPictureRegion;
 
-  RefPtr<MFTDecoder> mDecoder;
   RefPtr<layers::ImageContainer> mImageContainer;
   nsAutoPtr<DXVA2Manager> mDXVA2Manager;
 
   RefPtr<IMFSample> mLastInput;
   float mLastDuration;
 
   const bool mDXVAEnabled;
   const layers::LayersBackend mLayersBackend;