Bug 1160321 - Test whether we can create H.264/AAC decoders before we report we support them. r=mattwoodrow
☠☠ backed out by 595411569f1a ☠ ☠
authorChris Pearce <cpearce@mozilla.com>
Wed, 06 May 2015 11:40:45 +1200
changeset 273867 dbb002daa4558032d5b61e544f241f9eea2a4487
parent 273866 0d4307edffc2eb28ceb06b64bd5eed0c84f88f29
child 273868 674495f6c7604f38149461ec871203584b9628d1
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1160321
milestone40.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 1160321 - Test whether we can create H.264/AAC decoders before we report we support them. r=mattwoodrow
dom/base/nsDOMWindowUtils.cpp
dom/media/eme/MediaKeySystemAccess.cpp
dom/media/fmp4/MP4Decoder.cpp
dom/media/fmp4/MP4Decoder.h
dom/media/fmp4/MP4Reader.cpp
dom/media/fmp4/MP4Reader.h
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -21,17 +21,17 @@
 #include "mozilla/dom/Touch.h"
 #include "mozilla/PendingAnimationTracker.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsFrame.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "ClientLayerManager.h"
 #include "nsQueryObject.h"
 #ifdef MOZ_FMP4
-#include "MP4Reader.h"
+#include "MP4Decoder.h"
 #endif
 
 #include "nsIScrollableFrame.h"
 
 #include "nsContentUtils.h"
 
 #include "nsIFrame.h"
 #include "nsIWidget.h"
@@ -2248,17 +2248,17 @@ nsDOMWindowUtils::GetSupportsHardwareH26
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   LayerManager *mgr = widget->GetLayerManager();
   if (!mgr)
     return NS_ERROR_FAILURE;
 
-  *retval = MP4Reader::IsVideoAccelerated(mgr->GetCompositorBackendType());
+  *retval = MP4Decoder::IsVideoAccelerated(mgr->GetCompositorBackendType());
 #else
   *retval = false;
 #endif
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::StartFrameTimeRecording(uint32_t *startIndex)
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -156,17 +156,18 @@ MediaKeySystemAccess::GetKeySystemStatus
        aKeySystem.EqualsLiteral("com.adobe.primetime"))) {
     // Win Vista and later only.
     if (!IsVistaOrLater()) {
       return MediaKeySystemStatus::Cdm_not_supported;
     }
     if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) {
       return MediaKeySystemStatus::Cdm_disabled;
     }
-    if ((!WMFDecoderModule::HasH264() || !WMFDecoderModule::HasAAC()) ||
+    if (!MP4Decoder::CanCreateH264Decoder() ||
+        !MP4Decoder::CanCreateAACDecoder() ||
         !EMEVoucherFileExists()) {
       // The system doesn't have the codecs that Adobe EME relies
       // on installed, or doesn't have a voucher for the plugin-container.
       // Adobe EME isn't going to work, so don't advertise that it will.
       return MediaKeySystemStatus::Cdm_not_supported;
     }
     return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, true);
   }
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -23,16 +23,17 @@
 #endif
 #ifdef MOZ_APPLEMEDIA
 #include "apple/AppleDecoderModule.h"
 #endif
 #ifdef MOZ_WIDGET_ANDROID
 #include "nsIGfxInfo.h"
 #include "AndroidBridge.h"
 #endif
