Bug 1271491: P6. Remove the need to call PDMFactory::Init(). r=cpearce
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 12 May 2016 18:54:35 +1000
changeset 336353 91217b1ad73645e2ab85e5ff8f14239027c87486
parent 336352 30e33b58645e4fc094fb8fec341f78b1ac41ed5c
child 336354 65a7900758687be24170ee0bacbccf86d4b5e857
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1271491
milestone49.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 1271491: P6. Remove the need to call PDMFactory::Init(). r=cpearce PDMFactory will automatically load and initialize the required frameworks upon first use. Also fix constness of some methods. MozReview-Commit-ID: HFbvTMRFAey
dom/media/ADTSDecoder.cpp
dom/media/Benchmark.cpp
dom/media/MP3Decoder.cpp
dom/media/MediaFormatReader.cpp
dom/media/fmp4/MP4Decoder.cpp
dom/media/platforms/PDMFactory.cpp
dom/media/platforms/PDMFactory.h
dom/media/wave/WaveDecoder.cpp
--- a/dom/media/ADTSDecoder.cpp
+++ b/dom/media/ADTSDecoder.cpp
@@ -27,17 +27,16 @@ ADTSDecoder::CreateStateMachine()
   RefPtr<MediaDecoderReader> reader =
       new MediaFormatReader(this, new ADTSDemuxer(GetResource()));
   return new MediaDecoderStateMachine(this, reader);
 }
 
 /* static */ bool
 ADTSDecoder::IsEnabled()
 {
-  PDMFactory::Init();
   RefPtr<PDMFactory> platform = new PDMFactory();
   return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/mp4a-latm"),
                                     /* DecoderDoctorDiagnostics* */ nullptr);
 }
 
 /* static */ bool
 ADTSDecoder::CanHandleMediaType(const nsACString& aType,
                                 const nsAString& aCodecs)
--- a/dom/media/Benchmark.cpp
+++ b/dom/media/Benchmark.cpp
@@ -2,16 +2,17 @@
 /* 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/. */
 
 #include "Benchmark.h"
 #include "BufferMediaResource.h"
 #include "MediaData.h"
+#include "MediaPrefs.h"
 #include "PDMFactory.h"
 #include "WebMDemuxer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/ContentChild.h"
 
 #ifndef MOZ_WIDGET_ANDROID
 #include "WebMSample.h"
@@ -40,18 +41,16 @@ VP9Benchmark::IsVP9DecodeFast()
   uint32_t hadRecentUpdate = Preferences::GetUint(sBenchmarkFpsVersionCheck, 0U);
 
   if (!sHasRunTest && (!hasPref || hadRecentUpdate != sBenchmarkVersionID)) {
     sHasRunTest = true;
 
     RefPtr<WebMDemuxer> demuxer =
       new WebMDemuxer(new BufferMediaResource(sWebMSample, sizeof(sWebMSample), nullptr,
                                               NS_LITERAL_CSTRING("video/webm")));
-    PDMFactory::Init();
-
     RefPtr<Benchmark> estimiser =
       new Benchmark(demuxer,
                     {
                       Preferences::GetInt("media.benchmark.frames", 300), // frames to measure
                       1, // start benchmarking after decoding this frame.
                       8, // loop after decoding that many frames.
                       TimeDuration::FromMilliseconds(
                         Preferences::GetUint("media.benchmark.timeout", 1000))
@@ -130,17 +129,17 @@ Benchmark::Dispose()
   mPromise.RejectIfExists(false, __func__);
 }
 
 void
 Benchmark::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  PDMFactory::Init();
+  MediaPrefs::GetSingleton();
 }
 
 BenchmarkPlayback::BenchmarkPlayback(Benchmark* aMainThreadState,
                                      MediaDataDemuxer* aDemuxer)
   : QueueObject(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK)))
   , mMainThreadState(aMainThreadState)
   , mDecoderTaskQueue(new FlushableTaskQueue(GetMediaThreadPool(
                         MediaThreadType::PLATFORM_DECODER)))
--- a/dom/media/MP3Decoder.cpp
+++ b/dom/media/MP3Decoder.cpp
@@ -26,17 +26,16 @@ MP3Decoder::CreateStateMachine() {
   RefPtr<MediaDecoderReader> reader =
       new MediaFormatReader(this, new mp3::MP3Demuxer(GetResource()));
   return new MediaDecoderStateMachine(this, reader);
 }
 
 /* static */
 bool
 MP3Decoder::IsEnabled() {
-  PDMFactory::Init();
   RefPtr<PDMFactory> platform = new PDMFactory();
   return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/mpeg"),
                                     /* DecoderDoctorDiagnostics* */ nullptr);
 }
 
 /* static */
 bool MP3Decoder::CanHandleMediaType(const nsACString& aType,
                                     const nsAString& aCodecs)
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -167,17 +167,16 @@ MediaFormatReader::InitLayersBackendType
 
   mLayersBackendType = layerManager->GetCompositorBackendType();
 }
 
 nsresult
 MediaFormatReader::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
