Bug 1497951 - P5. Add VPXChangeMonitor and detect VPx inband resolution change. r=bryce
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 07 Nov 2018 13:49:30 +0000
changeset 444863 9b18bd5c4c8b27d090d68e9350caf0401b8c05cd
parent 444862 80643ce074f619a1b210781d8e0e695e3b3e3372
child 444864 4e832384a4643c4c0fd39148a9ec6374c4f2092b
push id35005
push useraiakab@mozilla.com
push dateWed, 07 Nov 2018 21:49:53 +0000
treeherdermozilla-central@12afa29e9c8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbryce
bugs1497951
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1497951 - P5. Add VPXChangeMonitor and detect VPx inband resolution change. r=bryce Depends on D10911 Differential Revision: https://phabricator.services.mozilla.com/D10912
dom/media/platforms/PDMFactory.cpp
dom/media/platforms/wrappers/MediaChangeMonitor.cpp
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -39,16 +39,17 @@
 #include "MediaInfo.h"
 
 #include "AgnosticDecoderModule.h"
 #include "EMEDecoderModule.h"
 
 #include "DecoderDoctorDiagnostics.h"
 
 #include "MP4Decoder.h"
+#include "VPXDecoder.h"
 #include "mozilla/dom/RemoteVideoDecoder.h"
 
 #include "H264.h"
 
 #include <functional>
 
 namespace mozilla {
 
@@ -289,24 +290,26 @@ PDMFactory::CreateDecoderWithPDM(Platfor
 
   if (!config.IsVideo()) {
     *result = MediaResult(
       NS_ERROR_DOM_MEDIA_FATAL_ERR,
       RESULT_DETAIL("Decoder configuration error, expected audio or video."));
     return nullptr;
   }
 
-  if (MP4Decoder::IsH264(config.mMimeType) && !aParams.mUseNullDecoder.mUse &&
-      !aParams.mNoWrapper.mDontUseWrapper) {
+  if ((MP4Decoder::IsH264(config.mMimeType) ||
+       VPXDecoder::IsVPX(config.mMimeType)) &&
+      !aParams.mUseNullDecoder.mUse && !aParams.mNoWrapper.mDontUseWrapper) {
     RefPtr<MediaChangeMonitor> h = new MediaChangeMonitor(aPDM, aParams);
     const MediaResult result = h->GetLastError();
     if (NS_SUCCEEDED(result) || result == NS_ERROR_NOT_INITIALIZED) {
       // The MediaChangeMonitor either successfully created the wrapped decoder,
-      // or there wasn't enough AVCC data to do so. Otherwise, there was some
-      // problem, for example WMF DLLs were missing.
+      // or there wasn't enough initialization data to do so (such as what can
+      // happen with AVC3). Otherwise, there was some problem, for example WMF
+      // DLLs were missing.
       m = h.forget();
     } else if (aParams.mError) {
       *aParams.mError = result;
     }
   } else {
     m = aPDM->CreateVideoDecoder(aParams);
   }
 
--- a/dom/media/platforms/wrappers/MediaChangeMonitor.cpp
+++ b/dom/media/platforms/wrappers/MediaChangeMonitor.cpp
@@ -8,16 +8,17 @@
 
 #include "AnnexB.h"
 #include "DecoderDoctorDiagnostics.h"
 #include "H264.h"
 #include "ImageContainer.h"
 #include "MP4Decoder.h"
 #include "MediaInfo.h"
 #include "PDMFactory.h"
+#include "VPXDecoder.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/TaskQueue.h"
 
 namespace mozilla
 {
 
 // H264ChangeMonitor is used to ensure that only AVCC or AnnexB is fed to the
 // underlying MediaDataDecoder. The H264ChangeMonitor allows playback of content
@@ -133,34 +134,98 @@ public:
 
     VideoInfo mCurrentConfig;
     bool mNeedKeyframe = true;
     uint32_t mStreamID = 0;
     RefPtr<TrackInfoSharedPtr> mTrackInfo;
     RefPtr<MediaByteBuffer> mPreviousExtraData;
 };
 
+class VPXChangeMonitor : public MediaChangeMonitor::CodecChangeMonitor
+{
+public:
+  explicit VPXChangeMonitor(const VideoInfo& aInfo)
+    : mCurrentConfig(aInfo)
+    , mCodec(VPXDecoder::IsVP8(aInfo.mMimeType) ? VPXDecoder::Codec::VP8
+                                                : VPXDecoder::Codec::VP9)
+  {
+  }
+
+  bool CanBeInstantiated() const override
+  {
+    return true;
+  }
+
+  MediaResult CheckForChange(MediaRawData* aSample) override
+  {
+    // Don't look at encrypted content.
+    if (aSample->mCrypto.mValid) {
+      return NS_OK;
+    }
+    // For both VP8 and VP9, we only look for resolution changes
+    // on keyframes. Other resolution changes are invalid.
+    if (!aSample->mKeyframe) {
+      return NS_OK;
+    }
+
+    auto dimensions = VPXDecoder::GetFrameSize(
+      MakeSpan<const uint8_t>(aSample->Data(), aSample->Size()), mCodec);
+
+    if (!mSize) {
+      mSize = Some(dimensions);
+      return NS_OK;
+    }
+    if (mSize.ref() == dimensions) {
+      return NS_OK;
+    }
+    mSize = Some(dimensions);
+    mCurrentConfig.mDisplay = dimensions;
+
+    return NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER;
+  }
+
+  const TrackInfo& Config() const override
+  {
+    return mCurrentConfig;
+  }
+
+  MediaResult PrepareSample(MediaDataDecoder::ConversionRequired aConversion,
+                            MediaRawData* aSample) override
+  {
+    return NS_OK;
+  }
+
+  private:
+    VideoInfo mCurrentConfig;
+    const VPXDecoder::Codec mCodec;
+    Maybe<gfx::IntSize> mSize;
+};
+
 MediaChangeMonitor::MediaChangeMonitor(PlatformDecoderModule* aPDM,
                                        const CreateDecoderParams& aParams)
   : mPDM(aPDM)
   , mCurrentConfig(aParams.VideoConfig())
   , mKnowsCompositor(aParams.mKnowsCompositor)
   , mImageContainer(aParams.mImageContainer)
   , mTaskQueue(aParams.mTaskQueue)
   , mDecoder(nullptr)
   , mGMPCrashHelper(aParams.mCrashHelper)
   , mLastError(NS_OK)
   , mType(aParams.mType)
   , mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent)
   , mDecoderOptions(aParams.mOptions)
   , mRate(aParams.mRate)
 {
   mInConstructor = true;
-  MOZ_ASSERT(MP4Decoder::IsH264(mCurrentConfig.mMimeType));
-  mChangeMonitor = MakeUnique<H264ChangeMonitor>(mCurrentConfig);
+  if (VPXDecoder::IsVPX(mCurrentConfig.mMimeType)) {
+    mChangeMonitor = MakeUnique<VPXChangeMonitor>(mCurrentConfig);
+  } else {
+    MOZ_ASSERT(MP4Decoder::IsH264(mCurrentConfig.mMimeType));
+    mChangeMonitor = MakeUnique<H264ChangeMonitor>(mCurrentConfig);
+  }
   mLastError = CreateDecoder(aParams.mDiagnostics);
   mInConstructor = false;
 }
 
 MediaChangeMonitor::~MediaChangeMonitor()
 {
 }