Bug 1264199: P2. Ensure the AudioStream only ever receive the same content format. r=kinetik
☠☠ backed out by 30c5dbcee7dd ☠ ☠
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 13 Apr 2016 17:30:23 +1000
changeset 317752 d3677ae4c8ecb9aa68e750bb1966cef127edc6dc
parent 317751 d08288654ec9a96d7b685c18efac351551d8fc35
child 317753 02f781a573b45dba4b69ab7b7b52d76f4243d658
push id9480
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 17:12:58 +0000
treeherdermozilla-aurora@0d6a91c76a9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1264199
milestone48.0a1
Bug 1264199: P2. Ensure the AudioStream only ever receive the same content format. r=kinetik The audio is automatically converted to always match the format of the first processed sample. This is a temporary approach, as it would be preferred to use a final sampling rate not causing too much quality loss. MozReview-Commit-ID: Lo3827aon43
dom/media/mediasink/DecodedAudioDataSink.cpp
--- a/dom/media/mediasink/DecodedAudioDataSink.cpp
+++ b/dom/media/mediasink/DecodedAudioDataSink.cpp
@@ -47,20 +47,16 @@ DecodedAudioDataSink::DecodedAudioDataSi
   , mFramesParsed(0)
   , mLastEndTime(0)
 {
   bool resampling = gfxPrefs::AudioSinkResampling();
   uint32_t resamplingRate = gfxPrefs::AudioSinkResampleRate();
   mOutputRate = resampling ? resamplingRate : mInfo.mRate;
   mOutputChannels = mInfo.mChannels > 2 && gfxPrefs::AudioSinkForceStereo()
                       ? 2 : mInfo.mChannels;
-  mConverter =
-    MakeUnique<AudioConverter>(
-      AudioConfig(mInfo.mChannels, mInfo.mRate),
-      AudioConfig(mOutputChannels, mOutputRate));
 }
 
 DecodedAudioDataSink::~DecodedAudioDataSink()
 {
 }
 
 RefPtr<GenericPromise>
 DecodedAudioDataSink::Init(const PlaybackParams& aParams)
@@ -312,23 +308,46 @@ DecodedAudioDataSink::NotifyAudioNeeded(
     RefPtr<AudioData> data =
       dont_AddRef(AudioQueue().PopFront().take()->As<AudioData>());
 
     // Ignore the element with 0 frames and try next.
     if (!data->mFrames) {
       continue;
     }
 
-    // Ignore invalid samples.
-    if (data->mRate != mConverter->InputConfig().Rate() ||
-        data->mChannels != mConverter->InputConfig().Channels()) {
-      NS_WARNING(nsPrintfCString(
-        "mismatched sample format, data=%p rate=%u channels=%u frames=%u",
-        data->mAudioData.get(), data->mRate, data->mChannels, data->mFrames).get());
-      continue;
+    if (!mConverter ||
+        (data->mRate != mConverter->InputConfig().Rate() ||
+         data->mChannels != mConverter->InputConfig().Channels())) {
+      SINK_LOG_V("Audio format changed from %u@%uHz to %u@%uHz",
+                 mConverter? mConverter->InputConfig().Channels() : 0,
+                 mConverter ? mConverter->InputConfig().Rate() : 0,
+                 data->mChannels, data->mRate);
+
+      // mFramesParsed indicates the current playtime in frames at the current
+      // input sampling rate. Recalculate it per the new sampling rate.
+      if (mFramesParsed) {
+        // We minimize overflow.
+        uint32_t oldRate = mConverter->InputConfig().Rate();
+        uint32_t newRate = data->mRate;
+        int64_t major = mFramesParsed / oldRate;
+        int64_t remainder = mFramesParsed % oldRate;
+        CheckedInt64 result =
+          CheckedInt64(remainder) * newRate / oldRate + major * oldRate;
+        if (!result.isValid()) {
+          NS_WARNING("Int overflow in DecodedAudioDataSink");
+          mErrored = true;
+          return;
+        }
+        mFramesParsed = result.value();
+      }
+
+      mConverter =
+        MakeUnique<AudioConverter>(
+          AudioConfig(data->mChannels, data->mRate),
+          AudioConfig(mOutputChannels, mOutputRate));
     }
 
     // See if there's a gap in the audio. If there is, push silence into the
     // audio hardware, so we can play across the gap.
     // Calculate the timestamp of the next chunk of audio in numbers of
     // samples.
     CheckedInt64 sampleTime = UsecsToFrames(data->mTime - mStartTime,
                                             data->mRate);