/* static */ bool MP3Decoder::CanHandleMediaType(const nsACString& aType, const nsAString& aCodecs) { if (aType.EqualsASCII("audio/mp3") || aType.EqualsASCII("audio/mpeg")) { return IsEnabled() && (aCodecs.IsEmpty() || aCodecs.EqualsASCII("mp3")); } return false; }
bool WMFDecoder::GetSupportedCodecs(const nsACString& aType, char const *const ** aCodecList) { if (!MediaDecoder::IsWMFEnabled() || NS_FAILED(LoadDLLs())) return false; // MP3 is specified to have no codecs in its "type" param: // http://wiki.whatwg.org/wiki/Video_type_parameters#MPEG // So specify an empty codecs list, so that if script specifies // a "type" param with codecs, it will be reported as not supported // as per the spec. static char const *const mp3AudioCodecs[] = { nullptr }; if (aType.EqualsASCII("audio/mpeg")) { if (aCodecList) { *aCodecList = mp3AudioCodecs; } // Assume that if LoadDLLs() didn't fail, we can decode MP3. return true; } // AAC in M4A. static char const *const aacAudioCodecs[] = { "mp4a.40.2", // AAC-LC nullptr }; if (aType.EqualsASCII("audio/mp4")) { if (aCodecList) { *aCodecList = aacAudioCodecs; } return true; } // H.264 + AAC in MP4. static char const *const H264Codecs[] = { "avc1.42E01E", // H.264 Constrained Baseline Profile Level 3.0 "avc1.42001E", // H.264 Baseline Profile Level 3.0 "avc1.58A01E", // H.264 Extended Profile Level 3.0 "avc1.4D401E", // H.264 Main Profile Level 3.0 "avc1.64001E", // H.264 High Profile Level 3.0 "avc1.64001F", // H.264 High Profile Level 3.1 "mp4a.40.2", // AAC-LC nullptr }; if (aType.EqualsASCII("video/mp4")) { if (aCodecList) { *aCodecList = H264Codecs; } return true; } return false; }
/* static */ bool ADTSDecoder::CanHandleMediaType(const nsACString& aType, const nsAString& aCodecs) { if (aType.EqualsASCII("audio/aac") || aType.EqualsASCII("audio/aacp")) { return IsEnabled() && (aCodecs.IsEmpty() || aCodecs.EqualsASCII("aac")); } return false; }
bool WMFDecoder::GetSupportedCodecs(const nsACString& aType, char const *const ** aCodecList) { if (!MediaDecoder::IsWMFEnabled() || NS_FAILED(LoadDLLs())) return false; // Assume that if LoadDLLs() didn't fail, we can playback the types that // we know should be supported on Windows 7+ using WMF. static char const *const mp3AudioCodecs[] = { "mp3", nullptr }; if (aType.EqualsASCII("audio/mpeg") || aType.EqualsASCII("audio/mp3")) { if (aCodecList) { *aCodecList = mp3AudioCodecs; } return true; } // AAC in M4A. static char const *const aacAudioCodecs[] = { "mp4a.40.2", // AAC-LC nullptr }; if (aType.EqualsASCII("audio/mp4") || aType.EqualsASCII("audio/x-m4a")) { if (aCodecList) { *aCodecList = aacAudioCodecs; } return true; } // H.264 + AAC in MP4. static char const *const H264Codecs[] = { "avc1.42E01E", // H.264 Constrained Baseline Profile Level 3.0 "avc1.42001E", // H.264 Baseline Profile Level 3.0 "avc1.58A01E", // H.264 Extended Profile Level 3.0 "avc1.4D401E", // H.264 Main Profile Level 3.0 "avc1.64001E", // H.264 High Profile Level 3.0 "avc1.64001F", // H.264 High Profile Level 3.1 "mp4a.40.2", // AAC-LC nullptr }; if (aType.EqualsASCII("video/mp4")) { if (aCodecList) { *aCodecList = H264Codecs; } return true; } return false; }
/* static */ bool WaveDecoder::CanHandleMediaType(const nsACString& aType, const nsAString& aCodecs) { if (aType.EqualsASCII("audio/wave") || aType.EqualsASCII("audio/x-wav") || aType.EqualsASCII("audio/wav") || aType.EqualsASCII("audio/x-pn-wav")) { return IsEnabled() && (aCodecs.IsEmpty() || aCodecs.EqualsASCII("1")); } return false; }
/* static */ bool MP4Decoder::CanHandleMediaType(const nsACString& aType, const nsAString& aCodecs, bool& aOutContainsAAC, bool& aOutContainsH264, bool& aOutContainsMP3) { if (!IsEnabled()) { return false; } if (aType.EqualsASCII("audio/mp4") || aType.EqualsASCII("audio/x-m4a")) { return MP4Decoder::CanCreateAACDecoder() && (aCodecs.IsEmpty() || IsSupportedAudioCodec(aCodecs, aOutContainsAAC, aOutContainsMP3)); } #ifdef MOZ_GONK_MEDIACODEC if (aType.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; } // Verify that all the codecs specifed are ones that we expect that // we can play. nsCharSeparatedTokenizer tokenizer(aCodecs, ','); bool expectMoreTokens = false; while (tokenizer.hasMoreTokens()) { const nsSubstring& token = tokenizer.nextToken(); expectMoreTokens = tokenizer.separatorAfterCurrentToken(); if (IsSupportedAudioCodec(token, aOutContainsAAC, aOutContainsMP3)) { continue; } if (IsSupportedH264Codec(token)) { aOutContainsH264 = true; continue; } return false; } if (expectMoreTokens) { // Last codec name was empty return false; } return true; }
bool WMFDecoder::CanPlayType(const nsACString& aType, const nsAString& aCodecs) { if (!MediaDecoder::IsWMFEnabled() || NS_FAILED(LoadDLLs())) { return false; } // Assume that if LoadDLLs() didn't fail, we can playback the types that // we know should be supported by Windows Media Foundation. if ((aType.EqualsASCII("audio/mpeg") || aType.EqualsASCII("audio/mp3")) && IsMP3Supported()) { // Note: We block MP3 playback on Window 7 SP0 since it seems to crash // in some circumstances. return !aCodecs.Length() || aCodecs.EqualsASCII("mp3"); } // AAC-LC or MP3 in M4A. if (aType.EqualsASCII("audio/mp4") || aType.EqualsASCII("audio/x-m4a")) { return !aCodecs.Length() || aCodecs.EqualsASCII("mp4a.40.2") || aCodecs.EqualsASCII("mp3"); } if (!aType.EqualsASCII("video/mp4")) { return false; } // H.264 + AAC in MP4. Verify that all the codecs specifed are ones that // we expect that we can play. nsCharSeparatedTokenizer tokenizer(aCodecs, ','); bool expectMoreTokens = false; while (tokenizer.hasMoreTokens()) { const nsSubstring& token = tokenizer.nextToken(); expectMoreTokens = tokenizer.separatorAfterCurrentToken(); if (token.EqualsASCII("mp4a.40.2") || // AAC-LC token.EqualsASCII("mp3") || IsSupportedH264Codec(token)) { continue; } return false; } if (expectMoreTokens) { // Last codec name was empty return false; } return true; }
/* static */ bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType) { return #ifdef MOZ_OGG IsOggType(aType) || #endif #ifdef MOZ_OMX_DECODER // We support amr inside WebApps on firefoxOS but not in general web content. // Ensure we dont create a VideoDocument when accessing amr URLs directly. (IsOmxSupportedType(aType) && !aType.EqualsASCII("audio/amr")) || #endif #ifdef MOZ_WEBM IsWebMType(aType) || #endif #ifdef MOZ_DASH IsDASHMPDType(aType) || #endif #ifdef MOZ_GSTREAMER IsGStreamerSupportedType(aType) || #endif #ifdef MOZ_MEDIA_PLUGINS (MediaDecoder::IsMediaPluginsEnabled() && IsMediaPluginsType(aType)) || #endif #ifdef MOZ_WMF (IsWMFSupportedType(aType) && Preferences::GetBool("media.windows-media-foundation.play-stand-alone", true)) || #endif #ifdef MOZ_DIRECTSHOW IsDirectShowSupportedType(aType) || #endif #ifdef MOZ_APPLEMEDIA IsAppleMediaSupportedType(aType) || #endif false; }
/* static */ bool MP4Decoder::CanHandleMediaType(const nsACString& aType, const nsAString& aCodecs, bool& aOutContainsAAC, 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); } if (!aType.EqualsASCII("video/mp4")) { 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()) { const nsSubstring& token = tokenizer.nextToken(); expectMoreTokens = tokenizer.separatorAfterCurrentToken(); if (IsSupportedAudioCodec(token, aOutContainsAAC, aOutContainsMP3)) { continue; } if (IsSupportedH264Codec(token)) { aOutContainsH264 = true; continue; } return false; } if (expectMoreTokens) { // Last codec name was empty return false; } return true; }
/* 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; }
bool ServiceWorkerRegistrar::IsSupportedVersion(const nsACString& aVersion) const { uint32_t numVersions = ArrayLength(gSupportedRegistrarVersions); for (uint32_t i = 0; i < numVersions; i++) { if (aVersion.EqualsASCII(gSupportedRegistrarVersions[i])) { return true; } } return false; }
/* 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 DecoderTraits::IsWebMAudioType(const nsACString& aType) { return aType.EqualsASCII("audio/webm"); }
/* 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; }
bool Contains(const nsACString& key) const { for (int i = 0; i < mLen; ++i) if (key.EqualsASCII(mItems[i])) return true; return false; }
// Instantiates but does not initialize decoder. static already_AddRefed<MediaDecoder> InstantiateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner) { nsRefPtr<MediaDecoder> decoder; #ifdef MOZ_FMP4 if (IsMP4SupportedType(aType)) { decoder = new MP4Decoder(); return decoder.forget(); } #endif #ifdef MOZ_GSTREAMER if (IsGStreamerSupportedType(aType)) { decoder = new GStreamerDecoder(); return decoder.forget(); } #endif #ifdef MOZ_RAW if (IsRawType(aType)) { decoder = new RawDecoder(); return decoder.forget(); } #endif if (IsOggType(aType)) { decoder = new OggDecoder(); return decoder.forget(); } #ifdef MOZ_WAVE if (IsWaveType(aType)) { decoder = new WaveDecoder(); return decoder.forget(); } #endif #ifdef MOZ_OMX_DECODER if (IsOmxSupportedType(aType)) { // AMR audio is enabled for MMS, but we are discouraging Web and App // developers from using AMR, thus we only allow AMR to be played on WebApps. if (aType.EqualsASCII("audio/amr")) { dom::HTMLMediaElement* element = aOwner->GetMediaElement(); if (!element) { return nullptr; } nsIPrincipal* principal = element->NodePrincipal(); if (!principal) { return nullptr; } if (principal->GetAppStatus() < nsIPrincipal::APP_STATUS_PRIVILEGED) { return nullptr; } } #if ANDROID_VERSION >= 18 decoder = MediaDecoder::IsOmxAsyncEnabled() ? static_cast<MediaDecoder*>(new MediaCodecDecoder()) : static_cast<MediaDecoder*>(new MediaOmxDecoder()); #else decoder = new MediaOmxDecoder(); #endif return decoder.forget(); } #endif #ifdef NECKO_PROTOCOL_rtsp if (IsRtspSupportedType(aType)) { decoder = new RtspOmxDecoder(); return decoder.forget(); } #endif #ifdef MOZ_ANDROID_OMX if (MediaDecoder::IsAndroidMediaEnabled() && GetAndroidMediaPluginHost()->FindDecoder(aType, nullptr)) { decoder = new AndroidMediaDecoder(aType); return decoder.forget(); } #endif #ifdef MOZ_WEBM if (IsWebMType(aType)) { decoder = new WebMDecoder(); return decoder.forget(); } #endif #ifdef MOZ_DIRECTSHOW // Note: DirectShow should come before WMF, so that we prefer DirectShow's // MP3 support over WMF's. if (IsDirectShowSupportedType(aType)) { decoder = new DirectShowDecoder(); return decoder.forget(); } #endif #ifdef MOZ_WMF if (IsWMFSupportedType(aType)) { decoder = new WMFDecoder(); return decoder.forget(); } #endif #ifdef MOZ_APPLEMEDIA if (IsAppleMediaSupportedType(aType)) { decoder = new AppleDecoder(); return decoder.forget(); } #endif NS_ENSURE_TRUE(decoder != nullptr, nullptr); NS_ENSURE_TRUE(decoder->Init(aOwner), nullptr); return nullptr; }
/* static */ already_AddRefed<MediaDecoder> DecoderTraits::CreateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner) { nsRefPtr<MediaDecoder> decoder; #ifdef MOZ_GSTREAMER if (IsGStreamerSupportedType(aType)) { decoder = new GStreamerDecoder(); } #endif #ifdef MOZ_RAW if (IsRawType(aType)) { decoder = new RawDecoder(); } #endif #ifdef MOZ_OGG if (IsOggType(aType)) { decoder = new OggDecoder(); } #endif #ifdef MOZ_WAVE if (IsWaveType(aType)) { decoder = new WaveDecoder(); } #endif #ifdef MOZ_OMX_DECODER if (IsOmxSupportedType(aType)) { // AMR audio is enabled for MMS, but we are discouraging Web and App // developers from using AMR, thus we only allow AMR to be played on WebApps. if (aType.EqualsASCII("audio/amr")) { HTMLMediaElement* element = aOwner->GetMediaElement(); if (!element) { return nullptr; } nsIPrincipal* principal = element->NodePrincipal(); if (!principal) { return nullptr; } if (principal->GetAppStatus() < nsIPrincipal::APP_STATUS_PRIVILEGED) { return nullptr; } } decoder = new MediaOmxDecoder(); } #endif #ifdef MOZ_MEDIA_PLUGINS if (MediaDecoder::IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(aType, NULL)) { decoder = new MediaPluginDecoder(aType); } #endif #ifdef MOZ_WEBM if (IsWebMType(aType)) { decoder = new WebMDecoder(); } #endif #ifdef MOZ_DASH if (IsDASHMPDType(aType)) { decoder = new DASHDecoder(); } #endif #ifdef MOZ_DIRECTSHOW // Note: DirectShow decoder must come before WMFDecoder, else the pref // "media.directshow.preferred" won't be honored. if (IsDirectShowSupportedType(aType)) { decoder = new DirectShowDecoder(); } #endif #ifdef MOZ_WMF if (IsWMFSupportedType(aType)) { decoder = new WMFDecoder(); } #endif #ifdef MOZ_APPLEMEDIA if (IsAppleMediaSupportedType(aType)) { decoder = new AppleDecoder(); } #endif NS_ENSURE_TRUE(decoder != nullptr, nullptr); NS_ENSURE_TRUE(decoder->Init(aOwner), nullptr); return decoder.forget(); }
/* 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; }
static bool IsMP3SupportedType(const nsACString& aType, const nsAString& aCodecs = EmptyString()) { return aType.EqualsASCII("audio/mpeg") && MP3Decoder::IsEnabled(); }