Bug 1264199: P8. Handle potential resampling errors. r=kinetik draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 19 Apr 2016 14:53:18 +1000
changeset 356287 4130d3707ef8f207b63ff78b241fb76a8c7c2838
parent 356286 4d2bca2c8531b5dcf8a0e4e634f20c0e353078fa
child 356288 a28e014db660c5d2d886a0aa90b9c1640fc2fefc
push id16486
push userbmo:jyavenard@mozilla.com
push dateTue, 26 Apr 2016 02:36:37 +0000
reviewerskinetik
bugs1264199
milestone49.0a1
Bug 1264199: P8. Handle potential resampling errors. r=kinetik The speex resampler can never return an error in its current state. But just in case and to handle any future changes to the speex resampler. Also ensure that we can never access a stale speex resampler. MozReview-Commit-ID: CEME0AA9ghK
dom/media/AudioConverter.cpp
--- a/dom/media/AudioConverter.cpp
+++ b/dom/media/AudioConverter.cpp
@@ -100,20 +100,17 @@ void
 }
 
 void
 AudioConverter::ReOrderInterleavedChannels(void* aOut, const void* aIn,
                                            size_t aFrames) const
 {
   MOZ_DIAGNOSTIC_ASSERT(mIn.Channels() == mOut.Channels());
 
-  if (mOut.Layout() == mIn.Layout()) {
-    return;
-  }
-  if (mOut.Channels() == 1) {
+  if (mOut.Channels() == 1 || mOut.Layout() == mIn.Layout()) {
     // If channel count is 1, planar and non-planar formats are the same and
     // there's nothing to reorder.
     if (aOut != aIn) {
       memmove(aOut, aIn, FramesOutToBytes(aFrames));
     }
     return;
   }
 
@@ -248,29 +245,38 @@ size_t
 AudioConverter::ResampleAudio(void* aOut, const void* aIn, size_t aFrames)
 {
   if (!mResampler) {
     return 0;
   }
   uint32_t outframes = ResampleRecipientFrames(aFrames);
   uint32_t inframes = aFrames;
 
+  int error;
   if (mOut.Format() == AudioConfig::FORMAT_FLT) {
     const float* in = reinterpret_cast<const float*>(aIn);
     float* out = reinterpret_cast<float*>(aOut);
-    speex_resampler_process_interleaved_float(mResampler, in, &inframes,
-                                              out, &outframes);
+    error =
+      speex_resampler_process_interleaved_float(mResampler, in, &inframes,
+                                                out, &outframes);
   } else if (mOut.Format() == AudioConfig::FORMAT_S16) {
     const int16_t* in = reinterpret_cast<const int16_t*>(aIn);
     int16_t* out = reinterpret_cast<int16_t*>(aOut);
-    speex_resampler_process_interleaved_int(mResampler, in, &inframes,
-                                            out, &outframes);
+    error =
+      speex_resampler_process_interleaved_int(mResampler, in, &inframes,
+                                              out, &outframes);
   } else {
     MOZ_DIAGNOSTIC_ASSERT(false, "Unsupported data type");
   }
+  MOZ_ASSERT(error == RESAMPLER_ERR_SUCCESS);
+  if (error != RESAMPLER_ERR_SUCCESS) {
+    speex_resampler_destroy(mResampler);
+    mResampler = nullptr;
+    return 0;
+  }
   MOZ_ASSERT(inframes == aFrames, "Some frames will be dropped");
   return outframes;
 }
 
 void
 AudioConverter::RecreateResampler()
 {
   if (mResampler) {
@@ -293,18 +299,17 @@ AudioConverter::RecreateResampler()
 
 size_t
 AudioConverter::DrainResampler(void* aOut)
 {
   if (!mResampler) {
     return 0;
   }
   int frames = speex_resampler_get_input_latency(mResampler);
-  AlignedByteBuffer buffer(FramesOutToSamples(frames) *
-                           AudioConfig::SampleSize(mOut.Format()));
+  AlignedByteBuffer buffer(FramesOutToBytes(frames));
   if (!buffer) {
     // OOM
     return 0;
   }
   frames = ResampleAudio(aOut, buffer.Data(), frames);
   // Tore down the resampler as it's easier than handling follow-up.
   RecreateResampler();
   return frames;
@@ -353,16 +358,19 @@ AudioConverter::UpmixAudio(void* aOut, c
 }
 
 size_t
 AudioConverter::ResampleRecipientFrames(size_t aFrames) const
 {
   if (!aFrames && mIn.Rate() != mOut.Rate()) {
     // The resampler will be drained, account for frames currently buffered
     // in the resampler.
+    if (!mResampler) {
+      return 0;
+    }
     return speex_resampler_get_output_latency(mResampler);
   } else {
     return (uint64_t)aFrames * mOut.Rate() / mIn.Rate() + 1;
   }
 }
 
 size_t
 AudioConverter::FramesOutToSamples(size_t aFrames) const