static bool CheckContentType(const nsAString& aContentType, mozilla::Function<bool(const nsAString&)> aSubtypeFilter, mozilla::Function<bool(const nsAString&)> aCodecFilter) { nsContentTypeParser parser(aContentType); nsAutoString mimeType; nsresult rv = parser.GetType(mimeType); if (NS_FAILED(rv) || !aSubtypeFilter(mimeType)) { return false; } nsString codecsStr; parser.GetParameter("codecs", codecsStr); nsTArray<nsString> codecs; if (!ParseCodecsString(codecsStr, codecs)) { return false; } for (const nsString& codec : codecs) { if (!aCodecFilter(codec)) { return false; } } return true; }
bool ParseMIMETypeString(const nsAString& aMIMEType, nsString& aOutContainerType, nsTArray<nsString>& aOutCodecs) { nsContentTypeParser parser(aMIMEType); nsresult rv = parser.GetType(aOutContainerType); if (NS_FAILED(rv)) { return false; } nsString codecsStr; parser.GetParameter("codecs", codecsStr); return ParseCodecsString(codecsStr, aOutCodecs); }
/* static */ bool OggDecoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, const nsAString& aCodecs) { if (!IsEnabled()) { return false; } const bool isOggAudio = aMIMETypeExcludingCodecs.EqualsASCII("audio/ogg"); const bool isOggVideo = aMIMETypeExcludingCodecs.EqualsASCII("video/ogg") || aMIMETypeExcludingCodecs.EqualsASCII("application/ogg"); if (!isOggAudio && !isOggVideo) { return false; } nsTArray<nsCString> codecMimes; if (aCodecs.IsEmpty()) { // WebM guarantees that the only codecs it contained are vp8, vp9, opus or vorbis. return true; } // Verify that all the codecs specified are ones that we expect that // we can play. nsTArray<nsString> codecs; if (!ParseCodecsString(aCodecs, codecs)) { return false; } for (const nsString& codec : codecs) { if ((IsOpusEnabled() && codec.EqualsLiteral("opus")) || codec.EqualsLiteral("vorbis") || (MediaPrefs::FlacInOgg() && codec.EqualsLiteral("flac"))) { continue; } // Note: Only accept Theora in a video content type, not in an audio // content type. if (isOggVideo && codec.EqualsLiteral("theora")) { continue; } // Some unsupported codec. return false; } return true; }
/* static */ bool WebMDecoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, const nsAString& aCodecs) { if (!IsEnabled()) { return false; } const bool isWebMAudio = aMIMETypeExcludingCodecs.EqualsASCII("audio/webm"); const bool isWebMVideo = aMIMETypeExcludingCodecs.EqualsASCII("video/webm"); if (!isWebMAudio && !isWebMVideo) { return false; } nsTArray<nsCString> codecMimes; if (aCodecs.IsEmpty()) { // WebM guarantees that the only codecs it contained are vp8, vp9, opus or vorbis. return true; } // Verify that all the codecs specified are ones that we expect that // we can play. nsTArray<nsString> codecs; if (!ParseCodecsString(aCodecs, codecs)) { return false; } for (const nsString& codec : codecs) { if (codec.EqualsLiteral("opus") || codec.EqualsLiteral("vorbis")) { continue; } // Note: Only accept VP8/VP9 in a video content type, not in an audio // content type. if (isWebMVideo && (codec.EqualsLiteral("vp8") || codec.EqualsLiteral("vp8.0") || codec.EqualsLiteral("vp9") || codec.EqualsLiteral("vp9.0"))) { continue; } // Some unsupported codec. return false; } return true; }
/* static */ bool MP4Decoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, const nsAString& aCodecs, 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 = aMIMETypeExcludingCodecs.EqualsASCII("audio/mp4") || aMIMETypeExcludingCodecs.EqualsASCII("audio/x-m4a") || aMIMETypeExcludingCodecs.EqualsASCII("audio/opus"); const bool isMP4Video = // On B2G, treat 3GPP as MP4 when Gonk PDM is available. #ifdef MOZ_GONK_MEDIACODEC aMIMETypeExcludingCodecs.EqualsASCII(VIDEO_3GPP) || #endif aMIMETypeExcludingCodecs.EqualsASCII("video/mp4") || aMIMETypeExcludingCodecs.EqualsASCII("video/quicktime") || aMIMETypeExcludingCodecs.EqualsASCII("video/x-m4v"); if (!isMP4Audio && !isMP4Video) { return false; } nsTArray<nsCString> codecMimes; if (aCodecs.IsEmpty()) { // No codecs specified. Assume AAC/H.264 if (isMP4Audio) { codecMimes.AppendElement(NS_LITERAL_CSTRING("audio/mp4a-latm")); } else { MOZ_ASSERT(isMP4Video); codecMimes.AppendElement(NS_LITERAL_CSTRING("video/avc")); } } else { // Verify that all the codecs specified are ones that we expect that // we can play. nsTArray<nsString> 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; } // Note: Only accept H.264 in a video content type, not in an audio // content type. if (IsWhitelistedH264Codec(codec) && isMP4Video) { codecMimes.AppendElement(NS_LITERAL_CSTRING("video/avc")); continue; } // Some unsupported codec. return false; } } // Verify that we have a PDM that supports the whitelisted types. RefPtr<PDMFactory> platform = new PDMFactory(); for (const nsCString& codecMime : codecMimes) { if (!platform->SupportsMimeType(codecMime, aDiagnostics)) { return false; } } return true; }
/* static */ bool MP4Decoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, const nsAString& aCodecs) { 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 = aMIMETypeExcludingCodecs.EqualsASCII("audio/mp4") || aMIMETypeExcludingCodecs.EqualsASCII("audio/x-m4a"); const bool isMP4Video = aMIMETypeExcludingCodecs.EqualsASCII("video/mp4") || #ifdef XP_LINUX aMIMETypeExcludingCodecs.EqualsASCII("video/quicktime") || #endif aMIMETypeExcludingCodecs.EqualsASCII("video/x-m4v"); if (!isMP4Audio && !isMP4Video) { return false; } #ifdef MOZ_GONK_MEDIACODEC if (aMIMETypeExcludingCodecs.EqualsASCII(VIDEO_3GPP)) { return Preferences::GetBool("media.gonk.enabled", false); } #endif nsTArray<nsCString> codecMimes; if (aCodecs.IsEmpty()) { // No codecs specified. Assume AAC/H.264 if (isMP4Audio) { codecMimes.AppendElement(NS_LITERAL_CSTRING("audio/mp4a-latm")); } else { MOZ_ASSERT(isMP4Video); codecMimes.AppendElement(NS_LITERAL_CSTRING("video/avc")); } } else { // Verify that all the codecs specified are ones that we expect that // we can play. nsTArray<nsString> 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; } // Note: Only accept H.264 in a video content type, not in an audio // content type. if (IsWhitelistedH264Codec(codec) && isMP4Video) { codecMimes.AppendElement(NS_LITERAL_CSTRING("video/avc")); continue; } // Some unsupported codec. return false; } } // Verify that we have a PDM that supports the whitelisted types. PlatformDecoderModule::Init(); nsRefPtr<PlatformDecoderModule> platform = PlatformDecoderModule::Create(); if (!platform) { return false; } for (const nsCString& codecMime : codecMimes) { if (!platform->SupportsMimeType(codecMime)) { return false; } } return true; }