Merge mozilla-central to autoland on a CLOSED TREE
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 23 Mar 2017 14:47:13 +0100
changeset 399692 b48c0e99e716c9fdef9823bd1f4336b818ccf51b
parent 399691 6c10860d02ad59b71aec82eca931e791404a7de9 (current diff)
parent 399627 fcfdeb52c2b2f020631fd47b5b02ea0be50d4027 (diff)
child 399693 fff5c87922e682f2f5f0fb7cf9ef07adf4bb759c
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone55.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
Merge mozilla-central to autoland on a CLOSED TREE
--- a/dom/media/platforms/wmf/MFTDecoder.cpp
+++ b/dom/media/platforms/wmf/MFTDecoder.cpp
@@ -46,17 +46,17 @@ MFTDecoder::SetMediaTypes(IMFMediaType* 
                           void* aData)
 {
   mOutputType = aOutputType;
 
   // Set the input type to the one the caller gave us...
   HRESULT hr = mDecoder->SetInputType(0, aInputType, 0);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-  hr = SetDecoderOutputType(true /* match all attributes */, aCallback, aData);
+  hr = SetDecoderOutputType(aCallback, aData);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   hr = mDecoder->GetInputStreamInfo(0, &mInputStreamInfo);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
@@ -71,44 +71,31 @@ MFTDecoder::GetAttributes()
 {
   RefPtr<IMFAttributes> attr;
   HRESULT hr = mDecoder->GetAttributes(getter_AddRefs(attr));
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
   return attr.forget();
 }
 
 HRESULT
-MFTDecoder::SetDecoderOutputType(bool aMatchAllAttributes,
-                                 ConfigureOutputCallback aCallback,
-                                 void* aData)
+MFTDecoder::SetDecoderOutputType(ConfigureOutputCallback aCallback, void* aData)
 {
   NS_ENSURE_TRUE(mDecoder != nullptr, E_POINTER);
 
-  GUID currentSubtype = {0};
-  HRESULT hr = mOutputType->GetGUID(MF_MT_SUBTYPE, &currentSubtype);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
   // Iterate the enumerate the output types, until we find one compatible
   // with what we need.
+  HRESULT hr;
   RefPtr<IMFMediaType> outputType;
   UINT32 typeIndex = 0;
   while (SUCCEEDED(mDecoder->GetOutputAvailableType(
     0, typeIndex++, getter_AddRefs(outputType)))) {
-    GUID outSubtype = {0};
-    hr = outputType->GetGUID(MF_MT_SUBTYPE, &outSubtype);
-    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
-    BOOL resultMatch = currentSubtype == outSubtype;
-
-    if (resultMatch && aMatchAllAttributes) {
-      hr = mOutputType->Compare(outputType, MF_ATTRIBUTES_MATCH_OUR_ITEMS,
-                                &resultMatch);
-      NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-    }
-    if (resultMatch == TRUE) {
+    BOOL resultMatch;
+    hr = mOutputType->Compare(
+      outputType, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &resultMatch);
+    if (SUCCEEDED(hr) && resultMatch == TRUE) {
       if (aCallback) {
         hr = aCallback(outputType, aData);
         NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
       }
       hr = mDecoder->SetOutputType(0, outputType, 0);
       NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
       hr = mDecoder->GetOutputStreamInfo(0, &mOutputStreamInfo);
@@ -232,16 +219,23 @@ MFTDecoder::Output(RefPtr<IMFSample>* aO
   if (output.pEvents) {
     // We must release this, as per the IMFTransform::ProcessOutput()
     // MSDN documentation.
     output.pEvents->Release();
     output.pEvents = nullptr;
   }
 
   if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
+    // Type change, probably geometric aperture change.
+    // Reconfigure decoder output type, so that GetOutputMediaType()
+    // returns the new type, and return the error code to caller.
+    // This is an expected failure, so don't warn on encountering it.
+    hr = SetDecoderOutputType(nullptr, nullptr);
+    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+    // Return the error, so that the caller knows to retry.
     return MF_E_TRANSFORM_STREAM_CHANGE;
   }
 
   if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
     // Not enough input to produce output. This is an expected failure,
     // so don't warn on encountering it.
     return hr;
   }
--- a/dom/media/platforms/wmf/MFTDecoder.h
+++ b/dom/media/platforms/wmf/MFTDecoder.h
@@ -82,20 +82,21 @@ public:
 
   // Sends a flush message to the MFT. This causes it to discard all
   // input data. Use before seeking.
   HRESULT Flush();
 
   // Sends a message to the MFT.
   HRESULT SendMFTMessage(MFT_MESSAGE_TYPE aMsg, ULONG_PTR aData);
 
-  HRESULT SetDecoderOutputType(bool aMatchAllAttributes,
-                               ConfigureOutputCallback aCallback,
-                               void* aData);
+
+  HRESULT SetDecoderOutputType(ConfigureOutputCallback aCallback, void* aData);
 private:
+
+
   HRESULT CreateOutputSample(RefPtr<IMFSample>* aOutSample);
 
   MFT_INPUT_STREAM_INFO mInputStreamInfo;
   MFT_OUTPUT_STREAM_INFO mOutputStreamInfo;
 
   RefPtr<IMFTransform> mDecoder;
 
   RefPtr<IMFMediaType> mOutputType;
--- a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
@@ -175,22 +175,16 @@ WMFAudioMFTManager::Init()
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = outputType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float);
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   hr = outputType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32);
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
-  hr = outputType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, mAudioChannels);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
-
-  hr = outputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), false);
-
   hr = decoder->SetMediaTypes(inputType, outputType);
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   mDecoder = decoder;
 
   return true;
 }
 