-  PDMFactory::Init();
 
   InitLayersBackendType();
 
   mAudio.mTaskQueue =
     new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   mVideo.mTaskQueue =
     new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
 
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -146,17 +146,16 @@ MP4Decoder::CanHandleMediaType(const nsA
         continue;
       }
       // Some unsupported codec.
       return false;
     }
   }
 
   // Verify that we have a PDM that supports the whitelisted types.
-  PDMFactory::Init();
   RefPtr<PDMFactory> platform = new PDMFactory();
   for (const nsCString& codecMime : codecMimes) {
     if (!platform->SupportsMimeType(codecMime, aDiagnostics)) {
       return false;
     }
   }
 
   return true;
@@ -225,18 +224,16 @@ CreateTestH264Decoder(layers::LayersBack
   aConfig.mId = 1;
   aConfig.mDuration = 40000;
   aConfig.mMediaTime = 0;
   aConfig.mImage = aConfig.mDisplay = nsIntSize(640, 360);
   aConfig.mExtraData = new MediaByteBuffer();
   aConfig.mExtraData->AppendElements(sTestH264ExtraData,
                                      MOZ_ARRAY_LENGTH(sTestH264ExtraData));
 
-  PDMFactory::Init();
-
   RefPtr<PDMFactory> platform = new PDMFactory();
   RefPtr<MediaDataDecoder> decoder(
     platform->CreateDecoder(aConfig, aTaskQueue, nullptr,
                             /* DecoderDoctorDiagnostics* */ nullptr,
                             aBackend, nullptr));
 
   return decoder.forget();
 }
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -21,84 +21,97 @@
 #ifdef MOZ_GONK_MEDIACODEC
 #include "GonkDecoderModule.h"
 #endif
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidDecoderModule.h"
 #endif
 #include "GMPDecoderModule.h"
 
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/SharedThreadPool.h"
+#include "mozilla/StaticPtr.h"
 #include "mozilla/TaskQueue.h"
 
-#include "mozilla/SharedThreadPool.h"
-
 #include "MediaInfo.h"
 #include "MediaPrefs.h"
 #include "FuzzingWrapper.h"
 #include "H264Converter.h"
 
 #include "AgnosticDecoderModule.h"
 
 #ifdef MOZ_EME
 #include "EMEDecoderModule.h"
 #include "mozilla/CDMProxy.h"
 #endif
 
 #include "DecoderDoctorDiagnostics.h"
 
+
 namespace mozilla {
 
 extern already_AddRefed<PlatformDecoderModule> CreateAgnosticDecoderModule();
 extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
 
-/* static */
-void
-PDMFactory::Init()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  static bool alreadyInitialized = false;
-  if (alreadyInitialized) {
-    return;
-  }
-  alreadyInitialized = true;
-
-  // Ensure MediaPrefs are initialized.
-  MediaPrefs::GetSingleton();
-
+class PDMFactoryImpl final {
+public:
+  PDMFactoryImpl()
+  {
 #ifdef XP_WIN
-  WMFDecoderModule::Init();
+    WMFDecoderModule::Init();
 #endif
 #ifdef MOZ_APPLEMEDIA
-  AppleDecoderModule::Init();
+    AppleDecoderModule::Init();
 #endif
 #ifdef MOZ_FFVPX
-  FFVPXRuntimeLinker::Init();
+    FFVPXRuntimeLinker::Init();
 #endif
 #ifdef MOZ_FFMPEG
-  FFmpegRuntimeLinker::Init();
+    FFmpegRuntimeLinker::Init();
 #endif
-  GMPDecoderModule::Init();
-}
+    GMPDecoderModule::Init();
+  }
+};
+
+StaticAutoPtr<PDMFactoryImpl> PDMFactory::sInstance;
+StaticMutex PDMFactory::sMonitor;
 
 PDMFactory::PDMFactory()
 {
+  EnsureInit();
   CreatePDMs();
 }
 
 PDMFactory::~PDMFactory()
 {
 }
 
