From fbc9c3a8b286e7d08254cb189c644bb2d6525b48 Mon Sep 17 00:00:00 2001 From: Maire Reavy Date: Thu, 3 Jan 2013 18:37:55 -0500 Subject: [PATCH] bug 822956: Handle audio chunks that aren't 10ms in duration r=ekr --- .../src/mediapipeline/MediaPipeline.cpp | 62 ++++++++++++++++++- .../src/mediapipeline/MediaPipeline.h | 14 ++++- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp index 6affdc25a56..9e39712e2de 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp @@ -691,8 +691,66 @@ void MediaPipelineTransmit::PipelineListener::ProcessAudioChunk( } } - MOZ_MTLOG(PR_LOG_DEBUG, "Sending an audio frame"); - conduit->SendAudioFrame(samples.get(), chunk.mDuration, rate, 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 + + if (samplenum_10ms_ != rate/100) { + // Determine number of samples in 10 ms from the rate: + samplenum_10ms_ = rate/100; + // If we switch sample rates (e.g. if we switch codecs), + // we throw away what was in the sample_10ms_buffer at the old rate + samples_10ms_buffer_ = new int16_t[samplenum_10ms_]; + 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(); + + 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)); + buffer_current_ += tocpy; + samples_tmp += tocpy; + chunk_remaining -= tocpy; + + if (buffer_current_ == samplenum_10ms_) { + // Send out the audio buffer we just finished filling + conduit->SendAudioFrame(samples_10ms_buffer_, samplenum_10ms_, rate, 0); + buffer_current_ = 0; + } else { + // We still don't have enough data to send a buffer + return; + } + } + + // Now send (more) frames if there is more than 10ms of input left + tocpy = (chunk_remaining / samplenum_10ms_) * samplenum_10ms_; + if (tocpy > 0) { + conduit->SendAudioFrame(samples_tmp, tocpy, rate, 0); + samples_tmp += tocpy; + chunk_remaining = chunk.mDuration - tocpy; + } + // Copy what remains for the next run + + MOZ_ASSERT(chunk_remaining < samplenum_10ms_); + + if (chunk_remaining) { + memcpy(samples_10ms_buffer_, samples_tmp, chunk_remaining * sizeof(int16_t)); + buffer_current_ = chunk_remaining; + } + } #ifdef MOZILLA_INTERNAL_API diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h index cf5c168256f..1cf472f9be1 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h @@ -253,9 +253,10 @@ class MediaPipelineTransmit : public MediaPipeline { class PipelineListener : public MediaStreamListener { public: PipelineListener(const RefPtr& conduit) - : conduit_(conduit), active_(false) {} + : conduit_(conduit), active_(false), samples_10ms_buffer_(nullptr), + buffer_current_(0), samplenum_10ms_(0){} - // XXX. This is not thread-safe but the hazard is just + // XXX. This is not thread-safe but the hazard is just // that active_ = true takes a while to propagate. Revisit // when 823600 lands. void SetActive(bool active) { active_ = active; } @@ -277,6 +278,15 @@ class MediaPipelineTransmit : public MediaPipeline { #endif RefPtr conduit_; volatile bool active_; + + // These vars handle breaking audio samples into exact 10ms chunks: + // The buffer of 10ms audio samples that we will send once full + // (can be carried over from one call to another). + nsAutoArrayPtr samples_10ms_buffer_; + // The location of the pointer within that buffer (in units of samples). + int64_t buffer_current_; + // The number of samples in a 10ms audio chunk. + int64_t samplenum_10ms_; }; private: