Bug 566245 - HTMLMediaElement.canPlayType support for WebM. r=roc

This commit is contained in:
Chris Double 2010-06-09 11:31:27 +12:00
Родитель f3045189b2
Коммит 42bf8162f5
9 изменённых файлов: 201 добавлений и 23 удалений

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

@ -61,6 +61,12 @@ class nsHTMLMediaElement : public nsGenericHTMLElement,
typedef mozilla::layers::ImageContainer ImageContainer;
public:
enum CanPlayStatus {
CANPLAY_NO,
CANPLAY_MAYBE,
CANPLAY_YES
};
nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParser = PR_FALSE);
virtual ~nsHTMLMediaElement();
@ -226,12 +232,17 @@ public:
// main thread when/if the size changes.
void UpdateMediaSize(nsIntSize size);
// Returns true if we can handle this MIME type.
// If it returns true, then it also returns a null-terminated list
// of supported codecs in *aSupportedCodecs. This
// list should not be freed, it is static data.
static PRBool CanHandleMediaType(const char* aMIMEType,
const char*** aSupportedCodecs);
// Returns the CanPlayStatus indicating if we can handle this
// MIME type. The MIME type should not include the codecs parameter.
// If it returns anything other than CANPLAY_NO then it also
// returns a null-terminated list of supported codecs
// in *aSupportedCodecs. This list should not be freed, it is static data.
static CanPlayStatus CanHandleMediaType(const char* aMIMEType,
const char*** aSupportedCodecs);
// Returns the CanPlayStatus indicating if we can handle the
// full MIME type including the optional codecs parameter.
static CanPlayStatus GetCanPlay(const nsAString& aType);
// Returns true if we should handle this MIME type when it appears
// as an <object> or as a toplevel page. If, in practice, our support

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

@ -93,6 +93,9 @@
#ifdef MOZ_WAVE
#include "nsWaveDecoder.h"
#endif
#ifdef MOZ_WEBM
#include "nsWebMDecoder.h"
#endif
#ifdef PR_LOGGING
static PRLogModuleInfo* gMediaElementLog;
@ -1247,23 +1250,60 @@ static PRBool IsWaveType(const nsACString& aType)
}
#endif
#ifdef MOZ_WEBM
static const char gWebMTypes[][17] = {
"video/webm",
"audio/webm"
};
static const char* gWebMCodecs[] = {
"vp8",
"vp8.0",
"vorbis",
nsnull
};
static PRBool IsWebMEnabled()
{
return nsContentUtils::GetBoolPref("media.webm.enabled");
}
static PRBool IsWebMType(const nsACString& aType)
{
if (!IsWebMEnabled())
return PR_FALSE;
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(gWebMTypes); ++i) {
if (aType.EqualsASCII(gWebMTypes[i]))
return PR_TRUE;
}
return PR_FALSE;
}
#endif
/* static */
PRBool nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType,
const char*** aCodecList)
nsHTMLMediaElement::CanPlayStatus
nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType,
const char*** aCodecList)
{
#ifdef MOZ_OGG
if (IsOggType(nsDependentCString(aMIMEType))) {
*aCodecList = gOggCodecs;
return PR_TRUE;
return CANPLAY_MAYBE;
}
#endif
#ifdef MOZ_WAVE
if (IsWaveType(nsDependentCString(aMIMEType))) {
*aCodecList = gWaveCodecs;
return PR_TRUE;
return CANPLAY_MAYBE;
}
#endif
return PR_FALSE;
#ifdef MOZ_WEBM
if (IsWebMType(nsDependentCString(aMIMEType))) {
*aCodecList = gWebMCodecs;
return CANPLAY_YES;
}
#endif
return CANPLAY_NO;
}
/* static */
@ -1272,6 +1312,10 @@ PRBool nsHTMLMediaElement::ShouldHandleMediaType(const char* aMIMEType)
#ifdef MOZ_OGG
if (IsOggType(nsDependentCString(aMIMEType)))
return PR_TRUE;
#endif
#ifdef MOZ_WEBM
if (IsWebMType(nsDependentCString(aMIMEType)))
return PR_TRUE;
#endif
// We should not return true for Wave types, since there are some
// Wave codecs actually in use in the wild that we don't support, and
@ -1291,13 +1335,9 @@ CodecListContains(const char** aCodecs, const nsAString& aCodec)
return PR_FALSE;
}
enum CanPlayStatus {
CANPLAY_NO,
CANPLAY_MAYBE,
CANPLAY_YES
};
static CanPlayStatus GetCanPlay(const nsAString& aType)
/* static */
nsHTMLMediaElement::CanPlayStatus
nsHTMLMediaElement::GetCanPlay(const nsAString& aType)
{
nsContentTypeParser parser(aType);
nsAutoString mimeType;
@ -1307,15 +1347,17 @@ static CanPlayStatus GetCanPlay(const nsAString& aType)
NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
const char** supportedCodecs;
if (!nsHTMLMediaElement::CanHandleMediaType(mimeTypeUTF8.get(),
&supportedCodecs))
CanPlayStatus status = CanHandleMediaType(mimeTypeUTF8.get(),
&supportedCodecs);
if (status == CANPLAY_NO)
return CANPLAY_NO;
nsAutoString codecs;
rv = parser.GetParameter("codecs", codecs);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
// Parameter not found or whatever
return CANPLAY_MAYBE;
return status;
}
CanPlayStatus result = CANPLAY_YES;
// See http://www.rfc-editor.org/rfc/rfc4281.txt for the description
@ -1364,6 +1406,15 @@ void nsHTMLMediaElement::InitMediaTypes()
PR_FALSE, PR_TRUE, nsnull);
}
}
#endif
#ifdef MOZ_WEBM
if (IsWebMEnabled()) {
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(gWebMTypes); i++) {
catMan->AddCategoryEntry("Gecko-Content-Viewers", gWebMTypes[i],
"@mozilla.org/content/document-loader-factory;1",
PR_FALSE, PR_TRUE, nsnull);
}
}
#endif
}
}
@ -1383,6 +1434,11 @@ void nsHTMLMediaElement::ShutdownMediaTypes()
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(gWaveTypes); i++) {
catMan->DeleteCategoryEntry("Gecko-Content-Viewers", gWaveTypes[i], PR_FALSE);
}
#endif
#ifdef MOZ_WEBM
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(gWebMTypes); i++) {
catMan->DeleteCategoryEntry("Gecko-Content-Viewers", gWebMTypes[i], PR_FALSE);
}
#endif
}
}
@ -1405,6 +1461,14 @@ nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
return decoder.forget().get();
}
}
#endif
#ifdef MOZ_WEBM
if (IsWebMType(aType)) {
nsRefPtr<nsWebMDecoder> decoder = new nsWebMDecoder();
if (decoder && decoder->Init(this)) {
return decoder.forget().get();
}
}
#endif
return nsnull;
}

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

