diff --git a/dom/media/DecoderTraits.cpp b/dom/media/DecoderTraits.cpp index 26fe5bbb6ae2..aa1c11fadedd 100644 --- a/dom/media/DecoderTraits.cpp +++ b/dom/media/DecoderTraits.cpp @@ -347,9 +347,7 @@ static bool IsMP4SupportedType(const nsACString& aType, const nsAString& aCodecs = EmptyString()) { - // MP4Decoder/Reader is currently used for MSE and mp4 files local playback. - bool haveAAC, haveMP3, haveH264; - return MP4Decoder::CanHandleMediaType(aType, aCodecs, haveAAC, haveH264, haveMP3); + return MP4Decoder::CanHandleMediaType(aType, aCodecs); } #endif diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp index e9382ba05b45..ebdc7b1f74b7 100644 --- a/dom/media/VideoUtils.cpp +++ b/dom/media/VideoUtils.cpp @@ -469,6 +469,15 @@ LogToBrowserConsole(const nsAString& aMsg) console->LogStringMessage(msg.get()); } +bool +IsAACCodecString(const nsAString& aCodec) +{ + return + aCodec.EqualsLiteral("mp4a.40.2") || // MPEG4 AAC-LC + aCodec.EqualsLiteral("mp4a.40.5") || // MPEG4 HE-AAC + aCodec.EqualsLiteral("mp4a.67"); // MPEG2 AAC-LC} +} + bool ParseCodecsString(const nsAString& aCodecs, nsTArray& aOutCodecs) { diff --git a/dom/media/VideoUtils.h b/dom/media/VideoUtils.h index a42517dbb16a..baeb15ddfddf 100644 --- a/dom/media/VideoUtils.h +++ b/dom/media/VideoUtils.h @@ -338,6 +338,9 @@ IsH264ContentType(const nsAString& aContentType); bool IsAACContentType(const nsAString& aContentType); +bool +IsAACCodecString(const nsAString& aCodec); + } // end namespace mozilla #endif diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp index 5e0a6c6aff8c..c65b0a94c0bf 100644 --- a/dom/media/fmp4/MP4Decoder.cpp +++ b/dom/media/fmp4/MP4Decoder.cpp @@ -16,6 +16,7 @@ #include "mozilla/Logging.h" #include "nsMimeTypes.h" #include "nsContentTypeParser.h" +#include "VideoUtils.h" #ifdef XP_WIN #include "mozilla/WindowsVersion.h" @@ -53,30 +54,7 @@ MediaDecoderStateMachine* MP4Decoder::CreateStateMachine() } static bool -IsSupportedAudioCodec(const nsAString& aCodec, - bool& aOutContainsAAC, - bool& aOutContainsMP3) -{ - // AAC-LC or HE-AAC in M4A. - aOutContainsAAC = aCodec.EqualsASCII("mp4a.40.2") // MPEG4 AAC-LC - || aCodec.EqualsASCII("mp4a.40.5") // MPEG4 HE-AAC - || aCodec.EqualsASCII("mp4a.67"); // MPEG2 AAC-LC - if (aOutContainsAAC) { - return true; - } -#ifndef MOZ_GONK_MEDIACODEC // B2G doesn't support MP3 in MP4 yet. - aOutContainsMP3 = aCodec.EqualsASCII("mp3"); - if (aOutContainsMP3) { - return true; - } -#else - aOutContainsMP3 = false; -#endif - return false; -} - -static bool -IsSupportedH264Codec(const nsAString& aCodec) +IsWhitelistedH264Codec(const nsAString& aCodec) { int16_t profile = 0, level = 0; @@ -110,52 +88,74 @@ IsSupportedH264Codec(const nsAString& aCodec) /* static */ bool -MP4Decoder::CanHandleMediaType(const nsACString& aType, - const nsAString& aCodecs, - bool& aOutContainsAAC, - bool& aOutContainsH264, - bool& aOutContainsMP3) +MP4Decoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, + const nsAString& aCodecs) { if (!IsEnabled()) { return false; } - if (aType.EqualsASCII("audio/mp4") || aType.EqualsASCII("audio/x-m4a")) { - return MP4Decoder::CanCreateAACDecoder() && - (aCodecs.IsEmpty() || - IsSupportedAudioCodec(aCodecs, - aOutContainsAAC, - aOutContainsMP3)); + // 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). + if (!aMIMETypeExcludingCodecs.EqualsASCII("audio/mp4") && + !aMIMETypeExcludingCodecs.EqualsASCII("audio/x-m4a") && + !aMIMETypeExcludingCodecs.EqualsASCII("video/mp4") && + !aMIMETypeExcludingCodecs.EqualsASCII("video/x-m4v")) { + return false; } #ifdef MOZ_GONK_MEDIACODEC - if (aType.EqualsASCII(VIDEO_3GPP)) { + if (aMIMETypeExcludingCodecs.EqualsASCII(VIDEO_3GPP)) { return Preferences::GetBool("media.fragmented-mp4.gonk.enabled", false); } #endif - if ((!aType.EqualsASCII("video/mp4") && !aType.EqualsASCII("video/x-m4v")) || - !MP4Decoder::CanCreateH264Decoder()) { - return false; + + nsTArray codecMimes; + if (aCodecs.IsEmpty()) { + // No codecs specified. Assume AAC/H.264 + if (aMIMETypeExcludingCodecs.EqualsLiteral("audio/mp4") || + aMIMETypeExcludingCodecs.EqualsLiteral("audio/x-m4a")) { + codecMimes.AppendElement(NS_LITERAL_CSTRING("audio/mp4a-latm")); + } else if (aMIMETypeExcludingCodecs.EqualsLiteral("video/mp4") || + aMIMETypeExcludingCodecs.EqualsLiteral("video/x-m4v")) { + codecMimes.AppendElement(NS_LITERAL_CSTRING("video/avc")); + } + } else { + // Verify that all the codecs specified are ones that we expect that + // we can play. + nsTArray codecs; + if (!ParseCodecsString(aCodecs, codecs)) { + return false; + } + for (const nsString& codec : codecs) { + if (IsAACCodecString(codec)) { + codecMimes.AppendElement(NS_LITERAL_CSTRING("audio/mp4a-latm")); + continue; + } + if (codec.EqualsLiteral("mp3")) { + codecMimes.AppendElement(NS_LITERAL_CSTRING("audio/mpeg")); + continue; + } + if (IsWhitelistedH264Codec(codec)) { + codecMimes.AppendElement(NS_LITERAL_CSTRING("video/avc")); + continue; + } + // Some unsupported codec. + return false; + } } - // Verify that all the codecs specifed are ones that we expect that - // we can play. - nsTArray codecs; - if (!ParseCodecsString(aCodecs, codecs)) { + // Verify that we have a PDM that supports the whitelisted types. + PlatformDecoderModule::Init(); + nsRefPtr platform = PlatformDecoderModule::Create(); + if (!platform) { return false; } - for (const nsString& codec : codecs) { - if (IsSupportedAudioCodec(codec, - aOutContainsAAC, - aOutContainsMP3)) { - continue; + for (const nsCString& codecMime : codecMimes) { + if (!platform->SupportsMimeType(codecMime)) { + return false; } - if (IsSupportedH264Codec(codec)) { - aOutContainsH264 = true; - continue; - } - // Some unsupported codec. - return false; } return true; @@ -173,10 +173,7 @@ MP4Decoder::CanHandleMediaType(const nsAString& aContentType) nsString codecs; parser.GetParameter("codecs", codecs); - bool ignoreAAC, ignoreH264, ignoreMP3; - return CanHandleMediaType(NS_ConvertUTF16toUTF8(mimeType), - codecs, - ignoreAAC, ignoreH264, ignoreMP3); + return CanHandleMediaType(NS_ConvertUTF16toUTF8(mimeType), codecs); } static bool diff --git a/dom/media/fmp4/MP4Decoder.h b/dom/media/fmp4/MP4Decoder.h index e3342b7220f4..aceec851aec9 100644 --- a/dom/media/fmp4/MP4Decoder.h +++ b/dom/media/fmp4/MP4Decoder.h @@ -29,11 +29,8 @@ public: // a MP4 platform decoder backend. If aCodecs is non emtpy, it is filled // with a comma-delimited list of codecs to check support for. Notes in // out params wether the codecs string contains AAC or H.264. - static bool CanHandleMediaType(const nsACString& aMIMEType, - const nsAString& aCodecs, - bool& aOutContainsAAC, - bool& aOutContainsH264, - bool& aOutContainsMP3); + static bool CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, + const nsAString& aCodecs); static bool CanHandleMediaType(const nsAString& aMIMEType);