Bug 1330284 - Use MediaContentType in MP4Decoder - r?jya draft
authorGerald Squelart <gsquelart@mozilla.com>
Sun, 01 Jan 2017 12:27:45 +1100
changeset 460034 169efd15c0451d72fac7317a439d6064956804fa
parent 460033 31f563a4c8880073eb34e52e92147e58d276f2b0
child 460035 0dfc4ba6534f60021e8208893af9abe100fd4992
push id41348
push usergsquelart@mozilla.com
push dateThu, 12 Jan 2017 20:50:49 +0000
reviewersjya
bugs1330284
milestone53.0a1
Bug 1330284 - Use MediaContentType in MP4Decoder - r?jya MozReview-Commit-ID: 9Npl40Iicjc
dom/media/DecoderTraits.cpp
dom/media/DecoderTraits.h
dom/media/eme/MediaKeySystemAccess.cpp
dom/media/fmp4/MP4Decoder.cpp
dom/media/fmp4/MP4Decoder.h
dom/media/gtest/TestMediaDataDecoder.cpp
dom/media/mediasource/MediaSource.cpp
--- a/dom/media/DecoderTraits.cpp
+++ b/dom/media/DecoderTraits.cpp
@@ -96,41 +96,22 @@ IsAndroidMediaType(const nsACString& aTy
 #ifdef MOZ_DIRECTSHOW
 static bool
 IsDirectShowSupportedType(const nsACString& aType)
 {
   return DirectShowDecoder::GetSupportedCodecs(aType, nullptr);
 }
 #endif
 
-#ifdef MOZ_FMP4
-static bool
-IsMP4SupportedType(const MediaContentType& aParsedType,
-                   DecoderDoctorDiagnostics* aDiagnostics)
-{
-  return MP4Decoder::CanHandleMediaType(aParsedType, aDiagnostics);
-}
-static bool
-IsMP4SupportedType(const nsACString& aType,
-                   DecoderDoctorDiagnostics* aDiagnostics)
-{
-  Maybe<MediaContentType> contentType = MakeMediaContentType(aType);
-  if (!contentType) {
-    return false;
-  }
-  return IsMP4SupportedType(*contentType, aDiagnostics);
-}
-#endif
-
 /* static */ bool
-DecoderTraits::IsMP4TypeAndEnabled(const nsACString& aType,
-                                   DecoderDoctorDiagnostics* aDiagnostics)
+DecoderTraits::IsMP4SupportedType(const MediaContentType& aType,
+                                  DecoderDoctorDiagnostics* aDiagnostics)
 {
 #ifdef MOZ_FMP4
-  return IsMP4SupportedType(aType, aDiagnostics);
+  return MP4Decoder::IsSupportedType(aType, aDiagnostics);
 #else
   return false;
 #endif
 }
 
 static bool
 IsMP3SupportedType(const nsACString& aType,
                    const nsAString& aCodecs = EmptyString())
@@ -197,18 +178,19 @@ CanHandleCodecsType(const MediaContentTy
     } else {
       // We can only reach this position if a particular codec was requested,
       // webm is supported and working: the codec must be invalid.
       return CANPLAY_NO;
     }
   }
 #endif
 #ifdef MOZ_FMP4
