Bug 1110534 - Make PlatformDecoderModule ref counted. r=edwin, a=sledru
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 23 Dec 2014 14:36:10 +1100
changeset 242657 4ec9cd2be4f5cfb3c1c4ab7230ffa7b6aa16d5e1
parent 242656 d1682329ba58c9b3fa97e18c7faea737a7ec98e5
child 242658 ab63a3d5f7cdfbdbf58fd06df7095cba3aedbc59
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedwin, sledru
bugs1110534
milestone36.0a2
Bug 1110534 - Make PlatformDecoderModule ref counted. r=edwin, a=sledru
dom/media/fmp4/BlankDecoderModule.cpp
dom/media/fmp4/MP4Reader.h
dom/media/fmp4/PlatformDecoderModule.cpp
dom/media/fmp4/PlatformDecoderModule.h
dom/media/fmp4/SharedDecoderManager.cpp
dom/media/fmp4/eme/EMEDecoderModule.h
dom/media/fmp4/ffmpeg/FFmpegDecoderModule.h
dom/media/fmp4/ffmpeg/FFmpegRuntimeLinker.cpp
dom/media/fmp4/ffmpeg/FFmpegRuntimeLinker.h
dom/media/webm/IntelWebMVideoDecoder.h
--- a/dom/media/fmp4/BlankDecoderModule.cpp
+++ b/dom/media/fmp4/BlankDecoderModule.cpp
@@ -245,14 +245,15 @@ public:
   virtual bool
   SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE
   {
     return true;
   }
 
 };
 
-PlatformDecoderModule* CreateBlankDecoderModule()
+already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule()
 {
-  return new BlankDecoderModule();
+  nsRefPtr<PlatformDecoderModule> pdm = new BlankDecoderModule();
+  return pdm.forget();
 }
 
 } // namespace mozilla
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -113,17 +113,17 @@ private:
   bool IsSupportedAudioMimeType(const char* aMimeType);
   bool IsSupportedVideoMimeType(const char* aMimeType);
   void NotifyResourcesStatusChanged();
   void RequestCodecResource();
   bool IsWaitingOnCodecResource();
   virtual bool IsWaitingOnCDMResource() MOZ_OVERRIDE;
 
   nsAutoPtr<mp4_demuxer::MP4Demuxer> mDemuxer;