@@ -234,19 +228,16 @@ WMFAudioMFTManager::Output(int64_t aStre
   HRESULT hr;
   int typeChangeCount = 0;
   while (true) {
     hr = mDecoder->Output(&sample);
     if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
       return hr;
     }
     if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
-      hr = mDecoder->SetDecoderOutputType(true /* check all attribute */,
-                                          nullptr,
-                                          nullptr);
       hr = UpdateOutputType();
       NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
       // Catch infinite loops, but some decoders perform at least 2 stream
       // changes on consecutive calls, so be permissive.
       // 100 is arbitrarily > 2.
       NS_ENSURE_TRUE(typeChangeCount < 100, MF_E_TRANSFORM_STREAM_CHANGE);
       ++typeChangeCount;
       continue;
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -104,18 +104,18 @@ GetCompositorBackendType(layers::KnowsCo
 }
 
 WMFVideoMFTManager::WMFVideoMFTManager(
                             const VideoInfo& aConfig,
                             layers::KnowsCompositor* aKnowsCompositor,
                             layers::ImageContainer* aImageContainer,
                             bool aDXVAEnabled)
   : mVideoInfo(aConfig)
+  , mVideoStride(0)
   , mImageSize(aConfig.mImage)
-  , mVideoStride(0)
   , mImageContainer(aImageContainer)
   , mDXVAEnabled(aDXVAEnabled)
   , mKnowsCompositor(aKnowsCompositor)
   // mVideoStride, mVideoWidth, mVideoHeight, mUseHwAccel are initialized in
   // Init().
 {
   MOZ_COUNT_CTOR(WMFVideoMFTManager);
 
@@ -567,46 +567,19 @@ WMFVideoMFTManager::InitInternal()
     Telemetry::Accumulate(Telemetry::MEDIA_DECODER_BACKEND_USED,
                           uint32_t(media::MediaDecoderBackend::WMFSoftware));
   }
 
   mDecoder = decoder;
   hr = SetDecoderMediaTypes();
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
-  RefPtr<IMFMediaType> outputType;
-  hr = mDecoder->GetOutputMediaType(outputType);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
-  if (mUseHwAccel && !CanUseDXVA(outputType)) {
-    mDXVAEnabled = false;
-    // DXVA initialization actually failed, re-do initialisation.
-    return InitInternal(aForceD3D9);
-  }
-
   LOG("Video Decoder initialized, Using DXVA: %s",
       (mUseHwAccel ? "Yes" : "No"));
 
-  if (mDXVA2Manager) {
-    hr = mDXVA2Manager->ConfigureForSize(mVideoInfo.ImageRect().width,
-                                         mVideoInfo.ImageRect().height);
-    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-  } else {
-    GetDefaultStride(outputType, mVideoInfo.ImageRect().width, &mVideoStride);
-  }
-  LOG("WMFVideoMFTManager frame geometry stride=%u picture=(%d, %d, %d, %d) "
-      "display=(%d,%d)",
-      mVideoStride,
-      mVideoInfo.ImageRect().x,
-      mVideoInfo.ImageRect().y,
-      mVideoInfo.ImageRect().width,
-      mVideoInfo.ImageRect().height,
-      mVideoInfo.mDisplay.width,
-      mVideoInfo.mDisplay.height);
-
   return true;
 }
 
 HRESULT
 WMFVideoMFTManager::SetDecoderMediaTypes()
 {
   // Setup the input/output media types.
   RefPtr<IMFMediaType> inputType;
@@ -618,38 +591,36 @@ WMFVideoMFTManager::SetDecoderMediaTypes
 
   hr = inputType->SetGUID(MF_MT_SUBTYPE, GetMediaSubtypeGUID());
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   hr = inputType->SetUINT32(MF_MT_INTERLACE_MODE,
                             MFVideoInterlace_MixedInterlaceOrProgressive);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-  hr = inputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+  // MSFT MFT needs this frame size set for VP9?
+  if (mStreamType == VP9 || mStreamType == VP8) {
+    hr =
+      inputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
+    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-  hr = MFSetAttributeSize(inputType,
-                          MF_MT_FRAME_SIZE,
-                          mVideoInfo.ImageRect().width,
-                          mVideoInfo.ImageRect().height);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+    hr = MFSetAttributeSize(inputType,
+                            MF_MT_FRAME_SIZE,
+                            mVideoInfo.ImageRect().width,
+                            mVideoInfo.ImageRect().height);
+    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+  }
 
   RefPtr<IMFMediaType> outputType;
   hr = wmf::MFCreateMediaType(getter_AddRefs(outputType));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   hr = outputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-  hr = MFSetAttributeSize(outputType,
-                          MF_MT_FRAME_SIZE,
-                          mVideoInfo.ImageRect().width,
-                          mVideoInfo.ImageRect().height);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
   GUID outputSubType = mUseHwAccel ? MFVideoFormat_NV12 : MFVideoFormat_YV12;
   hr = outputType->SetGUID(MF_MT_SUBTYPE, outputSubType);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   return mDecoder->SetMediaTypes(inputType, outputType);
 }
 
 HRESULT