-  if (DecoderTraits::IsMP4TypeAndEnabled(mimeType.Type().AsString(), aDiagnostics)) {
-    if (IsMP4SupportedType(aType, aDiagnostics)) {
+  if (MP4Decoder::IsSupportedType(mimeType,
+                                  /* DecoderDoctorDiagnostics* */ nullptr)) {
+    if (MP4Decoder::IsSupportedType(aType, aDiagnostics)) {
       return CANPLAY_YES;
     } else {
       // We can only reach this position if a particular codec was requested,
       // fmp4 is supported and working: the codec must be invalid.
       return CANPLAY_NO;
     }
   }
 #endif
@@ -281,19 +263,21 @@ CanHandleMediaType(const MediaContentTyp
   const MediaContentType mimeType(aType.Type());
 
   if (OggDecoder::IsSupportedType(mimeType)) {
     return CANPLAY_MAYBE;
   }
   if (IsWaveSupportedType(mimeType.Type().AsString())) {
     return CANPLAY_MAYBE;
   }
-  if (DecoderTraits::IsMP4TypeAndEnabled(mimeType.Type().AsString(), aDiagnostics)) {
+#ifdef MOZ_FMP4
+  if (MP4Decoder::IsSupportedType(mimeType, aDiagnostics)) {
     return CANPLAY_MAYBE;
   }
+#endif
 #if !defined(MOZ_OMX_WEBM_DECODER)
   if (WebMDecoder::IsSupportedType(mimeType)) {
     return CANPLAY_MAYBE;
   }
 #endif
   if (IsMP3SupportedType(mimeType.Type().AsString())) {
     return CANPLAY_MAYBE;
   }
@@ -363,17 +347,17 @@ already_AddRefed<MediaDecoder>
 InstantiateDecoder(const MediaContentType& aType,
                    MediaDecoderOwner* aOwner,
                    DecoderDoctorDiagnostics* aDiagnostics)
 {
   MOZ_ASSERT(NS_IsMainThread());
   RefPtr<MediaDecoder> decoder;
 
 #ifdef MOZ_FMP4
-  if (IsMP4SupportedType(aType.Type().AsString(), aDiagnostics)) {
+  if (MP4Decoder::IsSupportedType(aType, aDiagnostics)) {
     decoder = new MP4Decoder(aOwner);
     return decoder.forget();
   }
 #endif
   if (IsMP3SupportedType(aType.Type().AsString())) {
     decoder = new MP3Decoder(aOwner);
     return decoder.forget();
   }
@@ -448,17 +432,18 @@ MediaDecoderReader* DecoderTraits::Creat
     return decoderReader;
   }
   Maybe<MediaContentType> type = MakeMediaContentType(aType);
   if (!type) {
     return decoderReader;
   }
 
 #ifdef MOZ_FMP4
-  if (IsMP4SupportedType(aType, /* DecoderDoctorDiagnostics* */ nullptr)) {
+  if (MP4Decoder::IsSupportedType(*type,
+                                  /* DecoderDoctorDiagnostics* */ nullptr)) {
     decoderReader = new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()));
   } else
 #endif
   if (IsMP3SupportedType(aType)) {
     decoderReader = new MediaFormatReader(aDecoder, new mp3::MP3Demuxer(aDecoder->GetResource()));
   } else
   if (IsAACSupportedType(aType)) {
     decoderReader = new MediaFormatReader(aDecoder, new ADTSDemuxer(aDecoder->GetResource()));
@@ -510,17 +495,17 @@ bool DecoderTraits::IsSupportedInVideoDo
 
   return
     OggDecoder::IsSupportedType(*type) ||
     WebMDecoder::IsSupportedType(*type) ||
 #ifdef MOZ_ANDROID_OMX
     (MediaDecoder::IsAndroidMediaPluginEnabled() && IsAndroidMediaType(aType)) ||
 #endif
 #ifdef MOZ_FMP4
-    IsMP4SupportedType(aType, /* DecoderDoctorDiagnostics* */ nullptr) ||
+    MP4Decoder::IsSupportedType(*type, /* DecoderDoctorDiagnostics* */ nullptr) ||
 #endif
     IsMP3SupportedType(aType) ||
     IsAACSupportedType(aType) ||
     IsFlacSupportedType(aType) ||
 #ifdef MOZ_DIRECTSHOW
     IsDirectShowSupportedType(aType) ||
 #endif
     false;
--- a/dom/media/DecoderTraits.h
+++ b/dom/media/DecoderTraits.h
@@ -51,16 +51,18 @@ public:
   static MediaDecoderReader* CreateReader(const nsACString& aType,
                                           AbstractMediaDecoder* aDecoder);
 
   // Returns true if MIME type aType is supported in video documents,
   // or false otherwise. Not all platforms support all MIME types, and
   // vice versa.
   static bool IsSupportedInVideoDocument(const nsACString& aType);
 
-  static bool IsMP4TypeAndEnabled(const nsACString& aType,
-                                  DecoderDoctorDiagnostics* aDiagnostics);
+  // Convenience function that returns false if MOZ_FMP4 is not defined,
+  // otherwise defers to MP4Decoder::IsSupportedType().
+  static bool IsMP4SupportedType(const MediaContentType& aType,
+                                 DecoderDoctorDiagnostics* aDiagnostics);
 };
 
 } // namespace mozilla
 
 #endif
 
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -635,18 +635,17 @@ GetSupportedCapabilities(const CodecType
     }
 
     // If the user agent does not support container, continue to the next iteration.
     // The case-sensitivity of string comparisons is determined by the appropriate RFC.
     // (Note: Per RFC 6838 [RFC6838], "Both top-level type and subtype names are
     // case-insensitive."'. We're using nsContentTypeParser and that is
     // case-insensitive and converts all its parameter outputs to lower case.)
     const bool isMP4 =
-      DecoderTraits::IsMP4TypeAndEnabled(contentType.Type().AsString(),
-                                         aDiagnostics);
+      DecoderTraits::IsMP4SupportedType(contentType, aDiagnostics);
     if (isMP4 && !aKeySystem.mMP4.IsSupported()) {
       EME_LOG("MediaKeySystemConfiguration (label='%s') "
               "MediaKeySystemMediaCapability('%s','%s') unsupported; "
               "MP4 requested but unsupported.",
               NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(),
               NS_ConvertUTF16toUTF8(contentTypeString).get(),
               NS_ConvertUTF16toUTF8(robustness).get());
       continue;
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -62,61 +62,57 @@ IsWhitelistedH264Codec(const nsAString& 
          (profile == H264_PROFILE_BASE ||
           profile == H264_PROFILE_MAIN ||
           profile == H264_PROFILE_EXTENDED ||
           profile == H264_PROFILE_HIGH);
 }
 
 /* static */
 bool
-MP4Decoder::CanHandleMediaType(const MediaContentType& aType,
-                               DecoderDoctorDiagnostics* aDiagnostics)
+MP4Decoder::IsSupportedType(const MediaContentType& aType,
+                            DecoderDoctorDiagnostics* aDiagnostics)
 {
   if (!IsEnabled()) {
     return false;
   }
 
   // Whitelist MP4 types, so they explicitly match what we encounter on
   // the web, as opposed to what we use internally (i.e. what our demuxers
   // etc output).
-  const bool isMP4Audio = aType.Type() == MEDIAMIMETYPE("audio/mp4") ||
-                          aType.Type() == MEDIAMIMETYPE("audio/x-m4a");
-  const bool isMP4Video =
+  const bool isAudio = aType.Type() == MEDIAMIMETYPE("audio/mp4")
+                       || aType.Type() == MEDIAMIMETYPE("audio/x-m4a");
+  const bool isVideo = aType.Type() == MEDIAMIMETYPE("video/mp4")
+                       || aType.Type() == MEDIAMIMETYPE("video/quicktime")
   // On B2G, treat 3GPP as MP4 when Gonk PDM is available.
 #ifdef MOZ_GONK_MEDIACODEC
-      aType.Type() == MEDIAMIMETYPE(VIDEO_3GPP) ||
+                       || aType.Type() == MEDIAMIMETYPE(VIDEO_3GPP)
 #endif
-      aType.Type() == MEDIAMIMETYPE("video/mp4") ||
-      aType.Type() == MEDIAMIMETYPE("video/quicktime") ||
-      aType.Type() == MEDIAMIMETYPE("video/x-m4v");
-  if (!isMP4Audio && !isMP4Video) {
+                       || aType.Type() == MEDIAMIMETYPE("video/x-m4v");
+
+  if (!isAudio && !isVideo) {
     return false;
   }
 
   nsTArray<UniquePtr<TrackInfo>> trackInfos;
   if (aType.ExtendedType().Codecs().IsEmpty()) {
     // No codecs specified. Assume H.264
-    if (isMP4Audio) {
+    if (isAudio) {
       trackInfos.AppendElement(
         CreateTrackInfoWithMIMETypeAndContentTypeExtraParameters(
           NS_LITERAL_CSTRING("audio/mp4a-latm"), aType));
     } else {
-      MOZ_ASSERT(isMP4Video);
+      MOZ_ASSERT(isVideo);
       trackInfos.AppendElement(
         CreateTrackInfoWithMIMETypeAndContentTypeExtraParameters(
           NS_LITERAL_CSTRING("video/avc"), aType));
     }
   } else {
     // Verify that all the codecs specified are ones that we expect that
     // we can play.
-    nsTArray<nsString> codecs;
-    if (!ParseCodecsString(aType.ExtendedType().Codecs().AsString(), codecs)) {
-      return false;
-    }
-    for (const nsString& codec : codecs) {
+    for (const auto& codec : aType.ExtendedType().Codecs().Range()) {
       if (IsAACCodecString(codec)) {
         trackInfos.AppendElement(
           CreateTrackInfoWithMIMETypeAndContentTypeExtraParameters(
             NS_LITERAL_CSTRING("audio/mp4a-latm"), aType));
         continue;
       }
       if (codec.EqualsLiteral("mp3")) {
         trackInfos.AppendElement(
@@ -133,17 +129,17 @@ MP4Decoder::CanHandleMediaType(const Med
       if (codec.EqualsLiteral("flac")) {
         trackInfos.AppendElement(
           CreateTrackInfoWithMIMETypeAndContentTypeExtraParameters(
             NS_LITERAL_CSTRING("audio/flac"), aType));
         continue;
       }
       // Note: Only accept H.264 in a video content type, not in an audio
       // content type.
-      if (IsWhitelistedH264Codec(codec) && isMP4Video) {
+      if (IsWhitelistedH264Codec(codec) && isVideo) {
         trackInfos.AppendElement(
           CreateTrackInfoWithMIMETypeAndContentTypeExtraParameters(
             NS_LITERAL_CSTRING("video/avc"), aType));
         continue;
       }
       // Some unsupported codec.
       return false;
     }
--- a/dom/media/fmp4/MP4Decoder.h
+++ b/dom/media/fmp4/MP4Decoder.h
@@ -25,20 +25,21 @@ public:
     if (!IsEnabled()) {
       return nullptr;
     }
     return new MP4Decoder(aOwner);
   }
 
   MediaDecoderStateMachine* CreateStateMachine() override;
 
-  // Returns true if aType is a type that we think we can render with the
-  // a MP4 platform decoder backend.
-  static bool CanHandleMediaType(const MediaContentType& aType,
-                                 DecoderDoctorDiagnostics* aDiagnostics);
+  // Returns true if aContentType is an MP4 type that we think we can render
+  // with the a platform decoder backend.
+  // If provided, codecs are checked for support.
+  static bool IsSupportedType(const MediaContentType& aContentType,
+                              DecoderDoctorDiagnostics* aDiagnostics);
 
   // Return true if aMimeType is a one of the strings used by our demuxers to
   // identify H264. Does not parse general content type strings, i.e. white
   // space matters.
   static bool IsH264(const nsACString& aMimeType);
 
   // Return true if aMimeType is a one of the strings used by our demuxers to
   // identify AAC. Does not parse general content type strings, i.e. white
--- a/dom/media/gtest/TestMediaDataDecoder.cpp
+++ b/dom/media/gtest/TestMediaDataDecoder.cpp
@@ -3,16 +3,17 @@
  * 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 "gtest/gtest.h"
 #include "Benchmark.h"
 #include "MockMediaResource.h"
 #include "DecoderTraits.h"
 #include "MediaContentType.h"
+#include "MP4Decoder.h"
 #include "MP4Demuxer.h"
 #include "WebMDecoder.h"
 #include "WebMDemuxer.h"
 
 using namespace mozilla;
 
 class BenchmarkRunner
 {
@@ -39,18 +40,19 @@ public:
   }
 
 private:
   RefPtr<Benchmark> mBenchmark;
 };
 
 TEST(MediaDataDecoder, H264)
 {
-  if (!DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4")
-        , /* DecoderDoctorDiagnostics* */ nullptr)) {
+  if (!DecoderTraits::IsMP4SupportedType(
+         MediaContentType(MEDIAMIMETYPE("video/mp4")),
+         /* DecoderDoctorDiagnostics* */ nullptr)) {
     EXPECT_TRUE(true);
   } else {
     RefPtr<MediaResource> resource =
       new MockMediaResource("gizmo.mp4", NS_LITERAL_CSTRING("video/mp4"));
     nsresult rv = resource->Open(nullptr);
     EXPECT_TRUE(NS_SUCCEEDED(rv));
 
     BenchmarkRunner runner(new Benchmark(new MP4Demuxer(resource)));
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -67,18 +67,18 @@ namespace mozilla {
 //   * N/KN editions (Europe and Korea) of Windows 7/8/8.1/10 without the
 //     optional "Windows Media Feature Pack"
 // 2. If H264 hardware acceleration is not available.
 // 3. The CPU is considered to be fast enough
 static bool
 IsWebMForced(DecoderDoctorDiagnostics* aDiagnostics)
 {
   bool mp4supported =
-    DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4"),
-                                       aDiagnostics);
+    DecoderTraits::IsMP4SupportedType(MediaContentType(MEDIAMIMETYPE("video/mp4")),
+                                      aDiagnostics);
   bool hwsupported = gfx::gfxVars::CanUseHardwareVideoDecoding();
 #ifdef MOZ_WIDGET_ANDROID
   return !mp4supported || !hwsupported || VP9Benchmark::IsVP9DecodeFast() ||
          java::HardwareCodecCapabilityUtils::HasHWVP9();
 #else
   return !mp4supported || !hwsupported || VP9Benchmark::IsVP9DecodeFast();
 #endif
 }