-  nsAutoPtr<PlatformDecoderModule> mPlatform;
+  nsRefPtr<PlatformDecoderModule> mPlatform;
 
   class DecoderCallback : public MediaDataDecoderCallback {
   public:
     DecoderCallback(MP4Reader* aReader,
                     mp4_demuxer::TrackType aType)
       : mReader(aReader)
       , mType(aType)
     {
--- a/dom/media/fmp4/PlatformDecoderModule.cpp
+++ b/dom/media/fmp4/PlatformDecoderModule.cpp
@@ -26,17 +26,17 @@
 #include "EMEDecoderModule.h"
 #include "mozilla/CDMProxy.h"
 #endif
 #include "SharedThreadPool.h"
 #include "MediaTaskQueue.h"
 
 namespace mozilla {
 
-extern PlatformDecoderModule* CreateBlankDecoderModule();
+extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
 
 bool PlatformDecoderModule::sUseBlankDecoder = false;
 bool PlatformDecoderModule::sFFmpegDecoderEnabled = false;
 bool PlatformDecoderModule::sGonkDecoderEnabled = false;
 bool PlatformDecoderModule::sAndroidMCDecoderEnabled = false;
 bool PlatformDecoderModule::sAndroidMCDecoderPreferred = false;
 
 /* static */
@@ -71,90 +71,94 @@ PlatformDecoderModule::Init()
 #endif
 #ifdef MOZ_APPLEMEDIA
   AppleDecoderModule::Init();
 #endif
 }
 
 #ifdef MOZ_EME
 /* static */
-PlatformDecoderModule*
+already_AddRefed<PlatformDecoderModule>
 PlatformDecoderModule::CreateCDMWrapper(CDMProxy* aProxy,
                                         bool aHasAudio,
                                         bool aHasVideo,
                                         MediaTaskQueue* aTaskQueue)
 {
   bool cdmDecodesAudio;
   bool cdmDecodesVideo;
   {
     CDMCaps::AutoLock caps(aProxy->Capabilites());
     cdmDecodesAudio = caps.CanDecryptAndDecodeAudio();
     cdmDecodesVideo = caps.CanDecryptAndDecodeVideo();
   }
 
-  nsAutoPtr<PlatformDecoderModule> pdm;
+  nsRefPtr<PlatformDecoderModule> pdm;
   if ((!cdmDecodesAudio && aHasAudio) || (!cdmDecodesVideo && aHasVideo)) {
     // The CDM itself can't decode. We need to wrap a PDM to decode the
     // decrypted output of the CDM.
     pdm = Create();
     if (!pdm) {
       return nullptr;
     }
   }
 
-  return new EMEDecoderModule(aProxy,
-                              pdm.forget(),
-                              cdmDecodesAudio,
-                              cdmDecodesVideo);
+  nsRefPtr<PlatformDecoderModule> emepdm(new EMEDecoderModule(aProxy,
+                                                              pdm,
+                                                              cdmDecodesAudio,
+                                                              cdmDecodesVideo));
+  return emepdm.forget();
 }
 #endif
 
 /* static */
-PlatformDecoderModule*
+already_AddRefed<PlatformDecoderModule>
 PlatformDecoderModule::Create()
 {
   // Note: This runs on the decode thread.
   MOZ_ASSERT(!NS_IsMainThread());
 
 #ifdef MOZ_WIDGET_ANDROID
   if(sAndroidMCDecoderPreferred && sAndroidMCDecoderEnabled){
-    return new AndroidDecoderModule();
+    nsRefPtr<PlatformDecoderModule> m(new AndroidDecoderModule());
+    return m.forget();
   }
 #endif
   if (sUseBlankDecoder) {
     return CreateBlankDecoderModule();
   }
 #ifdef XP_WIN
-  nsAutoPtr<WMFDecoderModule> m(new WMFDecoderModule());
+  nsRefPtr<WMFDecoderModule> m(new WMFDecoderModule());
   if (NS_SUCCEEDED(m->Startup())) {
     return m.forget();
   }
 #endif
 #ifdef MOZ_FFMPEG
   if (sFFmpegDecoderEnabled) {
-    nsAutoPtr<PlatformDecoderModule> m(FFmpegRuntimeLinker::CreateDecoderModule());
+    nsRefPtr<PlatformDecoderModule> m(FFmpegRuntimeLinker::CreateDecoderModule());
     if (m) {
       return m.forget();
     }
   }
 #endif
 #ifdef MOZ_APPLEMEDIA
-  nsAutoPtr<AppleDecoderModule> m(new AppleDecoderModule());
+  nsRefPtr<AppleDecoderModule> m(new AppleDecoderModule());
   if (NS_SUCCEEDED(m->Startup())) {
     return m.forget();
   }
 #endif
 #ifdef MOZ_GONK_MEDIACODEC
   if (sGonkDecoderEnabled) {
-    return new GonkDecoderModule();
+    nsRefPtr<PlatformDecoderModule> m(new GonkDecoderModule());
+    return m.forget();
   }
 #endif
 #ifdef MOZ_WIDGET_ANDROID
   if(sAndroidMCDecoderEnabled){
-    return new AndroidDecoderModule();
+    nsRefPtr<PlatformDecoderModule> m(new AndroidDecoderModule());
+    return m.forget();
   }
 #endif
   return nullptr;
 }
 
 bool
 PlatformDecoderModule::SupportsAudioMimeType(const char* aMimeType)
 {
--- a/dom/media/fmp4/PlatformDecoderModule.h
+++ b/dom/media/fmp4/PlatformDecoderModule.h
@@ -49,38 +49,41 @@ typedef int64_t Microseconds;
 // means that we won't have fragmented MP4 supported in Media Source
 // Extensions.
 //
 // A cross-platform decoder module that discards input and produces "blank"
 // output samples exists for testing, and is created when the pref
 // "media.fragmented-mp4.use-blank-decoder" is true.
 class PlatformDecoderModule {
 public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PlatformDecoderModule)
+
   // Call on the main thread to initialize the static state
   // needed by Create().
   static void Init();
 
   // Factory method that creates the appropriate PlatformDecoderModule for
   // the platform we're running on. Caller is responsible for deleting this
   // instance. It's expected that there will be multiple
   // PlatformDecoderModules alive at the same time. There is one
   // PlatformDecoderModule created per MP4Reader.
   // This is called on the decode task queue.
-  static PlatformDecoderModule* Create();
+  static already_AddRefed<PlatformDecoderModule> Create();
 
 #ifdef MOZ_EME
   // Creates a PlatformDecoderModule that uses a CDMProxy to decrypt or
   // decrypt-and-decode EME encrypted content. If the CDM only decrypts and
   // does not decode, we create a PDM and use that to create MediaDataDecoders
   // that we use on on aTaskQueue to decode the decrypted stream.
   // This is called on the decode task queue.
-  static PlatformDecoderModule* CreateCDMWrapper(CDMProxy* aProxy,
-                                                 bool aHasAudio,
-                                                 bool aHasVideo,
-                                                 MediaTaskQueue* aTaskQueue);
+  static already_AddRefed<PlatformDecoderModule>
+  CreateCDMWrapper(CDMProxy* aProxy,
+                   bool aHasAudio,
+                   bool aHasVideo,
+                   MediaTaskQueue* aTaskQueue);
 #endif
 
   // Called to shutdown the decoder module and cleanup state. The PDM
   // is deleted immediately after Shutdown() is called. Shutdown() is
   // called after Shutdown() has been called on all MediaDataDecoders
   // created from this PlatformDecoderModule.
   // This is called on the decode task queue.
   virtual nsresult Shutdown() = 0;
@@ -119,20 +122,19 @@ public:
                      MediaDataDecoderCallback* aCallback) = 0;
 
   // An audio decoder module must support AAC by default.
   // If more audio codec is to be supported, SupportsAudioMimeType will have
   // to be extended
   virtual bool SupportsAudioMimeType(const char* aMimeType);
   virtual bool SupportsVideoMimeType(const char* aMimeType);
 
-  virtual ~PlatformDecoderModule() {}
-
 protected:
   PlatformDecoderModule() {}
+  virtual ~PlatformDecoderModule() {}
   // Caches pref media.fragmented-mp4.use-blank-decoder
   static bool sUseBlankDecoder;
   static bool sFFmpegDecoderEnabled;
   static bool sGonkDecoderEnabled;
   static bool sAndroidMCDecoderPreferred;
   static bool sAndroidMCDecoderEnabled;
 };
 
--- a/dom/media/fmp4/SharedDecoderManager.cpp
+++ b/dom/media/fmp4/SharedDecoderManager.cpp
@@ -67,17 +67,17 @@ SharedDecoderManager::~SharedDecoderMana
 
 already_AddRefed<MediaDataDecoder>
 SharedDecoderManager::CreateVideoDecoder(
   const mp4_demuxer::VideoDecoderConfig& aConfig,
   layers::LayersBackend aLayersBackend, layers::ImageContainer* aImageContainer,
   MediaTaskQueue* aVideoTaskQueue, MediaDataDecoderCallback* aCallback)
 {
   if (!mDecoder) {
-    nsAutoPtr<PlatformDecoderModule> platform(PlatformDecoderModule::Create());
+    nsRefPtr<PlatformDecoderModule> platform(PlatformDecoderModule::Create());
     mDecoder = platform->CreateVideoDecoder(
       aConfig, aLayersBackend, aImageContainer, aVideoTaskQueue, mCallback);
     if (!mDecoder) {
       return nullptr;
     }
     nsresult rv = mDecoder->Init();
     NS_ENSURE_SUCCESS(rv, nullptr);
   }
--- a/dom/media/fmp4/eme/EMEDecoderModule.h
+++ b/dom/media/fmp4/eme/EMEDecoderModule.h
@@ -43,17 +43,17 @@ public:
   virtual already_AddRefed<MediaDataDecoder>
   CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
                      MediaTaskQueue* aAudioTaskQueue,
                      MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
 private:
   nsRefPtr<CDMProxy> mProxy;
   // Will be null if CDM has decoding capability.
-  nsAutoPtr<PlatformDecoderModule> mPDM;
+  nsRefPtr<PlatformDecoderModule> mPDM;
   // We run the PDM on its own task queue.
   nsRefPtr<MediaTaskQueue> mTaskQueue;
   bool mCDMDecodesAudio;
   bool mCDMDecodesVideo;
 
 };
 
 } // namespace mozilla