+void
+PDMFactory::EnsureInit() const
+{
+  StaticMutexAutoLock mon(sMonitor);
+  if (!sInstance) {
+    sInstance = new PDMFactoryImpl();
+    if (NS_IsMainThread()) {
+      ClearOnShutdown(&sInstance);
+    } else {
+      nsCOMPtr<nsIRunnable> runnable =
+        NS_NewRunnableFunction([]() { ClearOnShutdown(&sInstance); });
+      NS_DispatchToMainThread(runnable);
+    }
+  }
+}
+
 already_AddRefed<MediaDataDecoder>
 PDMFactory::CreateDecoder(const TrackInfo& aConfig,
                           FlushableTaskQueue* aTaskQueue,
                           MediaDataDecoderCallback* aCallback,
                           DecoderDoctorDiagnostics* aDiagnostics,
                           layers::LayersBackend aLayersBackend,
-                          layers::ImageContainer* aImageContainer)
+                          layers::ImageContainer* aImageContainer) const
 {
   bool isEncrypted = mEMEPDM && aConfig.mCrypto.mValid;
 
   if (isEncrypted) {
     return CreateDecoderWithPDM(mEMEPDM,
                                 aConfig,
                                 aTaskQueue,
                                 aCallback,
@@ -143,17 +156,17 @@ PDMFactory::CreateDecoder(const TrackInf
 
 already_AddRefed<MediaDataDecoder>
 PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM,
                                  const TrackInfo& aConfig,
                                  FlushableTaskQueue* aTaskQueue,
                                  MediaDataDecoderCallback* aCallback,
                                  DecoderDoctorDiagnostics* aDiagnostics,
                                  layers::LayersBackend aLayersBackend,
-                                 layers::ImageContainer* aImageContainer)
+                                 layers::ImageContainer* aImageContainer) const
 {
   MOZ_ASSERT(aPDM);
   RefPtr<MediaDataDecoder> m;
 
   if (aConfig.GetAsAudioInfo()) {
     m = aPDM->CreateAudioDecoder(*aConfig.GetAsAudioInfo(),
                                  aTaskQueue,
                                  aCallback,
--- a/dom/media/platforms/PDMFactory.h
+++ b/dom/media/platforms/PDMFactory.h
@@ -3,45 +3,44 @@
 /* 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/. */
 
 #if !defined(PDMFactory_h_)
 #define PDMFactory_h_
 
 #include "PlatformDecoderModule.h"
+#include "mozilla/StaticMutex.h"
 
 class CDMProxy;
 
 namespace mozilla {
 
 class DecoderDoctorDiagnostics;
+class PDMFactoryImpl;
+template<class T> class StaticAutoPtr;
 
 class PDMFactory final {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PDMFactory)
 
   PDMFactory();
 
-  // 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.
   // This is called on the decode task queue.
   already_AddRefed<MediaDataDecoder>
   CreateDecoder(const TrackInfo& aConfig,
                 FlushableTaskQueue* aTaskQueue,
                 MediaDataDecoderCallback* aCallback,
                 DecoderDoctorDiagnostics* aDiagnostics,
                 layers::LayersBackend aLayersBackend = layers::LayersBackend::LAYERS_NONE,
-                layers::ImageContainer* aImageContainer = nullptr);
+                layers::ImageContainer* aImageContainer = nullptr) const;
 
   bool SupportsMimeType(const nsACString& aMimeType,
                         DecoderDoctorDiagnostics* aDiagnostics) const;
 
 #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
@@ -62,21 +61,26 @@ private:
 
   already_AddRefed<MediaDataDecoder>
   CreateDecoderWithPDM(PlatformDecoderModule* aPDM,
                        const TrackInfo& aConfig,
                        FlushableTaskQueue* aTaskQueue,
                        MediaDataDecoderCallback* aCallback,
                        DecoderDoctorDiagnostics* aDiagnostics,
                        layers::LayersBackend aLayersBackend,
-                       layers::ImageContainer* aImageContainer);
+                       layers::ImageContainer* aImageContainer) const;
 
   nsTArray<RefPtr<PlatformDecoderModule>> mCurrentPDMs;
   RefPtr<PlatformDecoderModule> mEMEPDM;
 
   bool mWMFFailedToLoad = false;
   bool mFFmpegFailedToLoad = false;
   bool mGMPPDMFailedToStartup = false;
+
+  void EnsureInit() const;
+  template<class T> friend class StaticAutoPtr;
+  static StaticAutoPtr<PDMFactoryImpl> sInstance;
+  static StaticMutex sMonitor;
 };
 
 } // namespace mozilla
 
 #endif /* PDMFactory_h_ */
--- a/dom/media/wave/WaveDecoder.cpp
+++ b/dom/media/wave/WaveDecoder.cpp
@@ -35,17 +35,16 @@ WaveDecoder::CreateStateMachine()
 /* static */
 bool
 WaveDecoder::IsEnabled()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!Preferences::GetBool("media.wave.decoder.enabled", false)) {
     return false;
   }
-  PDMFactory::Init();
   RefPtr<PDMFactory> platform = new PDMFactory();
   return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/x-wav"),
                                     /* DecoderDoctorDiagnostics* */ nullptr);
 }
 
 /* static */
 bool
 WaveDecoder::CanHandleMediaType(const nsACString& aType,