@ -70,6 +70,7 @@ _TEST_FILES = \
allowed.sjs \
can_play_type_ogg.js \
can_play_type_wave.js \
can_play_type_webm.js \
cancellable_request.sjs \
dynamic_redirect.sjs \
file_access_controls.html \
@ -241,6 +242,16 @@ _TEST_FILES += \
$(NULL)
endif
ifdef MOZ_WEBM
_TEST_FILES += \
test_can_play_type_webm.html \
$(NULL)
else
_TEST_FILES += \
test_can_play_type_no_webm.html \
$(NULL)
endif
ifdef MOZ_WAVE
_TEST_FILES += \
test_can_play_type_wave.html \

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

@ -0,0 +1,26 @@
function check_webm(v, enabled) {
function check(type, expected) {
is(v.canPlayType(type), enabled ? expected : "no", type);
}
// WebM types
check("video/webm", "probably");
check("audio/webm", "probably");
// Supported Webm codecs
check("audio/webm; codecs=vorbis", "probably");
check("video/webm; codecs=vorbis", "probably");
check("video/webm; codecs=vorbis,vp8", "probably");
check("video/webm; codecs=vorbis,vp8.0", "probably");
check("video/webm; codecs=\"vorbis,vp8\"", "probably");
check("video/webm; codecs=\"vorbis,vp8.0\"", "probably");
check("video/webm; codecs=\"vp8, vorbis\"", "probably");
check("video/webm; codecs=\"vp8.0, vorbis\"", "probably");
check("video/webm; codecs=vp8", "probably");
check("video/webm; codecs=vp8.0", "probably");
// Unsupported WebM codecs
check("video/webm; codecs=xyz", "");
check("video/webm; codecs=xyz,vorbis", "");
check("video/webm; codecs=vorbis,xyz", "");
}

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

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=566245
-->
<head>
<title>Test for Bug 566245: WebM backend disabled</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566245">Mozill
a Bug 566245</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<video id="v" onerror="event.stopPropagation();"></video>
<pre id="test">
<script src="can_play_type_webm.js"></script>
check_webm(document.getElementById('v'), false);
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=566245
-->
<head>
<title>Test for Bug 566245: WebM backend</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566245">Mozill
a Bug 566245</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<video id="v" onerror="event.stopPropagation();"></video>
<pre id="test">
<script src="can_play_type_webm.js"></script>
<script>
check_webm(document.getElementById('v'), true);
</script>
</pre>
</body>
</html>

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

@ -161,6 +161,9 @@ pref("media.ogg.enabled", true);
#ifdef MOZ_WAVE
pref("media.wave.enabled", true);
#endif
#ifdef MOZ_WEBM
pref("media.webm.enabled", true);
#endif
// Whether to autostart a media element with an |autoplay| attribute
pref("media.autoplay.enabled", true);

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

@ -104,6 +104,7 @@
#define AUDIO_BASIC "audio/basic"
#define AUDIO_OGG "audio/ogg"
#define AUDIO_WAV "audio/x-wav"
#define AUDIO_WEBM "audio/webm"
#define IMAGE_GIF "image/gif"
#define IMAGE_JPG "image/jpeg"
@ -156,6 +157,7 @@
#define VIDEO_MPEG "video/mpeg"
#define VIDEO_OGG "video/ogg"
#define VIDEO_WEBM "video/webm"
#define APPLICATION_OGG "application/ogg"
/* x-uuencode-apple-single. QuickMail made me do this. */

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

@ -540,7 +540,11 @@ static nsExtraMimeTypeEntry extraMimeEntries [] =
{ VIDEO_OGG, "ogg", "Ogg Video" },
{ APPLICATION_OGG, "ogg", "Ogg Video"},
{ AUDIO_OGG, "oga", "Ogg Audio" },
{ AUDIO_WAV, "wav", "Waveform Audio" }
#ifdef MOZ_WEBM
{ VIDEO_WEBM, "webm", "Web Media Video" },
{ AUDIO_WEBM, "webm", "Web Media Audio" },
#endif
{ AUDIO_WAV, "wav", "Waveform Audio" },
};
#undef MAC_TYPE