@@ -659,29 +630,28 @@ WMFVideoMFTManager::Input(MediaRawData* 
     return E_FAIL;
   }
 
   if (!mDecoder) {
     // This can happen during shutdown.
     return E_FAIL;
   }
 
-  RefPtr<IMFSample> inputSample;
   HRESULT hr = mDecoder->CreateInputSample(aSample->Data(),
                                            uint32_t(aSample->Size()),
                                            aSample->mTime,
-                                           &inputSample);
-  NS_ENSURE_TRUE(SUCCEEDED(hr) && inputSample != nullptr, hr);
+                                           &mLastInput);
+  NS_ENSURE_TRUE(SUCCEEDED(hr) && mLastInput != nullptr, hr);
 
   mLastDuration = aSample->mDuration;
   mLastTime = aSample->mTime;
   mSamplesCount++;
 
   // Forward sample data to the decoder.
-  return mDecoder->Input(inputSample);
+  return mDecoder->Input(mLastInput);
 }
 
 class SupportsConfigEvent : public Runnable {
 public:
   SupportsConfigEvent(DXVA2Manager* aDXVA2Manager,
                       IMFMediaType* aMediaType,
                       float aFramerate)
     : mDXVA2Manager(aDXVA2Manager)
@@ -742,16 +712,79 @@ WMFVideoMFTManager::CanUseDXVA(IMFMediaT
     // This logic needs to run on the main thread
     mozilla::SyncRunnable::DispatchToThread(
       SystemGroup::EventTargetFor(mozilla::TaskCategory::Other), event);
   }
 
   return event->mSupportsConfig;
 }
 
+HRESULT
+WMFVideoMFTManager::ConfigureVideoFrameGeometry()
+{
+  RefPtr<IMFMediaType> mediaType;
+  HRESULT hr = mDecoder->GetOutputMediaType(mediaType);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
+  // If we enabled/disabled DXVA in response to a resolution
+  // change then we need to renegotiate our media types,
+  // and resubmit our previous frame (since the MFT appears
+  // to lose it otherwise).
+  if (mUseHwAccel && !CanUseDXVA(mediaType)) {
+    mDXVAEnabled = false;
+    if (!Init()) {
+      return E_FAIL;
+    }
+
+    mDecoder->Input(mLastInput);
+    return S_OK;
+  }
+
+  // Verify that the video subtype is what we expect it to be.
+  // When using hardware acceleration/DXVA2 the video format should
+  // be NV12, which is DXVA2's preferred format. For software decoding
+  // we use YV12, as that's easier for us to stick into our rendering
+  // pipeline than NV12. NV12 has interleaved UV samples, whereas YV12
+  // is a planar format.
+  GUID videoFormat;
+  hr = mediaType->GetGUID(MF_MT_SUBTYPE, &videoFormat);
+  NS_ENSURE_TRUE(videoFormat == MFVideoFormat_NV12 || !mUseHwAccel, E_FAIL);
+  NS_ENSURE_TRUE(videoFormat == MFVideoFormat_YV12 || mUseHwAccel, E_FAIL);
+
+  nsIntRect pictureRegion;
+  hr = GetPictureRegion(mediaType, pictureRegion);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
+  UINT32 width = pictureRegion.width;
+  UINT32 height = pictureRegion.height;
+  mImageSize = nsIntSize(width, height);
+  // Calculate and validate the picture region and frame dimensions after
+  // scaling by the pixel aspect ratio.
+  pictureRegion = mVideoInfo.ScaledImageRect(width, height);
+  if (!IsValidVideoRegion(mImageSize, pictureRegion, mVideoInfo.mDisplay)) {
+    // Video track's frame sizes will overflow. Ignore the video track.
+    return E_FAIL;
+  }
+
+  if (mDXVA2Manager) {
+    hr = mDXVA2Manager->ConfigureForSize(width, height);
+    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+  }
+
+  // Success! Save state.
+  GetDefaultStride(mediaType, width, &mVideoStride);
+
+  LOG("WMFVideoMFTManager frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d)",
+      width, height,
+      mVideoStride,
+      pictureRegion.x, pictureRegion.y, pictureRegion.width, pictureRegion.height,
+      mVideoInfo.mDisplay.width, mVideoInfo.mDisplay.height);
+
+  return S_OK;
+}
 
 HRESULT
 WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
                                           int64_t aStreamOffset,
                                           VideoData** aOutVideoData)
 {
   NS_ENSURE_TRUE(aSample, E_POINTER);
   NS_ENSURE_TRUE(aOutVideoData, E_POINTER);
@@ -935,44 +968,31 @@ WMFVideoMFTManager::Output(int64_t aStre
 
   // Loop until we decode a sample, or an unexpected error that we can't
   // handle occurs.
   while (true) {
     hr = mDecoder->Output(&sample);
     if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
       return MF_E_TRANSFORM_NEED_MORE_INPUT;
     }
-
     if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
+      // Video stream output type change. Probably a geometric apperature
+      // change. Reconfigure the video geometry, so that we output the
+      // correct size frames.
       MOZ_ASSERT(!sample);
-      // Video stream output type change, probably geometric aperture change.
-      // We must reconfigure the decoder output type.
-      hr = mDecoder->SetDecoderOutputType(false /* check all attribute */,
-                                          nullptr,
-                                          nullptr);
+      hr = ConfigureVideoFrameGeometry();
       NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
-      if (!mUseHwAccel) {
-        // The stride may have changed, recheck for it.
-        RefPtr<IMFMediaType> outputType;
-        hr = mDecoder->GetOutputMediaType(outputType);
-        NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-        hr = GetDefaultStride(outputType, mVideoInfo.ImageRect().width,
-                              &mVideoStride);
-        NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-      }
       // Catch infinite loops, but some decoders perform at least 2 stream
       // changes on consecutive calls, so be permissive.
       // 100 is arbitrarily > 2.
       NS_ENSURE_TRUE(typeChangeCount < 100, MF_E_TRANSFORM_STREAM_CHANGE);
       // Loop back and try decoding again...
       ++typeChangeCount;
       continue;
     }
-
     if (SUCCEEDED(hr)) {
       if (!sample) {
         LOG("Video MFTDecoder returned success but no output!");
         // On some machines/input the MFT returns success but doesn't output
         // a video frame. If we detect this, try again, but only up to a
         // point; after 250 failures, give up. Note we count all failures
         // over the life of the decoder, as we may end up exiting with a
         // NEED_MORE_INPUT and coming back to hit the same error. So just
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.h
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.h
@@ -68,37 +68,40 @@ public:
 
 private:
   bool ValidateVideoInfo();
 
   bool InitializeDXVA();
 
   bool InitInternal();
 
+  HRESULT ConfigureVideoFrameGeometry();
+
   HRESULT CreateBasicVideoFrame(IMFSample* aSample,
                                 int64_t aStreamOffset,
                                 VideoData** aOutVideoData);
 
   HRESULT CreateD3DVideoFrame(IMFSample* aSample,
                               int64_t aStreamOffset,
                               VideoData** aOutVideoData);
 
   HRESULT SetDecoderMediaTypes();
 
   bool CanUseDXVA(IMFMediaType* aType);
 
   // Video frame geometry.
-  const VideoInfo mVideoInfo;
-  const nsIntSize mImageSize;
+  VideoInfo mVideoInfo;
   uint32_t mVideoStride;
+  nsIntSize mImageSize;
 
   RefPtr<layers::ImageContainer> mImageContainer;
   RefPtr<layers::KnowsCompositor> mKnowsCompositor;
   nsAutoPtr<DXVA2Manager> mDXVA2Manager;
 
+  RefPtr<IMFSample> mLastInput;
   float mLastDuration;
   int64_t mLastTime = 0;
   bool mDraining = false;
   int64_t mSamplesCount = 0;
 
   bool mDXVAEnabled;
   bool mUseHwAccel;