eBug 1347101: P2. Don't rely on MF_E_TRANSFORM_STREAM_CHANGE result. r=mattwoodrow a=Tomcat
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 17 Mar 2017 01:21:23 +0100
changeset 503825 439ee2e4fc4ed4a82102608639d9751e376d5536
parent 503824 b0494b853b51c13deef16cb463cb30f3e4c0e1d0
child 503826 0df1cc2cd662be10fb8a4a47f908a4ff7fc3012e
child 503833 66b253393a51a589fbfbbeebbafb2313d8bae91d
child 503837 db73f13e3703d8f267048050a71ce74ce74c93cb
child 503840 a60b3552158d7e9a64bfdf155fe161b2b0738714
child 503842 98a341e19882dff74c21c1a7816f1d6349316e36
child 503872 e80d980902a1e07e7294031de11158a58ab0a9f6
child 503875 b997adc9d9f5a3ed8fda5913bc43ee021cc13a73
child 503876 95e9df3d6105b6397e944cf5662f1ac32c8daef1
child 503879 48fb683ebb83fe1b78fee13af494695e8560d53a
child 503881 634bd3c7b60c7ad996ee38ab7314071b426e3f6f
child 503882 fc57b162b9631fd52629670744029d2f944f9034
child 503884 391f506ff5d6b8ec423021db2ab034eeeec9f6ad
child 503886 6c6091c18b45580c1defa28a66effe679a3930dc
child 503887 5e3277e71e771b13179b60f77352e8a5bea56d5d
child 503892 52c349640feb254f557cdf3dd21ccd4bb9638d92
child 503906 200182ef115692c4ed2909f1a8beae8a6f19d127
child 503909 01c87b267ce3e82c0bc2410728a83649fabece91
child 503912 b05478addbf629b33c9ba79e3830520104ae715b
child 503913 b434392efee9687f2e0b2b397745c34575ed6982
child 503916 570845c2f497eb9268ec4c696a59779c12bed58b
child 503918 fe3c3b4a0742938245d19b0c90c563710993f4e3
child 503921 822048b5f5fe0d95fa48d1816ef7a68edd4be130
child 503922 d2fe0d35a5da3105d71e7c79dce1df0701909647
child 504127 285df2026b175f85b90934dd76247838618fa850
child 504478 a491242d24cefc63ddca99c243ceab1c400c7220
child 504675 54c17ed57e8d8649eff77b68c739fa29bb64d1d0
child 551469 acd216bf727c8035403c6f22fd76ac8b9684dbd4
push id50664
push userbmo:poirot.alex@gmail.com
push dateThu, 23 Mar 2017 15:53:31 +0000
reviewersmattwoodrow, Tomcat
bugs1347101
milestone55.0a1
eBug 1347101: P2. Don't rely on MF_E_TRANSFORM_STREAM_CHANGE result. r=mattwoodrow a=Tomcat Under some circumstances, and seen on Windows 8, a decoded sample can be returned without the MFT returning MF_E_TRANSFORM_STREAM_CHANGE. For historical reasons, we required that message to be returned at least once to set the output image size. This was required as the decoder used to be recycled with different video streams. This is no longer the case, we can rely on the video info instead. It also greatly simplifies the code MozReview-Commit-ID: H14KBiNWrjQ
dom/media/platforms/wmf/MFTDecoder.cpp
dom/media/platforms/wmf/MFTDecoder.h
dom/media/platforms/wmf/WMFAudioMFTManager.cpp
dom/media/platforms/wmf/WMFVideoMFTManager.cpp
dom/media/platforms/wmf/WMFVideoMFTManager.h
--- 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(aCallback, aData);
+  hr = SetDecoderOutputType(true /* match all attributes */, 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,31 +71,44 @@ MFTDecoder::GetAttributes()
 {
   RefPtr<IMFAttributes> attr;
   HRESULT hr = mDecoder->GetAttributes(getter_AddRefs(attr));
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
   return attr.forget();
 }
 
 HRESULT
-MFTDecoder::SetDecoderOutputType(ConfigureOutputCallback aCallback, void* aData)
+MFTDecoder::SetDecoderOutputType(bool aMatchAllAttributes,
+                                 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)))) {
-    BOOL resultMatch;
-    hr = mOutputType->Compare(
-      outputType, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &resultMatch);
-    if (SUCCEEDED(hr) && resultMatch == TRUE) {
+    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) {
       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);
@@ -219,23 +232,16 @@ 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,21 +82,20 @@ 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(ConfigureOutputCallback aCallback, void* aData);
+  HRESULT SetDecoderOutputType(bool aMatchAllAttributes,
+                               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,16 +175,22 @@ 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;
 }
 
@@ -228,16 +234,19 @@ 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)
+  , mImageSize(aConfig.mImage)
   , mVideoStride(0)
-  , mImageSize(aConfig.mImage)
   , mImageContainer(aImageContainer)
   , mDXVAEnabled(aDXVAEnabled)
   , mKnowsCompositor(aKnowsCompositor)
   // mVideoStride, mVideoWidth, mVideoHeight, mUseHwAccel are initialized in
   // Init().
 {
   MOZ_COUNT_CTOR(WMFVideoMFTManager);
 
@@ -567,19 +567,46 @@ 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();
+  }
+
   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;
@@ -591,36 +618,38 @@ 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);
 
-  // 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 = 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
@@ -630,28 +659,29 @@ 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,
-                                           &mLastInput);
-  NS_ENSURE_TRUE(SUCCEEDED(hr) && mLastInput != nullptr, hr);
+                                           &inputSample);
+  NS_ENSURE_TRUE(SUCCEEDED(hr) && inputSample != nullptr, hr);
 
   mLastDuration = aSample->mDuration;
   mLastTime = aSample->mTime;
   mSamplesCount++;
 
   // Forward sample data to the decoder.
-  return mDecoder->Input(mLastInput);
+  return mDecoder->Input(inputSample);
 }
 
 class SupportsConfigEvent : public Runnable {
 public:
   SupportsConfigEvent(DXVA2Manager* aDXVA2Manager,
                       IMFMediaType* aMediaType,
                       float aFramerate)
     : mDXVA2Manager(aDXVA2Manager)
@@ -712,79 +742,16 @@ 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);
@@ -968,31 +935,44 @@ 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);
-      hr = ConfigureVideoFrameGeometry();
+      // 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);
       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,40 +68,37 @@ 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.
-  VideoInfo mVideoInfo;
+  const VideoInfo mVideoInfo;
+  const nsIntSize mImageSize;
   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;