--- a/dom/media/fmp4/ffmpeg/FFmpegDecoderModule.h
+++ b/dom/media/fmp4/ffmpeg/FFmpegDecoderModule.h
@@ -13,17 +13,22 @@
 
 namespace mozilla
 {
 
 template <int V>
 class FFmpegDecoderModule : public PlatformDecoderModule
 {
 public:
-  static PlatformDecoderModule* Create() { return new FFmpegDecoderModule(); }
+  static already_AddRefed<PlatformDecoderModule>
+  Create()
+  {
+    nsRefPtr<PlatformDecoderModule> pdm = new FFmpegDecoderModule();
+    return pdm.forget();
+  }
 
   FFmpegDecoderModule() {}
   virtual ~FFmpegDecoderModule() {}
 
   virtual nsresult Shutdown() MOZ_OVERRIDE { return NS_OK; }
 
   virtual already_AddRefed<MediaDataDecoder>
   CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
@@ -52,13 +57,14 @@ public:
   {
     return FFmpegAudioDecoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
   }
 
   virtual bool SupportsVideoMimeType(const char* aMimeType) MOZ_OVERRIDE
   {
     return FFmpegH264Decoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
   }
+
 };
 
 } // namespace mozilla
 
 #endif // __FFmpegDecoderModule_h__
