Bug 901633 - Part 5 - Make MediaPipeline downmix and properly convert audio for webrtc.org code. r=jesup
authorPaul Adenot <paul@paul.cx>
Wed, 29 Jul 2015 18:39:56 +0200
changeset 260327 b026e7f47823ffbc1f32798f8ce5ba00f964e7f5
parent 260326 2e896277675f898506d34b612b7c56d423c9f1ff
child 260328 10869420ec36d5db74ad3e40d26616c56f137895
push id29307
push userryanvm@gmail.com
push dateWed, 02 Sep 2015 01:01:53 +0000
treeherdermozilla-central@e2eb0442ece9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs901633
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 901633 - Part 5 - Make MediaPipeline downmix and properly convert audio for webrtc.org code. r=jesup This means converting to int16, interleaving, and down-mixing to stereo (or keeping it to mono if it's already mono of course).
media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -943,44 +943,43 @@ NewData(MediaStreamGraph* graph, TrackID
     // Ignore
   }
 }
 
 void MediaPipelineTransmit::PipelineListener::ProcessAudioChunk(
     AudioSessionConduit *conduit,
     TrackRate rate,
     AudioChunk& chunk) {
-  // TODO(ekr@rtfm.com): Do more than one channel
-  nsAutoArrayPtr<int16_t> samples(new int16_t[chunk.mDuration]);
 
-  if (enabled_ && chunk.mBuffer) {
-    switch (chunk.mBufferFormat) {
+  // Convert to interleaved, 16-bits integer audio, with a maximum of two
+  // channels (since the WebRTC.org code below makes the assumption that the
+  // input audio is either mono or stereo).
+  uint32_t outputChannels = chunk.ChannelCount() == 1 ? 1 : 2;
+  nsAutoArrayPtr<int16_t> convertedSamples(
+      new int16_t[chunk.mDuration * outputChannels]);
+
+  // If this track is not enabled, simply ignore the data in the chunk.
+  if (!enabled_) {
+    chunk.mBufferFormat = AUDIO_FORMAT_SILENCE;
+  }
+
+  switch (chunk.mBufferFormat) {
       case AUDIO_FORMAT_FLOAT32:
-        {
-          const float* buf = static_cast<const float *>(chunk.mChannelData[0]);
-          ConvertAudioSamplesWithScale(buf, static_cast<int16_t*>(samples),
-                                       chunk.mDuration, chunk.mVolume);
-        }
+        DownmixAndInterleave(chunk.ChannelData<float>(),
+                             chunk.mDuration, chunk.mVolume, outputChannels,
+                             convertedSamples.get());
         break;
       case AUDIO_FORMAT_S16:
-        {
-          const short* buf = static_cast<const short *>(chunk.mChannelData[0]);
-          ConvertAudioSamplesWithScale(buf, samples, chunk.mDuration, chunk.mVolume);
-        }
+        DownmixAndInterleave(chunk.ChannelData<int16_t>(),
+                             chunk.mDuration, chunk.mVolume, outputChannels,
+                             convertedSamples.get());
         break;
       case AUDIO_FORMAT_SILENCE:
-        memset(samples, 0, chunk.mDuration * sizeof(samples[0]));
+        PodZero(convertedSamples.get(), chunk.mDuration * outputChannels);
         break;
-      default:
-        MOZ_ASSERT_UNREACHABLE("Unexpected AudioSampleFormat");
-        return;
-    }
-  } else {
-    // This means silence.
-    memset(samples, 0, chunk.mDuration * sizeof(samples[0]));
   }
 
   MOZ_ASSERT(!(rate%100)); // rate should be a multiple of 100
 
   // Check if the rate has changed since the last time we came through
   // I realize it may be overkill to check if the rate has changed, but
   // I believe it is possible (e.g. if we change sources) and it costs us
   // very little to handle this case
@@ -994,17 +993,17 @@ void MediaPipelineTransmit::PipelineList
     buffer_current_ = 0;
   }
 
   // Vars to handle the non-sunny-day case (where the audio chunks
   // we got are not multiples of 10ms OR there were samples left over
   // from the last run)
   int64_t chunk_remaining;
   int64_t tocpy;
-  int16_t *samples_tmp = samples.get();
+  int16_t *samples_tmp = convertedSamples.get();
 
   chunk_remaining = chunk.mDuration;
 
   MOZ_ASSERT(chunk_remaining >= 0);
 
   if (buffer_current_) {
     tocpy = std::min(chunk_remaining, samplenum_10ms_ - buffer_current_);
     memcpy(&samples_10ms_buffer_[buffer_current_], samples_tmp, tocpy * sizeof(int16_t));