Add mute state field to AudioFrame and switch some callers to use it. Also make AudioFrame::data_ private and instead provide:
const int16_t* data() const;
int16_t* mutable_data();
- data() returns a zeroed static buffer on muted frames (to avoid unnecessary zeroing of the member buffer) and directly returns AudioFrame::data_ on unmuted frames.
- mutable_data(), lazily zeroes AudioFrame::data_ if the frame is currently muted, sets muted=false, and returns AudioFrame::data_.
These accessors serve to "force" callers to be aware of the mute state field, i.e. lazy zeroing is not the primary motivation.
This change only optimizes handling of muted frames where it is somewhat trivial to do so. Other improvements requiring more significant structural changes will come later.
BUG=webrtc:7343
TBR=henrika
Review-Url: https://codereview.webrtc.org/2750783004
Cr-Commit-Position: refs/heads/master@{#18543}
diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/acm2/acm_receiver.cc
index 553265e..a2a5eb7 100644
--- a/webrtc/modules/audio_coding/acm2/acm_receiver.cc
+++ b/webrtc/modules/audio_coding/acm2/acm_receiver.cc
@@ -154,10 +154,11 @@
// TODO(henrik.lundin) Glitches in the output may appear if the output rate
// from NetEq changes. See WebRTC issue 3923.
if (need_resampling) {
+ // TODO(yujo): handle this more efficiently for muted frames.
int samples_per_channel_int = resampler_.Resample10Msec(
- audio_frame->data_, current_sample_rate_hz, desired_freq_hz,
+ audio_frame->data(), current_sample_rate_hz, desired_freq_hz,
audio_frame->num_channels_, AudioFrame::kMaxDataSizeSamples,
- audio_frame->data_);
+ audio_frame->mutable_data());
if (samples_per_channel_int < 0) {
LOG(LERROR) << "AcmReceiver::GetAudio - Resampling audio_buffer_ failed.";
return -1;
@@ -175,7 +176,7 @@
}
// Store current audio in |last_audio_buffer_| for next time.
- memcpy(last_audio_buffer_.get(), audio_frame->data_,
+ memcpy(last_audio_buffer_.get(), audio_frame->data(),
sizeof(int16_t) * audio_frame->samples_per_channel_ *
audio_frame->num_channels_);
diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver_unittest.cc b/webrtc/modules/audio_coding/acm2/acm_receiver_unittest.cc
index 05f4e11..af23e17 100644
--- a/webrtc/modules/audio_coding/acm2/acm_receiver_unittest.cc
+++ b/webrtc/modules/audio_coding/acm2/acm_receiver_unittest.cc
@@ -103,8 +103,7 @@
frame.sample_rate_hz_ = codec.plfreq;
frame.samples_per_channel_ = codec.plfreq / 100; // 10 ms.
frame.num_channels_ = codec.channels;
- memset(frame.data_, 0, frame.samples_per_channel_ * frame.num_channels_ *
- sizeof(int16_t));
+ frame.Mute();
packet_sent_ = false;
last_packet_send_timestamp_ = timestamp_;
while (!packet_sent_) {
diff --git a/webrtc/modules/audio_coding/acm2/acm_send_test.cc b/webrtc/modules/audio_coding/acm2/acm_send_test.cc
index d5388f8..787bea8 100644
--- a/webrtc/modules/audio_coding/acm2/acm_send_test.cc
+++ b/webrtc/modules/audio_coding/acm2/acm_send_test.cc
@@ -86,13 +86,13 @@
// Insert audio and process until one packet is produced.
while (clock_.TimeInMilliseconds() < test_duration_ms_) {
clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
- RTC_CHECK(
- audio_source_->Read(input_block_size_samples_, input_frame_.data_));
+ RTC_CHECK(audio_source_->Read(input_block_size_samples_,
+ input_frame_.mutable_data()));
if (input_frame_.num_channels_ > 1) {
- InputAudioFile::DuplicateInterleaved(input_frame_.data_,
+ InputAudioFile::DuplicateInterleaved(input_frame_.data(),
input_block_size_samples_,
input_frame_.num_channels_,
- input_frame_.data_);
+ input_frame_.mutable_data());
}
data_to_send_ = false;
RTC_CHECK_GE(acm_->Add10MsData(input_frame_), 0);
diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module.cc b/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
index 551ae05..2fcbecf 100644
--- a/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
+++ b/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
@@ -325,24 +325,37 @@
int DownMix(const AudioFrame& frame,
size_t length_out_buff,
int16_t* out_buff) {
- if (length_out_buff < frame.samples_per_channel_) {
- return -1;
+ RTC_DCHECK_EQ(frame.num_channels_, 2);
+ RTC_DCHECK_GE(length_out_buff, frame.samples_per_channel_);
+
+ if (!frame.muted()) {
+ const int16_t* frame_data = frame.data();
+ for (size_t n = 0; n < frame.samples_per_channel_; ++n) {
+ out_buff[n] = static_cast<int16_t>(
+ (static_cast<int32_t>(frame_data[2 * n]) +
+ static_cast<int32_t>(frame_data[2 * n + 1])) >> 1);
+ }
+ } else {
+ memset(out_buff, 0, frame.samples_per_channel_);
}
- for (size_t n = 0; n < frame.samples_per_channel_; ++n)
- out_buff[n] = (frame.data_[2 * n] + frame.data_[2 * n + 1]) >> 1;
return 0;
}
// Mono-to-stereo can be used as in-place.
int UpMix(const AudioFrame& frame, size_t length_out_buff, int16_t* out_buff) {
- if (length_out_buff < frame.samples_per_channel_) {
- return -1;
- }
- for (size_t n = frame.samples_per_channel_; n != 0; --n) {
- size_t i = n - 1;
- int16_t sample = frame.data_[i];
- out_buff[2 * i + 1] = sample;
- out_buff[2 * i] = sample;
+ RTC_DCHECK_EQ(frame.num_channels_, 1);
+ RTC_DCHECK_GE(length_out_buff, 2 * frame.samples_per_channel_);
+
+ if (!frame.muted()) {
+ const int16_t* frame_data = frame.data();
+ for (size_t n = frame.samples_per_channel_; n != 0; --n) {
+ size_t i = n - 1;
+ int16_t sample = frame_data[i];
+ out_buff[2 * i + 1] = sample;
+ out_buff[2 * i] = sample;
+ }
+ } else {
+ memset(out_buff, 0, 2 * frame.samples_per_channel_);
}
return 0;
}
@@ -725,12 +738,13 @@
// When adding data to encoders this pointer is pointing to an audio buffer
// with correct number of channels.
- const int16_t* ptr_audio = ptr_frame->data_;
+ const int16_t* ptr_audio = ptr_frame->data();
// For pushing data to primary, point the |ptr_audio| to correct buffer.
if (!same_num_channels)
ptr_audio = input_data->buffer;
+ // TODO(yujo): Skip encode of muted frames.
input_data->input_timestamp = ptr_frame->timestamp_;
input_data->audio = ptr_audio;
input_data->length_per_channel = ptr_frame->samples_per_channel_;
@@ -744,6 +758,7 @@
// encoders has to be mono for down-mix to take place.
// |*ptr_out| will point to the pre-processed audio-frame. If no pre-processing
// is required, |*ptr_out| points to |in_frame|.
+// TODO(yujo): Make this more efficient for muted frames.
int AudioCodingModuleImpl::PreprocessToAddData(const AudioFrame& in_frame,
const AudioFrame** ptr_out) {
const bool resample =
@@ -793,13 +808,12 @@
*ptr_out = &preprocess_frame_;
preprocess_frame_.num_channels_ = in_frame.num_channels_;
int16_t audio[WEBRTC_10MS_PCM_AUDIO];
- const int16_t* src_ptr_audio = in_frame.data_;
- int16_t* dest_ptr_audio = preprocess_frame_.data_;
+ const int16_t* src_ptr_audio = in_frame.data();
if (down_mix) {
// If a resampling is required the output of a down-mix is written into a
// local buffer, otherwise, it will be written to the output frame.
- if (resample)
- dest_ptr_audio = audio;
+ int16_t* dest_ptr_audio = resample ?
+ audio : preprocess_frame_.mutable_data();
if (DownMix(in_frame, WEBRTC_10MS_PCM_AUDIO, dest_ptr_audio) < 0)
return -1;
preprocess_frame_.num_channels_ = 1;
@@ -813,7 +827,7 @@
// If it is required, we have to do a resampling.
if (resample) {
// The result of the resampler is written to output frame.
- dest_ptr_audio = preprocess_frame_.data_;
+ int16_t* dest_ptr_audio = preprocess_frame_.mutable_data();
int samples_per_channel = resampler_.Resample10Msec(
src_ptr_audio, in_frame.sample_rate_hz_, encoder_stack_->SampleRateHz(),
diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest.cc
index 99fef79..236501a 100644
--- a/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -175,9 +175,7 @@
input_frame_.samples_per_channel_ = kSampleRateHz * 10 / 1000; // 10 ms.
static_assert(kSampleRateHz * 10 / 1000 <= AudioFrame::kMaxDataSizeSamples,
"audio frame too small");
- memset(input_frame_.data_,
- 0,
- input_frame_.samples_per_channel_ * sizeof(input_frame_.data_[0]));
+ input_frame_.Mute();
ASSERT_EQ(0, acm_->RegisterTransportCallback(&packet_cb_));
@@ -698,7 +696,7 @@
// TODO(kwiberg): Use std::copy here. Might be complications because AFAICS
// this call confuses the number of samples with the number of bytes, and
// ends up copying only half of what it should.
- memcpy(input_frame_.data_, audio_loop_.GetNextBlock().data(),
+ memcpy(input_frame_.mutable_data(), audio_loop_.GetNextBlock().data(),
kNumSamples10ms);
AudioCodingModuleTestOldApi::InsertAudio();
}