Bug 1211339 Part 2 - Make MP4Decoder::CanHandleMediaType() check all codecs are supported by a PDM before reporting support. r=jya

This commit is contained in:
Chris Pearce 2015-10-06 16:52:58 +13:00
Родитель 494f013e18
Коммит aaf1f72ba5
5 изменённых файлов: 70 добавлений и 66 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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<nsString>& aOutCodecs)
{

Просмотреть файл

@ -338,6 +338,9 @@ IsH264ContentType(const nsAString& aContentType);
bool
IsAACContentType(const nsAString& aContentType);
bool
IsAACCodecString(const nsAString& aCodec);
} // end namespace mozilla
#endif

Просмотреть файл

@ -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<nsCString> 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<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;
}
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<nsString> codecs;
if (!ParseCodecsString(aCodecs, codecs)) {
// Verify that we have a PDM that supports the whitelisted types.
PlatformDecoderModule::Init();
nsRefPtr<PlatformDecoderModule> 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

Просмотреть файл

@ -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);