Bug 1162364 - Detect and abort MF_E_TRANSFORM_STREAM_CHANGE infinite loops. r=cpearce, a=lizzard
authorKarl Tomlinson <karlt+@karlt.net>
Fri, 22 May 2015 15:23:00 +1200
changeset 266218 35fad3eed522
parent 266217 d787fb3b86be
child 266219 ffc4a84bbcdf
push id4792
push userryanvm@gmail.com
push date2015-06-10 20:30 +0000
treeherdermozilla-beta@f137fedd1455 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, lizzard
bugs1162364
milestone39.0
Bug 1162364 - Detect and abort MF_E_TRANSFORM_STREAM_CHANGE infinite loops. r=cpearce, a=lizzard
dom/media/fmp4/wmf/WMFAudioMFTManager.cpp
dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
--- a/dom/media/fmp4/wmf/WMFAudioMFTManager.cpp
+++ b/dom/media/fmp4/wmf/WMFAudioMFTManager.cpp
@@ -204,24 +204,30 @@ WMFAudioMFTManager::UpdateOutputType()
 
 HRESULT
 WMFAudioMFTManager::Output(int64_t aStreamOffset,
                            nsRefPtr<MediaData>& aOutData)
 {
   aOutData = nullptr;
   RefPtr<IMFSample> sample;
   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 = 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;
     }
     break;
   }
 
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   RefPtr<IMFMediaBuffer> buffer;
--- a/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
@@ -463,32 +463,38 @@ WMFVideoMFTManager::CreateD3DVideoFrame(
 // Blocks until decoded sample is produced by the deoder.
 HRESULT
 WMFVideoMFTManager::Output(int64_t aStreamOffset,
                            nsRefPtr<MediaData>& aOutData)
 {
   RefPtr<IMFSample> sample;
   HRESULT hr;
   aOutData = nullptr;
+  int typeChangeCount = 0;
 
   // 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();
       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)) {
       break;
     }
     // Else unexpected error, assert, and bail.
     NS_WARNING("WMFVideoMFTManager::Output() unexpected error");
     return E_FAIL;