--- a/dom/media/fmp4/ffmpeg/FFmpegRuntimeLinker.cpp
+++ b/dom/media/fmp4/ffmpeg/FFmpegRuntimeLinker.cpp
@@ -16,24 +16,24 @@ namespace mozilla
 {
 
 FFmpegRuntimeLinker::LinkStatus FFmpegRuntimeLinker::sLinkStatus =
   LinkStatus_INIT;
 
 struct AvFormatLib
 {
   const char* Name;
-  PlatformDecoderModule* (*Factory)();
+  already_AddRefed<PlatformDecoderModule> (*Factory)();
   uint32_t Version;
 };
 
 template <int V> class FFmpegDecoderModule
 {
 public:
-  static PlatformDecoderModule* Create();
+  static already_AddRefed<PlatformDecoderModule> Create();
 };
 
 static const AvFormatLib sLibs[] = {
   { "libavformat.so.56", FFmpegDecoderModule<55>::Create, 55 },
   { "libavformat.so.55", FFmpegDecoderModule<55>::Create, 55 },
   { "libavformat.so.54", FFmpegDecoderModule<54>::Create, 54 },
   { "libavformat.so.53", FFmpegDecoderModule<53>::Create, 53 },
   { "libavformat.56.dylib", FFmpegDecoderModule<55>::Create, 55 },
@@ -96,24 +96,24 @@ FFmpegRuntimeLinker::Bind(const char* aL
     }                                                                          \
   }
 #include "FFmpegFunctionList.h"
 #undef AV_FUNC
 #undef LIBAVCODEC_ALLVERSION
   return true;
 }
 
-/* static */ PlatformDecoderModule*
+/* static */ already_AddRefed<PlatformDecoderModule>
 FFmpegRuntimeLinker::CreateDecoderModule()
 {
   if (!Link()) {
     return nullptr;
   }
-  PlatformDecoderModule* module = sLib->Factory();
-  return module;
+  nsRefPtr<PlatformDecoderModule> module = sLib->Factory();
+  return module.forget();
 }
 
 /* static */ void
 FFmpegRuntimeLinker::Unlink()
 {
   if (sLinkedLib) {
     dlclose(sLinkedLib);
     sLinkedLib = nullptr;
--- a/dom/media/fmp4/ffmpeg/FFmpegRuntimeLinker.h
+++ b/dom/media/fmp4/ffmpeg/FFmpegRuntimeLinker.h
@@ -2,30 +2,30 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __FFmpegRuntimeLinker_h__
 #define __FFmpegRuntimeLinker_h__
 
+#include "PlatformDecoderModule.h"
 #include <stdint.h>
 
 namespace mozilla
 {
 
-class PlatformDecoderModule;
 struct AvFormatLib;
 
 class FFmpegRuntimeLinker
 {
 public:
   static bool Link();
   static void Unlink();
-  static PlatformDecoderModule* CreateDecoderModule();
+  static already_AddRefed<PlatformDecoderModule> CreateDecoderModule();
 
 private:
   static void* sLinkedLib;
   static const AvFormatLib* sLib;
 
   static bool Bind(const char* aLibName, uint32_t Version);
 
   static enum LinkStatus {
--- a/dom/media/webm/IntelWebMVideoDecoder.h
+++ b/dom/media/webm/IntelWebMVideoDecoder.h
@@ -54,17 +54,17 @@ private:
 
   bool SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed);
 
   bool IsSupportedVideoMimeType(const char* aMimeType);
 
   VP8Sample* PopSample();
 
   nsRefPtr<WebMReader> mReader;
-  nsAutoPtr<PlatformDecoderModule> mPlatform;
+  nsRefPtr<PlatformDecoderModule> mPlatform;
   nsRefPtr<MediaDataDecoder> mMediaDataDecoder;
 
   // TaskQueue on which decoder can choose to decode.
   // Only non-null up until the decoder is created.
   nsRefPtr<MediaTaskQueue> mTaskQueue;
 
   // Monitor that protects all non-threadsafe state; the primitives
   // that follow.