Bug 1338032 - Report VP9 in MP4 not supported in HTMLMediaElement.canPlayType, but supported in MediaSource.isTypeSupported(). r=gerald draft
authorChris Pearce <cpearce@mozilla.com>
Wed, 15 Feb 2017 13:37:01 +1300
changeset 484250 cd7a18ff3080b2c9bca90b6935b03bfa2c8d780f
parent 484213 3b8423eb84b3292f52681b94ab1888af69670ec8
child 545746 6268c31b79ecfdf1564fbd644188f982c3c28174
push id45430
push usercpearce@mozilla.com
push dateWed, 15 Feb 2017 02:30:26 +0000
reviewersgerald
bugs1338032, 1339204
milestone54.0a1
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
dom/html/HTMLMediaElement.cpp
dom/media/test/test_can_play_type_mpeg.html
--- 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 + "'");
   }