Bug 1096716 - Delay buffer frame calculation in WMF audio decoder until after UpdateOutputType to avoid using obsolete rate/channel values. r=cpearce, a=lmandel
authorMatthew Gregan <kinetik@flim.org>
Tue, 11 Nov 2014 14:17:09 +1300
changeset 226038 49f10dbc7d69
parent 226037 2b08e1cb3c6f
child 226039 609915862295
push id4119
push userryanvm@gmail.com
push date2014-11-12 22:22 +0000
treeherdermozilla-beta@f2dd9f2a084a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, lmandel
bugs1096716
milestone34.0
Bug 1096716 - Delay buffer frame calculation in WMF audio decoder until after UpdateOutputType to avoid using obsolete rate/channel values. r=cpearce, a=lmandel
content/media/fmp4/wmf/WMFAudioMFTManager.cpp
--- a/content/media/fmp4/wmf/WMFAudioMFTManager.cpp
+++ b/content/media/fmp4/wmf/WMFAudioMFTManager.cpp
@@ -216,19 +216,16 @@ WMFAudioMFTManager::Output(int64_t aStre
   hr = sample->ConvertToContiguousBuffer(byRef(buffer));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   BYTE* data = nullptr; // Note: *data will be owned by the IMFMediaBuffer, we don't need to free it.
   DWORD maxLength = 0, currentLength = 0;
   hr = buffer->Lock(&data, &maxLength, &currentLength);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-  int32_t numSamples = currentLength / mAudioBytesPerSample;
-  int32_t numFrames = numSamples / mAudioChannels;
-
   // Sometimes when starting decoding, the AAC decoder gives us samples
   // with a negative timestamp. AAC does usually have preroll (or encoder
   // delay) encoded into its bitstream, but the amount encoded to the stream
   // is variable, and it not signalled in-bitstream. There is sometimes
   // signalling in the MP4 container what the preroll amount, but it's
   // inconsistent. It looks like WMF's AAC encoder may take this into
   // account, so strip off samples with a negative timestamp to get us
   // to a 0-timestamp start. This seems to maintain A/V sync, so we can run
@@ -240,38 +237,40 @@ WMFAudioMFTManager::Output(int64_t aStre
 
   // If this sample block comes after a discontinuity (i.e. a gap or seek)
   // reset the frame counters, and capture the timestamp. Future timestamps
   // will be offset from this block's timestamp.
   UINT32 discontinuity = false;
   int32_t numFramesToStrip = 0;
   sample->GetUINT32(MFSampleExtension_Discontinuity, &discontinuity);
   if (mMustRecaptureAudioPosition || discontinuity) {
+    // Update the output type, in case this segment has a different
+    // rate. This also triggers on the first sample, which can have a
+    // different rate than is advertised in the container, and sometimes we
+    // don't get a MF_E_TRANSFORM_STREAM_CHANGE when the rate changes.
+    hr = UpdateOutputType();
+    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
     mAudioFrameSum = 0;
     LONGLONG timestampHns = 0;
     hr = sample->GetSampleTime(&timestampHns);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
     hr = HNsToFrames(timestampHns, mAudioRate, &mAudioFrameOffset);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
     if (mAudioFrameOffset < 0) {
       // First sample has a negative timestamp. Strip off the samples until
       // we reach positive territory.
       numFramesToStrip = -mAudioFrameOffset;
       mAudioFrameOffset = 0;
     }
     mMustRecaptureAudioPosition = false;
-
-    // Also update the output type, in case this segment has a different
-    // rate. This also triggers on the first sample, which can have a
-    // different rate than is advertised in the container, and sometimes
-    // we don't get a MF_E_TRANSFORM_STREAM_CHANGE when the rate changes.
-    hr = UpdateOutputType();
-    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   }
   MOZ_ASSERT(numFramesToStrip >= 0);
+  int32_t numSamples = currentLength / mAudioBytesPerSample;
+  int32_t numFrames = numSamples / mAudioChannels;
   int32_t offset = std::min<int32_t>(numFramesToStrip, numFrames);
   numFrames -= offset;
   numSamples -= offset * mAudioChannels;
   MOZ_ASSERT(numFrames >= 0);
   MOZ_ASSERT(numSamples >= 0);
   if (numFrames == 0) {
     // All data from this chunk stripped, loop back and try to output the next
     // frame, if possible.