static bool IsSupportedH264Codec(const nsAString& aCodec) { int16_t profile = 0, level = 0; if (!ExtractH264CodecDetails(aCodec, profile, level)) { return false; } #ifdef XP_WIN // 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 // WMF can play, since we don't have documentation about what other // platforms can play... According to the WMF documentation: // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815%28v=vs.85%29.aspx // "The Media Foundation H.264 video decoder is a Media Foundation Transform // that supports decoding of Baseline, Main, and High profiles, up to level // 5.1.". We also report that we can play Extended profile, as there are // bitstreams that are Extended compliant that are also Baseline compliant. return level >= H264_LEVEL_1 && level <= H264_LEVEL_5_1 && (profile == H264_PROFILE_BASE || profile == H264_PROFILE_MAIN || profile == H264_PROFILE_EXTENDED || profile == H264_PROFILE_HIGH); }
static bool IsWhitelistedH264Codec(const nsAString& aCodec) { uint8_t profile = 0, constraint = 0, level = 0; if (!ExtractH264CodecDetails(aCodec, profile, constraint, level)) { return false; } // Just assume what we can play on all platforms the codecs/formats that // WMF can play, since we don't have documentation about what other // platforms can play... According to the WMF documentation: // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815%28v=vs.85%29.aspx // "The Media Foundation H.264 video decoder is a Media Foundation Transform // that supports decoding of Baseline, Main, and High profiles, up to level // 5.1.". We extend the limit to level 5.2, relying on the decoder to handle // any potential errors, the level limit being rather arbitrary. // We also report that we can play Extended profile, as there are // bitstreams that are Extended compliant that are also Baseline compliant. return level >= H264_LEVEL_1 && level <= H264_LEVEL_5_2 && (profile == H264_PROFILE_BASE || profile == H264_PROFILE_MAIN || profile == H264_PROFILE_EXTENDED || profile == H264_PROFILE_HIGH); }
bool IsH264CodecString(const nsAString& aCodec) { int16_t profile = 0; int16_t level = 0; return ExtractH264CodecDetails(aCodec, profile, level); }
bool IsH264CodecString(const nsAString& aCodec) { uint8_t profile = 0; uint8_t constraint = 0; uint8_t level = 0; return ExtractH264CodecDetails(aCodec, profile, constraint, level); }
bool IsH264ContentType(const nsAString& aContentType) { return CheckContentType(aContentType, [](const nsAString& type) { return type.EqualsLiteral("video/mp4"); }, [](const nsAString& codec) { int16_t profile = 0; int16_t level = 0; return ExtractH264CodecDetails(codec, profile, level); } ); }
/* statis */ nsTArray<UniquePtr<TrackInfo>> MP4Decoder::GetTracksInfo(const MediaContainerType& aType, MediaResult& aError) { nsTArray<UniquePtr<TrackInfo>> tracks; if (!IsTypeValid(aType)) { aError = MediaResult( NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("Invalid type:%s", aType.Type().AsString().get())); return tracks; } aError = NS_OK; const MediaCodecs& codecs = aType.ExtendedType().Codecs(); if (codecs.IsEmpty()) { return tracks; } const bool isVideo = aType.Type() == MEDIAMIMETYPE("video/mp4") || aType.Type() == MEDIAMIMETYPE("video/quicktime") || aType.Type() == MEDIAMIMETYPE("video/x-m4v"); for (const auto& codec : codecs.Range()) { if (IsAACCodecString(codec)) { tracks.AppendElement( CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("audio/mp4a-latm"), aType)); continue; } if (codec.EqualsLiteral("mp3")) { tracks.AppendElement( CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("audio/mpeg"), aType)); continue; } if (codec.EqualsLiteral("opus") || codec.EqualsLiteral("flac")) { tracks.AppendElement( CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("audio/") + NS_ConvertUTF16toUTF8(codec), aType)); continue; } if (IsVP9CodecString(codec)) { auto trackInfo = CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("video/vp9"), aType); uint8_t profile = 0; uint8_t level = 0; uint8_t bitDepth = 0; if (ExtractVPXCodecDetails(codec, profile, level, bitDepth)) { trackInfo->GetAsVideoInfo()->mBitDepth = bitDepth; } tracks.AppendElement(std::move(trackInfo)); continue; } if (isVideo && IsWhitelistedH264Codec(codec)) { auto trackInfo = CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( NS_LITERAL_CSTRING("video/avc"), aType); uint8_t profile = 0, constraint = 0, level = 0; MOZ_ALWAYS_TRUE( ExtractH264CodecDetails(codec, profile, constraint, level)); uint32_t width = aType.ExtendedType().GetWidth().refOr(1280); uint32_t height = aType.ExtendedType().GetHeight().refOr(720); trackInfo->GetAsVideoInfo()->mExtraData = H264::CreateExtraData(profile, constraint, level, { width, height }); tracks.AppendElement(std::move(trackInfo)); continue; } // Unknown codec aError = MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("Unknown codec:%s", NS_ConvertUTF16toUTF8(codec).get())); } return tracks; }