+#include "mozilla/layers/LayersTypes.h"
 
 namespace mozilla {
 
 MediaDecoderStateMachine* MP4Decoder::CreateStateMachine()
 {
   return new MediaDecoderStateMachine(this, new MP4Reader(this));
 }
 
@@ -59,22 +60,16 @@ static bool
 IsSupportedAudioCodec(const nsAString& aCodec,
                       bool& aOutContainsAAC,
                       bool& aOutContainsMP3)
 {
   // AAC-LC or HE-AAC in M4A.
   aOutContainsAAC = aCodec.EqualsASCII("mp4a.40.2") ||
                     aCodec.EqualsASCII("mp4a.40.5");
   if (aOutContainsAAC) {
-#ifdef XP_WIN
-    if (!Preferences::GetBool("media.fragmented-mp4.use-blank-decoder") &&
-        !WMFDecoderModule::HasAAC()) {
-      return false;
-    }
-#endif
     return true;
   }
 #ifndef MOZ_GONK_MEDIACODEC // B2G doesn't support MP3 in MP4 yet.
   aOutContainsMP3 = aCodec.EqualsASCII("mp3");
   if (aOutContainsMP3) {
     return true;
   }
 #else
@@ -88,21 +83,16 @@ IsSupportedH264Codec(const nsAString& aC
 {
   int16_t profile = 0, level = 0;
 
   if (!ExtractH264CodecDetails(aCodec, profile, level)) {
     return false;
   }
 
 #ifdef XP_WIN
-  if (!Preferences::GetBool("media.fragmented-mp4.use-blank-decoder") &&
-      !WMFDecoderModule::HasH264()) {
-    return false;
-  }
-
   // Disable 4k video on windows vista since it performs poorly.
   if (!IsWin7OrLater() &&
       level >= H264_LEVEL_5) {
     return false;
   }
 #endif
 
   // Just assume what we can play on all platforms the codecs/formats that
@@ -129,23 +119,25 @@ MP4Decoder::CanHandleMediaType(const nsA
                                bool& aOutContainsH264,
                                bool& aOutContainsMP3)
 {
   if (!IsEnabled()) {
     return false;
   }
 
   if (aType.EqualsASCII("audio/mp4") || aType.EqualsASCII("audio/x-m4a")) {
-    return aCodecs.IsEmpty() ||
-           IsSupportedAudioCodec(aCodecs,
-                                 aOutContainsAAC,
-                                 aOutContainsMP3);
+    return MP4Decoder::CanCreateAACDecoder() &&
+           (aCodecs.IsEmpty() ||
+            IsSupportedAudioCodec(aCodecs,
+                                  aOutContainsAAC,
+                                  aOutContainsMP3));
   }
 
-  if (!aType.EqualsASCII("video/mp4")) {
+  if (!aType.EqualsASCII("video/mp4") ||
+      !MP4Decoder::CanCreateH264Decoder()) {
     return false;
   }
 
   // Verify that all the codecs specifed are ones that we expect that
   // we can play.
   nsCharSeparatedTokenizer tokenizer(aCodecs, ',');
   bool expectMoreTokens = false;
   while (tokenizer.hasMoreTokens()) {
@@ -248,10 +240,138 @@ HavePlatformMPEGDecoders()
 /* static */
 bool
 MP4Decoder::IsEnabled()
 {
   return Preferences::GetBool("media.fragmented-mp4.enabled") &&
          HavePlatformMPEGDecoders();
 }
 
+static const uint8_t sTestH264ExtraData[] = {
+  0x01, 0x64, 0x00, 0x0a, 0xff, 0xe1, 0x00, 0x17, 0x67, 0x64,
+  0x00, 0x0a, 0xac, 0xd9, 0x44, 0x26, 0x84, 0x00, 0x00, 0x03,
+  0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc8, 0x3c, 0x48, 0x96,
+  0x58, 0x01, 0x00, 0x06, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0
+};
+
+static already_AddRefed<MediaDataDecoder>
+CreateTestH264Decoder(layers::LayersBackend aBackend,
+                      VideoInfo& aConfig)
+{
+  aConfig.mMimeType = "video/avc";
+  aConfig.mId = 1;
+  aConfig.mDuration = 40000;
+  aConfig.mMediaTime = 0;
+  aConfig.mDisplay = aConfig.mImage = nsIntSize(64, 64);
+  aConfig.mExtraData = new MediaByteBuffer();
+  aConfig.mExtraData->AppendElements(sTestH264ExtraData,
+                                     MOZ_ARRAY_LENGTH(sTestH264ExtraData));
+
+  PlatformDecoderModule::Init();
+
+  nsRefPtr<PlatformDecoderModule> platform = PlatformDecoderModule::Create();
+  if (!platform) {
+    return nullptr;
+  }
+
+  nsRefPtr<MediaDataDecoder> decoder(
+    platform->CreateDecoder(aConfig, nullptr, nullptr, aBackend, nullptr));
+  if (!decoder) {
+    return nullptr;
+  }
+  nsresult rv = decoder->Init();
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  return decoder.forget();
+}
+
+/* static */ bool
+MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend)
+{
+  VideoInfo config;
+  nsRefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aBackend, config));
+  if (!decoder) {
+    return false;
+  }
+  bool result = decoder->IsHardwareAccelerated();
+  decoder->Shutdown();
+  return result;
+}
+
+/* static */ bool
+MP4Decoder::CanCreateH264Decoder()
+{
+  static bool haveCachedResult = false;
+  static bool result = false;
+  if (haveCachedResult) {
+    return result;
+  }
+  VideoInfo config;
+  nsRefPtr<MediaDataDecoder> decoder(
+    CreateTestH264Decoder(layers::LayersBackend::LAYERS_BASIC, config));
+  if (decoder) {
+    decoder->Shutdown();
+    result = true;
+  }
+  haveCachedResult = true;
+  return result;
+}
+
+static already_AddRefed<MediaDataDecoder>
+CreateTestAACDecoder(AudioInfo& aConfig)
+{
+  PlatformDecoderModule::Init();
+
+  nsRefPtr<PlatformDecoderModule> platform = PlatformDecoderModule::Create();
+  if (!platform) {
+    return nullptr;
+  }
+
+  nsRefPtr<MediaDataDecoder> decoder(
+    platform->CreateDecoder(aConfig, nullptr, nullptr));
+  if (!decoder) {
+    return nullptr;
+  }
+  nsresult rv = decoder->Init();
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  return decoder.forget();
+}
+
+// bipbop.mp4's extradata/config...
+static const uint8_t sTestAACExtraData[] = {
+  0x03, 0x80, 0x80, 0x80, 0x22, 0x00, 0x02, 0x00, 0x04, 0x80,
+  0x80, 0x80, 0x14, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x11, 0x51, 0x00, 0x00, 0x11, 0x51, 0x05, 0x80, 0x80, 0x80,
+  0x02, 0x13, 0x90, 0x06, 0x80, 0x80, 0x80, 0x01, 0x02
+};
+
+static const uint8_t sTestAACConfig[] = { 0x13, 0x90 };
+
+/* static */ bool
+MP4Decoder::CanCreateAACDecoder()
+{
+  static bool haveCachedResult = false;
+  static bool result = false;
+  if (haveCachedResult) {
+    return result;
+  }
+  AudioInfo config;
+  config.mMimeType = "audio/mp4a-latm";
+  config.mRate = 22050;
+  config.mChannels = 2;
+  config.mBitDepth = 16;
+  config.mProfile = 2;
+  config.mExtendedProfile = 2;
+  config.mCodecSpecificConfig->AppendElements(sTestAACConfig,
+                                              MOZ_ARRAY_LENGTH(sTestAACConfig));
+  config.mExtraData->AppendElements(sTestAACExtraData,
+                                    MOZ_ARRAY_LENGTH(sTestAACExtraData));
+  nsRefPtr<MediaDataDecoder> decoder(CreateTestAACDecoder(config));
+  if (decoder) {
+    decoder->Shutdown();
+    result = true;
+  }
+  haveCachedResult = true;
+  return result;
+}
+
 } // namespace mozilla
-
--- a/dom/media/fmp4/MP4Decoder.h
+++ b/dom/media/fmp4/MP4Decoder.h
@@ -36,13 +36,17 @@ public:
                                  const nsAString& aCodecs,
                                  bool& aOutContainsAAC,
                                  bool& aOutContainsH264,
                                  bool& aOutContainsMP3);
 
   // Returns true if the MP4 backend is preffed on, and we're running on a
   // platform that is likely to have decoders for the contained formats.
   static bool IsEnabled();
+
+  static bool IsVideoAccelerated(layers::LayersBackend aBackend);
+  static bool CanCreateAACDecoder();
+  static bool CanCreateH264Decoder();
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -68,53 +68,16 @@ TrackTypeToStr(TrackInfo::TrackType aTra
   case TrackInfo::kVideoTrack:
     return "Video";
   default:
     return "Unknown";
   }
 }
 #endif
 
-uint8_t sTestExtraData[40] = { 0x01, 0x64, 0x00, 0x0a, 0xff, 0xe1, 0x00, 0x17, 0x67, 0x64, 0x00, 0x0a, 0xac, 0xd9, 0x44, 0x26, 0x84, 0x00, 0x00, 0x03,
-                               0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc8, 0x3c, 0x48, 0x96, 0x58, 0x01, 0x00, 0x06, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0 };
-
-/* static */ bool
-MP4Reader::IsVideoAccelerated(LayersBackend aBackend)
-{
-  VideoInfo config;
-  config.mMimeType = "video/avc";
-  config.mId = 1;
-  config.mDuration = 40000;
-  config.mMediaTime = 0;
-  config.mDisplay = config.mImage = nsIntSize(64, 64);
-  config.mExtraData = new MediaByteBuffer();
-  config.mExtraData->AppendElements(sTestExtraData, 40);
-
-  PlatformDecoderModule::Init();
-
-  nsRefPtr<PlatformDecoderModule> platform = PlatformDecoderModule::Create();
-  if (!platform) {
-    return false;
-  }
-
-  nsRefPtr<MediaDataDecoder> decoder =
-    platform->CreateDecoder(config, nullptr, nullptr, aBackend, nullptr);
-  if (!decoder) {
-    return false;
-  }
-  nsresult rv = decoder->Init();
-  NS_ENSURE_SUCCESS(rv, false);
-
-  bool result = decoder->IsHardwareAccelerated();
-
-  decoder->Shutdown();
-
-  return result;
-}
-
 bool
 AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata)
 {
   SPSData spsdata;
   if (H264::DecodeSPSFromExtraData(aExtradata, spsdata)) {
    uint8_t constraints = (spsdata.constraint_set0_flag ? (1 << 0) : 0) |
                          (spsdata.constraint_set1_flag ? (1 << 1) : 0) |
                          (spsdata.constraint_set2_flag ? (1 << 2) : 0) |
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -82,18 +82,16 @@ public:
   virtual nsRefPtr<ShutdownPromise> Shutdown() override;
 
   virtual bool IsAsync() const override { return true; }
 
   virtual bool VideoIsHardwareAccelerated() const override;
 
   virtual void DisableHardwareAcceleration() override;
 
-  static bool IsVideoAccelerated(layers::LayersBackend aBackend);
-
 private:
 
   bool InitDemuxer();
   void ReturnOutput(MediaData* aData, TrackType aTrack);
 
   bool EnsureDecodersSetup();
 
   // Sends input to decoder for aTrack, and output to the state machine,