Bug 1338032 - Report VP9 in MP4 not supported in HTMLMediaElement.canPlayType, but supported in MediaSource.isTypeSupported(). r=gerald
We don't have an MP4 demuxer that can handle VP9 in non-fragmented MP4. Jay's
change to DecoderTraits in
Bug 1339204 will make MediaSource.isTypeSupported()
report that it can play VP9 in MP4. But we don't want to report that we can
play VP9 in MP4 in HTMLMediaElement.canPlayType(), as usually canPlayType() is
used with the intention to check for whether fragmented MP4 can be played. So
we need to special case canPlayType() so that it reports that it can't play
VP9 in MP4.
The upcoming Rust demuxer will be able to support VP9 in MP4, so once we've
enabled that, we can confidently report in canPlayType that we support VP9 in
MP4.
MozReview-Commit-ID: G0q5ho5N2wr
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -4508,26 +4508,44 @@ void HTMLMediaElement::UnbindFromTree(bo
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([self] () {
if (self->mUnboundFromTree) {
self->Pause();
}
});
RunInStableState(task);
}
+static bool
+IsVP9InMP4(const MediaContainerType& aContainerType)
+{
+ const MediaContainerType mimeType(aContainerType.Type());
+ return DecoderTraits::IsMP4SupportedType(mimeType,
+ /* DecoderDoctorDiagnostics* */ nullptr)
+ && IsVP9CodecString(aContainerType.ExtendedType().Codecs().AsString());
+}
+
/* static */
CanPlayStatus
HTMLMediaElement::GetCanPlay(const nsAString& aType,
DecoderDoctorDiagnostics* aDiagnostics)
{
Maybe<MediaContainerType> containerType = MakeMediaContainerType(aType);
if (!containerType) {
return CANPLAY_NO;
}
- return DecoderTraits::CanHandleContainerType(*containerType, aDiagnostics);
+ CanPlayStatus status = DecoderTraits::CanHandleContainerType(*containerType, aDiagnostics);
+ if (status == CANPLAY_YES && IsVP9InMP4(*containerType)) {
+ // We don't have a demuxer that can handle VP9 in non-fragmented MP4.
+ // So special-case VP9 in MP4 here, as we assume canPlayType() implies
+ // non-fragmented MP4 anyway. Note we report that we can play VP9
+ // in MP4 in MediaSource.isTypeSupported(), as the fragmented MP4
+ // demuxer can handle VP9 in fragmented MP4.
+ return CANPLAY_NO;
+ }
+ return status;
}
NS_IMETHODIMP
HTMLMediaElement::CanPlayType(const nsAString& aType, nsAString& aResult)
{
DecoderDoctorDiagnostics diagnostics;
CanPlayStatus canPlay = GetCanPlay(aType, &diagnostics);
diagnostics.StoreFormatDiagnostics(
--- a/dom/media/test/test_can_play_type_mpeg.html
+++ b/dom/media/test/test_can_play_type_mpeg.html
@@ -83,16 +83,33 @@ function check_mp4(v, enabled) {
check("audio/mp4; codecs=\"opus\"", "probably");
check("audio/mp4; codecs=opus", "probably");
// Flac.
// Not available on Android yet.
var expectedResult = IsSupportedAndroid() ? "" : "probably";
check("audio/mp4; codecs=\"flac\"", expectedResult);
check("audio/mp4; codecs=flac", expectedResult);
+
+ // VP9.
+ // Note: canPlayType assumes non-fragmented MP4. Once we support VP9 in
+ // non-fragmented MP4, we need to change this to report supported.
+ [ "video/mp4; codecs=vp9",
+ "video/mp4; codecs=\"vp9\"",
+ "video/mp4; codecs=\"vp9.0\""
+ ].forEach((codec) => {
+ // canPlayType should not support VP9 in MP4...
+ check(codec, "");
+ // But VP9 in MP4 is supported in MSE.
+ ok(MediaSource.isTypeSupported(codec), "VP9 in MP4 should be supported in MSE");
+ });
+
+ check("video/mp4; codecs=vp9", "");
+ check("video/mp4; codecs=\"vp9\"", "");
+ check("video/mp4; codecs=\"vp9.0\"", "");
}
function check_mp3(v, enabled) {
function check(type, expected) {
var ex = enabled ? expected : "";
is(v.canPlayType(type), ex, type + "='" + ex + "'");
}