diff --git a/webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.cc b/webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.cc index ec3f4fcddc..e4a34a7294 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.cc +++ b/webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.cc @@ -159,7 +159,7 @@ void AcmReceiveTestOldApi::Run() { while (clock_.TimeInMilliseconds() < packet->time_ms()) { AudioFrame output_frame; EXPECT_EQ(0, acm_->PlayoutData10Ms(output_freq_hz_, &output_frame)); - EXPECT_EQ(output_freq_hz_, output_frame.sample_rate_hz_); + ASSERT_EQ(output_freq_hz_, output_frame.sample_rate_hz_); const size_t samples_per_block = static_cast(output_freq_hz_ * 10 / 1000); EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_); diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/acm2/acm_receiver.cc index 39d8a0d175..02d165a2d5 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.cc +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.cc @@ -18,6 +18,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/format_macros.h" #include "webrtc/base/logging.h" +#include "webrtc/base/safe_conversions.h" #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" #include "webrtc/common_types.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" @@ -120,14 +121,12 @@ bool IsCng(int codec_id) { AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) : last_audio_decoder_(nullptr), previous_audio_activity_(AudioFrame::kVadPassive), - audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), neteq_(NetEq::Create(config.neteq_config)), vad_enabled_(config.neteq_config.enable_post_decode_vad), clock_(config.clock), resampled_last_output_frame_(true) { assert(clock_); - memset(audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples); memset(last_audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples); } @@ -208,19 +207,11 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header, } int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) { - enum NetEqOutputType type; - size_t samples_per_channel; - size_t num_channels; - // Accessing members, take the lock. rtc::CritScope lock(&crit_sect_); - // Always write the output to |audio_buffer_| first. - if (neteq_->GetAudio(AudioFrame::kMaxDataSizeSamples, - audio_buffer_.get(), - &samples_per_channel, - &num_channels, - &type) != NetEq::kOK) { + enum NetEqOutputType type; + if (neteq_->GetAudio(audio_frame, &type) != NetEq::kOK) { LOG(LERROR) << "AcmReceiver::GetAudio - NetEq Failed."; return -1; } @@ -236,44 +227,42 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) { int16_t temp_output[AudioFrame::kMaxDataSizeSamples]; int samples_per_channel_int = resampler_.Resample10Msec( last_audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz, - num_channels, AudioFrame::kMaxDataSizeSamples, temp_output); + audio_frame->num_channels_, AudioFrame::kMaxDataSizeSamples, + temp_output); if (samples_per_channel_int < 0) { LOG(LERROR) << "AcmReceiver::GetAudio - " "Resampling last_audio_buffer_ failed."; return -1; } - samples_per_channel = static_cast(samples_per_channel_int); } - // The audio in |audio_buffer_| is tansferred to |audio_frame_| below, either - // through resampling, or through straight memcpy. // TODO(henrik.lundin) Glitches in the output may appear if the output rate // from NetEq changes. See WebRTC issue 3923. if (need_resampling) { int samples_per_channel_int = resampler_.Resample10Msec( - audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz, - num_channels, AudioFrame::kMaxDataSizeSamples, audio_frame->data_); + audio_frame->data_, current_sample_rate_hz, desired_freq_hz, + audio_frame->num_channels_, AudioFrame::kMaxDataSizeSamples, + audio_frame->data_); if (samples_per_channel_int < 0) { LOG(LERROR) << "AcmReceiver::GetAudio - Resampling audio_buffer_ failed."; return -1; } - samples_per_channel = static_cast(samples_per_channel_int); + audio_frame->samples_per_channel_ = + static_cast(samples_per_channel_int); + audio_frame->sample_rate_hz_ = desired_freq_hz; + RTC_DCHECK_EQ( + audio_frame->sample_rate_hz_, + rtc::checked_cast(audio_frame->samples_per_channel_ * 100)); resampled_last_output_frame_ = true; } else { resampled_last_output_frame_ = false; // We might end up here ONLY if codec is changed. - memcpy(audio_frame->data_, - audio_buffer_.get(), - samples_per_channel * num_channels * sizeof(int16_t)); } - // Swap buffers, so that the current audio is stored in |last_audio_buffer_| - // for next time. - audio_buffer_.swap(last_audio_buffer_); - - audio_frame->num_channels_ = num_channels; - audio_frame->samples_per_channel_ = samples_per_channel; - audio_frame->sample_rate_hz_ = static_cast(samples_per_channel * 100); + // Store current audio in |last_audio_buffer_| for next time. + memcpy(last_audio_buffer_.get(), audio_frame->data_, + sizeof(int16_t) * audio_frame->samples_per_channel_ * + audio_frame->num_channels_); // Should set |vad_activity| before calling SetAudioFrameActivityAndType(). audio_frame->vad_activity_ = previous_audio_activity_; @@ -284,6 +273,7 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) { // Computes the RTP timestamp of the first sample in |audio_frame| from // |GetPlayoutTimestamp|, which is the timestamp of the last sample of // |audio_frame|. + // TODO(henrik.lundin) Move setting of audio_frame->timestamp_ inside NetEq. uint32_t playout_timestamp = 0; if (GetPlayoutTimestamp(&playout_timestamp)) { audio_frame->timestamp_ = playout_timestamp - diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.h b/webrtc/modules/audio_coding/acm2/acm_receiver.h index 476f29dd71..ae3969bda0 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.h +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.h @@ -280,9 +280,6 @@ class AcmReceiver { const Decoder* last_audio_decoder_ GUARDED_BY(crit_sect_); AudioFrame::VADActivity previous_audio_activity_ GUARDED_BY(crit_sect_); ACMResampler resampler_ GUARDED_BY(crit_sect_); - // Used in GetAudio, declared as member to avoid allocating every 10ms. - // TODO(henrik.lundin) Stack-allocate in GetAudio instead? - std::unique_ptr audio_buffer_ GUARDED_BY(crit_sect_); std::unique_ptr last_audio_buffer_ GUARDED_BY(crit_sect_); CallStatistics call_stats_ GUARDED_BY(crit_sect_); NetEq* neteq_; diff --git a/webrtc/modules/audio_coding/neteq/audio_multi_vector.cc b/webrtc/modules/audio_coding/neteq/audio_multi_vector.cc index 1381895085..bd38c43903 100644 --- a/webrtc/modules/audio_coding/neteq/audio_multi_vector.cc +++ b/webrtc/modules/audio_coding/neteq/audio_multi_vector.cc @@ -14,6 +14,7 @@ #include +#include "webrtc/base/checks.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -130,9 +131,7 @@ size_t AudioMultiVector::ReadInterleaved(size_t length, size_t AudioMultiVector::ReadInterleavedFromIndex(size_t start_index, size_t length, int16_t* destination) const { - if (!destination) { - return 0; - } + RTC_DCHECK(destination); size_t index = 0; // Number of elements written to |destination| so far. assert(start_index <= Size()); start_index = std::min(start_index, Size()); diff --git a/webrtc/modules/audio_coding/neteq/audio_multi_vector_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_multi_vector_unittest.cc index 1921dc25d7..864c2b2c29 100644 --- a/webrtc/modules/audio_coding/neteq/audio_multi_vector_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/audio_multi_vector_unittest.cc @@ -208,16 +208,6 @@ TEST_P(AudioMultiVectorTest, ReadInterleaved) { delete [] output; } -// Try to read to a NULL pointer. Expected to return 0. -TEST_P(AudioMultiVectorTest, ReadInterleavedToNull) { - AudioMultiVector vec(num_channels_); - vec.PushBackInterleaved(array_interleaved_, interleaved_length_); - int16_t* output = NULL; - // Read 5 samples. - size_t read_samples = 5; - EXPECT_EQ(0u, vec.ReadInterleaved(read_samples, output)); -} - // Test the PopFront method. TEST_P(AudioMultiVectorTest, PopFront) { AudioMultiVector vec(num_channels_); diff --git a/webrtc/modules/audio_coding/neteq/include/neteq.h b/webrtc/modules/audio_coding/neteq/include/neteq.h index 1322223970..dff09db3db 100644 --- a/webrtc/modules/audio_coding/neteq/include/neteq.h +++ b/webrtc/modules/audio_coding/neteq/include/neteq.h @@ -23,6 +23,7 @@ namespace webrtc { // Forward declarations. +class AudioFrame; struct WebRtcRTPHeader; struct NetEqNetworkStatistics { @@ -163,16 +164,12 @@ class NetEq { uint32_t receive_timestamp) = 0; // Instructs NetEq to deliver 10 ms of audio data. The data is written to - // |output_audio|, which can hold (at least) |max_length| elements. - // The number of channels that were written to the output is provided in - // the output variable |num_channels|, and each channel contains - // |samples_per_channel| elements. If more than one channel is written, - // the samples are interleaved. + // |audio_frame|. All data in |audio_frame| is wiped; |data_|, |interleaved_|, + // |num_channels_|, and |samples_per_channel_| are updated upon success. If + // an error is returned, some fields may not have been updated. // The speech type is written to |type|, if |type| is not NULL. // Returns kOK on success, or kFail in case of an error. - virtual int GetAudio(size_t max_length, int16_t* output_audio, - size_t* samples_per_channel, size_t* num_channels, - NetEqOutputType* type) = 0; + virtual int GetAudio(AudioFrame* audio_frame, NetEqOutputType* type) = 0; // Associates |rtp_payload_type| with |codec| and |codec_name|, and stores the // information in the codec database. Returns 0 on success, -1 on failure. diff --git a/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc index 73eff4524b..7712b244bd 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc @@ -17,6 +17,7 @@ #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" #include "webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/test/testsupport/fileutils.h" namespace webrtc { @@ -188,25 +189,19 @@ class NetEqExternalVsInternalDecoderTest : public NetEqExternalDecoderUnitTest, void GetAndVerifyOutput() override { NetEqOutputType output_type; - size_t samples_per_channel; - size_t num_channels; // Get audio from internal decoder instance. EXPECT_EQ(NetEq::kOK, - neteq_internal_->GetAudio(kMaxBlockSize, - output_internal_, - &samples_per_channel, - &num_channels, - &output_type)); - EXPECT_EQ(1u, num_channels); + neteq_internal_->GetAudio(&output_internal_, &output_type)); + EXPECT_EQ(1u, output_internal_.num_channels_); EXPECT_EQ(static_cast(kOutputLengthMs * sample_rate_hz_ / 1000), - samples_per_channel); + output_internal_.samples_per_channel_); // Get audio from external decoder instance. - samples_per_channel = GetOutputAudio(kMaxBlockSize, output_, &output_type); + GetOutputAudio(&output_, &output_type); - for (size_t i = 0; i < samples_per_channel; ++i) { - ASSERT_EQ(output_[i], output_internal_[i]) << - "Diff in sample " << i << "."; + for (size_t i = 0; i < output_.samples_per_channel_; ++i) { + ASSERT_EQ(output_.data_[i], output_internal_.data_[i]) + << "Diff in sample " << i << "."; } } @@ -227,8 +222,8 @@ class NetEqExternalVsInternalDecoderTest : public NetEqExternalDecoderUnitTest, private: int sample_rate_hz_; std::unique_ptr neteq_internal_; - int16_t output_internal_[kMaxBlockSize]; - int16_t output_[kMaxBlockSize]; + AudioFrame output_internal_; + AudioFrame output_; }; TEST_F(NetEqExternalVsInternalDecoderTest, RunTest) { @@ -291,9 +286,9 @@ class LargeTimestampJumpTest : public NetEqExternalDecoderUnitTest, } void GetAndVerifyOutput() override { - size_t num_samples; + AudioFrame output; NetEqOutputType output_type; - num_samples = GetOutputAudio(kMaxBlockSize, output_, &output_type); + GetOutputAudio(&output, &output_type); UpdateState(output_type); if (test_state_ == kExpandPhase || test_state_ == kFadedExpandPhase) { @@ -301,8 +296,9 @@ class LargeTimestampJumpTest : public NetEqExternalDecoderUnitTest, return; } - for (size_t i = 0; i < num_samples; ++i) { - if (output_[i] != 0) + ASSERT_EQ(1u, output.num_channels_); + for (size_t i = 0; i < output.samples_per_channel_; ++i) { + if (output.data_[i] != 0) return; } EXPECT_TRUE(false) @@ -321,9 +317,6 @@ class LargeTimestampJumpTest : public NetEqExternalDecoderUnitTest, } TestStates test_state_; - - private: - int16_t output_[kMaxBlockSize]; }; TEST_F(LargeTimestampJumpTest, JumpLongerThanHalfRange) { diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc index 93699821cf..f899d07217 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -148,13 +148,13 @@ int NetEqImpl::InsertSyncPacket(const WebRtcRTPHeader& rtp_header, return kOK; } -int NetEqImpl::GetAudio(size_t max_length, int16_t* output_audio, - size_t* samples_per_channel, size_t* num_channels, - NetEqOutputType* type) { +int NetEqImpl::GetAudio(AudioFrame* audio_frame, NetEqOutputType* type) { TRACE_EVENT0("webrtc", "NetEqImpl::GetAudio"); rtc::CritScope lock(&crit_sect_); - int error = GetAudioInternal(max_length, output_audio, samples_per_channel, - num_channels); + int error = GetAudioInternal(audio_frame); + RTC_DCHECK_EQ( + audio_frame->sample_rate_hz_, + rtc::checked_cast(audio_frame->samples_per_channel_ * 100)); if (error != 0) { error_code_ = error; return kFail; @@ -162,8 +162,7 @@ int NetEqImpl::GetAudio(size_t max_length, int16_t* output_audio, if (type) { *type = LastOutputType(); } - last_output_sample_rate_hz_ = - rtc::checked_cast(*samples_per_channel * 100); + last_output_sample_rate_hz_ = audio_frame->sample_rate_hz_; RTC_DCHECK(last_output_sample_rate_hz_ == 8000 || last_output_sample_rate_hz_ == 16000 || last_output_sample_rate_hz_ == 32000 || @@ -739,10 +738,7 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, return 0; } -int NetEqImpl::GetAudioInternal(size_t max_length, - int16_t* output, - size_t* samples_per_channel, - size_t* num_channels) { +int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame) { PacketList packet_list; DtmfEvent dtmf_event; Operations operation; @@ -857,16 +853,18 @@ int NetEqImpl::GetAudioInternal(size_t max_length, // Extract data from |sync_buffer_| to |output|. size_t num_output_samples_per_channel = output_size_samples_; size_t num_output_samples = output_size_samples_ * sync_buffer_->Channels(); - if (num_output_samples > max_length) { - LOG(LS_WARNING) << "Output array is too short. " << max_length << " < " << - output_size_samples_ << " * " << sync_buffer_->Channels(); - num_output_samples = max_length; - num_output_samples_per_channel = max_length / sync_buffer_->Channels(); + if (num_output_samples > AudioFrame::kMaxDataSizeSamples) { + LOG(LS_WARNING) << "Output array is too short. " + << AudioFrame::kMaxDataSizeSamples << " < " + << output_size_samples_ << " * " + << sync_buffer_->Channels(); + num_output_samples = AudioFrame::kMaxDataSizeSamples; + num_output_samples_per_channel = + AudioFrame::kMaxDataSizeSamples / sync_buffer_->Channels(); } - const size_t samples_from_sync = - sync_buffer_->GetNextAudioInterleaved(num_output_samples_per_channel, - output); - *num_channels = sync_buffer_->Channels(); + sync_buffer_->GetNextAudioInterleaved(num_output_samples_per_channel, + audio_frame); + audio_frame->sample_rate_hz_ = fs_hz_; if (sync_buffer_->FutureLength() < expand_->overlap_length()) { // The sync buffer should always contain |overlap_length| samples, but now // too many samples have been extracted. Reinstall the |overlap_length| @@ -877,22 +875,22 @@ int NetEqImpl::GetAudioInternal(size_t max_length, sync_buffer_->set_next_index(sync_buffer_->next_index() - missing_lookahead_samples); } - if (samples_from_sync != output_size_samples_) { - LOG(LS_ERROR) << "samples_from_sync (" << samples_from_sync + if (audio_frame->samples_per_channel_ != output_size_samples_) { + LOG(LS_ERROR) << "audio_frame->samples_per_channel_ (" + << audio_frame->samples_per_channel_ << ") != output_size_samples_ (" << output_size_samples_ << ")"; // TODO(minyue): treatment of under-run, filling zeros - memset(output, 0, num_output_samples * sizeof(int16_t)); - *samples_per_channel = output_size_samples_; + memset(audio_frame->data_, 0, num_output_samples * sizeof(int16_t)); return kSampleUnderrun; } - *samples_per_channel = output_size_samples_; // Should always have overlap samples left in the |sync_buffer_|. RTC_DCHECK_GE(sync_buffer_->FutureLength(), expand_->overlap_length()); if (play_dtmf) { - return_value = DtmfOverdub(dtmf_event, sync_buffer_->Channels(), output); + return_value = + DtmfOverdub(dtmf_event, sync_buffer_->Channels(), audio_frame->data_); } // Update the background noise parameters if last operation wrote data diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.h b/webrtc/modules/audio_coding/neteq/neteq_impl.h index 78c678c00b..4575864c0d 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.h +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.h @@ -96,19 +96,7 @@ class NetEqImpl : public webrtc::NetEq { int InsertSyncPacket(const WebRtcRTPHeader& rtp_header, uint32_t receive_timestamp) override; - // Instructs NetEq to deliver 10 ms of audio data. The data is written to - // |output_audio|, which can hold (at least) |max_length| elements. - // The number of channels that were written to the output is provided in - // the output variable |num_channels|, and each channel contains - // |samples_per_channel| elements. If more than one channel is written, - // the samples are interleaved. - // The speech type is written to |type|, if |type| is not NULL. - // Returns kOK on success, or kFail in case of an error. - int GetAudio(size_t max_length, - int16_t* output_audio, - size_t* samples_per_channel, - size_t* num_channels, - NetEqOutputType* type) override; + int GetAudio(AudioFrame* audio_frame, NetEqOutputType* type) override; int RegisterPayloadType(NetEqDecoder codec, const std::string& codec_name, @@ -211,16 +199,9 @@ class NetEqImpl : public webrtc::NetEq { bool is_sync_packet) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); - // Delivers 10 ms of audio data. The data is written to |output|, which can - // hold (at least) |max_length| elements. The number of channels that were - // written to the output is provided in the output variable |num_channels|, - // and each channel contains |samples_per_channel| elements. If more than one - // channel is written, the samples are interleaved. + // Delivers 10 ms of audio data. The data is written to |audio_frame|. // Returns 0 on success, otherwise an error code. - int GetAudioInternal(size_t max_length, - int16_t* output, - size_t* samples_per_channel, - size_t* num_channels) + int GetAudioInternal(AudioFrame* audio_frame) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); // Provides a decision to the GetAudioInternal method. The decision what to diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc index f734883635..cb4405d16d 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -28,6 +28,7 @@ #include "webrtc/modules/audio_coding/neteq/preemptive_expand.h" #include "webrtc/modules/audio_coding/neteq/sync_buffer.h" #include "webrtc/modules/audio_coding/neteq/timestamp_scaler.h" +#include "webrtc/modules/include/module_common_types.h" using ::testing::AtLeast; using ::testing::Return; @@ -464,16 +465,11 @@ TEST_F(NetEqImplTest, VerifyTimestampPropagation) { // Pull audio once. const size_t kMaxOutputSize = static_cast(10 * kSampleRateHz / 1000); - int16_t output[kMaxOutputSize]; - size_t samples_per_channel; - size_t num_channels; + AudioFrame output; NetEqOutputType type; - EXPECT_EQ( - NetEq::kOK, - neteq_->GetAudio( - kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); - ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputNormal, type); // Start with a simple check that the fake decoder is behaving as expected. @@ -485,7 +481,8 @@ TEST_F(NetEqImplTest, VerifyTimestampPropagation) { // timestamp should match the playout timestamp. uint32_t timestamp = 0; EXPECT_TRUE(neteq_->GetPlayoutTimestamp(×tamp)); - EXPECT_EQ(rtp_header.header.timestamp + output[samples_per_channel - 1], + EXPECT_EQ(rtp_header.header.timestamp + + output.data_[output.samples_per_channel_ - 1], timestamp); // Check the timestamp for the last value in the sync buffer. This should @@ -497,8 +494,9 @@ TEST_F(NetEqImplTest, VerifyTimestampPropagation) { // Check that the number of samples still to play from the sync buffer add // up with what was already played out. - EXPECT_EQ(kPayloadLengthSamples - output[samples_per_channel - 1], - sync_buffer->FutureLength()); + EXPECT_EQ( + kPayloadLengthSamples - output.data_[output.samples_per_channel_ - 1], + sync_buffer->FutureLength()); } TEST_F(NetEqImplTest, ReorderedPacket) { @@ -543,16 +541,11 @@ TEST_F(NetEqImplTest, ReorderedPacket) { // Pull audio once. const size_t kMaxOutputSize = static_cast(10 * kSampleRateHz / 1000); - int16_t output[kMaxOutputSize]; - size_t samples_per_channel; - size_t num_channels; + AudioFrame output; NetEqOutputType type; - EXPECT_EQ( - NetEq::kOK, - neteq_->GetAudio( - kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); - ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputNormal, type); // Insert two more packets. The first one is out of order, and is already too @@ -578,12 +571,9 @@ TEST_F(NetEqImplTest, ReorderedPacket) { Return(kPayloadLengthSamples))); // Pull audio once. - EXPECT_EQ( - NetEq::kOK, - neteq_->GetAudio( - kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); - ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputNormal, type); // Now check the packet buffer, and make sure it is empty, since the @@ -620,16 +610,12 @@ TEST_F(NetEqImplTest, FirstPacketUnknown) { // Pull audio once. const size_t kMaxOutputSize = static_cast(10 * kSampleRateHz / 1000); - int16_t output[kMaxOutputSize]; - size_t samples_per_channel; - size_t num_channels; + AudioFrame output; NetEqOutputType type; - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); - ASSERT_LE(samples_per_channel, kMaxOutputSize); - EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + ASSERT_LE(output.samples_per_channel_, kMaxOutputSize); + EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputPLC, type); // Register the payload type. @@ -647,12 +633,10 @@ TEST_F(NetEqImplTest, FirstPacketUnknown) { // Pull audio repeatedly and make sure we get normal output, that is not PLC. for (size_t i = 0; i < 3; ++i) { - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); - ASSERT_LE(samples_per_channel, kMaxOutputSize); - EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + ASSERT_LE(output.samples_per_channel_, kMaxOutputSize); + EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputNormal, type) << "NetEq did not decode the packets as expected."; } @@ -732,9 +716,7 @@ TEST_F(NetEqImplTest, CodecInternalCng) { neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); const size_t kMaxOutputSize = static_cast(10 * kSampleRateKhz); - int16_t output[kMaxOutputSize]; - size_t samples_per_channel; - size_t num_channels; + AudioFrame output; uint32_t timestamp; uint32_t last_timestamp; NetEqOutputType type; @@ -752,19 +734,15 @@ TEST_F(NetEqImplTest, CodecInternalCng) { 50 * kSampleRateKhz, 10 * kSampleRateKhz }; - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); EXPECT_TRUE(neteq_->GetPlayoutTimestamp(&last_timestamp)); for (size_t i = 1; i < 6; ++i) { - ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(expected_type[i - 1], type); EXPECT_TRUE(neteq_->GetPlayoutTimestamp(×tamp)); - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); EXPECT_TRUE(neteq_->GetPlayoutTimestamp(×tamp)); EXPECT_EQ(timestamp, last_timestamp + expected_timestamp_increment[i]); last_timestamp = timestamp; @@ -778,12 +756,10 @@ TEST_F(NetEqImplTest, CodecInternalCng) { neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); for (size_t i = 6; i < 8; ++i) { - ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(expected_type[i - 1], type); - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); EXPECT_TRUE(neteq_->GetPlayoutTimestamp(×tamp)); EXPECT_EQ(timestamp, last_timestamp + expected_timestamp_increment[i]); last_timestamp = timestamp; @@ -871,24 +847,23 @@ TEST_F(NetEqImplTest, UnsupportedDecoder) { EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); - const size_t kMaxOutputSize = 10 * kSampleRateHz / 1000 * kChannels; - int16_t output[kMaxOutputSize]; - size_t samples_per_channel; - size_t num_channels; + AudioFrame output; NetEqOutputType type; - - EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(kMaxOutputSize, output, - &samples_per_channel, &num_channels, - &type)); + // First call to GetAudio will try to decode the "faulty" packet. + // Expect kFail return value... + EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&output, &type)); + // ... and kOtherDecoderError error code. EXPECT_EQ(NetEq::kOtherDecoderError, neteq_->LastError()); - EXPECT_EQ(kMaxOutputSize, samples_per_channel * kChannels); - EXPECT_EQ(kChannels, num_channels); + // Output size and number of channels should be correct. + const size_t kExpectedOutputSize = 10 * (kSampleRateHz / 1000) * kChannels; + EXPECT_EQ(kExpectedOutputSize, output.samples_per_channel_ * kChannels); + EXPECT_EQ(kChannels, output.num_channels_); - EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(kMaxOutputSize, output, - &samples_per_channel, &num_channels, - &type)); - EXPECT_EQ(kMaxOutputSize, samples_per_channel * kChannels); - EXPECT_EQ(kChannels, num_channels); + // Second call to GetAudio will decode the packet that is ok. No errors are + // expected. + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + EXPECT_EQ(kExpectedOutputSize, output.samples_per_channel_ * kChannels); + EXPECT_EQ(kChannels, output.num_channels_); } // This test inserts packets until the buffer is flushed. After that, it asks @@ -978,15 +953,11 @@ TEST_F(NetEqImplTest, DecodedPayloadTooShort) { // Pull audio once. const size_t kMaxOutputSize = static_cast(10 * kSampleRateHz / 1000); - int16_t output[kMaxOutputSize]; - size_t samples_per_channel; - size_t num_channels; + AudioFrame output; NetEqOutputType type; - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); - ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputNormal, type); EXPECT_CALL(mock_decoder, Die()); @@ -1075,43 +1046,33 @@ TEST_F(NetEqImplTest, DecodingError) { // Pull audio. const size_t kMaxOutputSize = static_cast(10 * kSampleRateHz / 1000); - int16_t output[kMaxOutputSize]; - size_t samples_per_channel; - size_t num_channels; + AudioFrame output; NetEqOutputType type; - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); - EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputNormal, type); // Pull audio again. Decoder fails. - EXPECT_EQ(NetEq::kFail, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); + EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&output, &type)); EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError()); EXPECT_EQ(kDecoderErrorCode, neteq_->LastDecoderError()); - EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); // TODO(minyue): should NetEq better give kOutputPLC, since it is actually an // expansion. EXPECT_EQ(kOutputNormal, type); // Pull audio again, should continue an expansion. - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); - EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputPLC, type); // Pull audio again, should behave normal. - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); - EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputNormal, type); EXPECT_CALL(mock_decoder, Die()); @@ -1196,35 +1157,27 @@ TEST_F(NetEqImplTest, DecodingErrorDuringInternalCng) { // Pull audio. const size_t kMaxOutputSize = static_cast(10 * kSampleRateHz / 1000); - int16_t output[kMaxOutputSize]; - size_t samples_per_channel; - size_t num_channels; + AudioFrame output; NetEqOutputType type; - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); - EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputCNG, type); // Pull audio again. Decoder fails. - EXPECT_EQ(NetEq::kFail, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); + EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&output, &type)); EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError()); EXPECT_EQ(kDecoderErrorCode, neteq_->LastDecoderError()); - EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); // TODO(minyue): should NetEq better give kOutputPLC, since it is actually an // expansion. EXPECT_EQ(kOutputCNG, type); // Pull audio again, should resume codec CNG. - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, - &num_channels, &type)); - EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1u, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type)); + EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_); + EXPECT_EQ(1u, output.num_channels_); EXPECT_EQ(kOutputCNG, type); EXPECT_CALL(mock_decoder, Die()); diff --git a/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc index f22c51b7a5..91ae4d0f3d 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc @@ -13,6 +13,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h" +#include "webrtc/modules/include/module_common_types.h" namespace webrtc { namespace test { @@ -83,7 +84,6 @@ class NetEqNetworkStatsTest : public NetEqExternalDecoderTest { public: static const int kPayloadSizeByte = 30; static const int kFrameSizeMs = 20; - static const int kMaxOutputSize = 960; // 10 ms * 48 kHz * 2 channels. enum logic { kIgnore, @@ -195,7 +195,7 @@ struct NetEqNetworkStatsCheck { InsertPacket(rtp_header_, payload_, next_send_time); } } - GetOutputAudio(kMaxOutputSize, output_, &output_type); + GetOutputAudio(&output_frame_, &output_type); time_now += kOutputLengthMs; } CheckNetworkStatistics(expects); @@ -269,7 +269,7 @@ struct NetEqNetworkStatsCheck { uint32_t last_lost_time_; uint32_t packet_loss_interval_; uint8_t payload_[kPayloadSizeByte]; - int16_t output_[kMaxOutputSize]; + AudioFrame output_frame_; }; TEST(NetEqNetworkStatsTest, DecodeFec) { diff --git a/webrtc/modules/audio_coding/neteq/neteq_stereo_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_stereo_unittest.cc index aaff4710da..5beeeea909 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_stereo_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_stereo_unittest.cc @@ -20,6 +20,7 @@ #include "webrtc/modules/audio_coding/neteq/include/neteq.h" #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/test/testsupport/fileutils.h" namespace webrtc { @@ -69,7 +70,6 @@ class NetEqStereoTest : public ::testing::TestWithParam { input_multi_channel_ = new int16_t[frame_size_samples_ * num_channels_]; encoded_multi_channel_ = new uint8_t[frame_size_samples_ * 2 * num_channels_]; - output_multi_channel_ = new int16_t[kMaxBlockSize * num_channels_]; } ~NetEqStereoTest() { @@ -79,7 +79,6 @@ class NetEqStereoTest : public ::testing::TestWithParam { delete [] encoded_; delete [] input_multi_channel_; delete [] encoded_multi_channel_; - delete [] output_multi_channel_; } virtual void SetUp() { @@ -164,8 +163,9 @@ class NetEqStereoTest : public ::testing::TestWithParam { virtual void VerifyOutput(size_t num_samples) { for (size_t i = 0; i < num_samples; ++i) { for (size_t j = 0; j < num_channels_; ++j) { - ASSERT_EQ(output_[i], output_multi_channel_[i * num_channels_ + j]) << - "Diff in sample " << i << ", channel " << j << "."; + ASSERT_EQ(output_.data_[i], + output_multi_channel_.data_[i * num_channels_ + j]) + << "Diff in sample " << i << ", channel " << j << "."; } } } @@ -213,22 +213,15 @@ class NetEqStereoTest : public ::testing::TestWithParam { } NetEqOutputType output_type; // Get audio from mono instance. - size_t samples_per_channel; - size_t num_channels; - EXPECT_EQ(NetEq::kOK, - neteq_mono_->GetAudio(kMaxBlockSize, output_, - &samples_per_channel, &num_channels, - &output_type)); - EXPECT_EQ(1u, num_channels); - EXPECT_EQ(output_size_samples_, samples_per_channel); + EXPECT_EQ(NetEq::kOK, neteq_mono_->GetAudio(&output_, &output_type)); + EXPECT_EQ(1u, output_.num_channels_); + EXPECT_EQ(output_size_samples_, output_.samples_per_channel_); // Get audio from multi-channel instance. ASSERT_EQ(NetEq::kOK, - neteq_->GetAudio(kMaxBlockSize * num_channels_, - output_multi_channel_, - &samples_per_channel, &num_channels, - &output_type)); - EXPECT_EQ(num_channels_, num_channels); - EXPECT_EQ(output_size_samples_, samples_per_channel); + neteq_->GetAudio(&output_multi_channel_, &output_type)); + EXPECT_EQ(num_channels_, output_multi_channel_.num_channels_); + EXPECT_EQ(output_size_samples_, + output_multi_channel_.samples_per_channel_); std::ostringstream ss; ss << "Lap number " << k << "."; SCOPED_TRACE(ss.str()); // Print out the parameter values on failure. @@ -253,8 +246,8 @@ class NetEqStereoTest : public ::testing::TestWithParam { int16_t* input_multi_channel_; uint8_t* encoded_; uint8_t* encoded_multi_channel_; - int16_t output_[kMaxBlockSize]; - int16_t* output_multi_channel_; + AudioFrame output_; + AudioFrame output_multi_channel_; WebRtcRTPHeader rtp_header_mono_; WebRtcRTPHeader rtp_header_; size_t payload_size_bytes_; @@ -360,14 +353,16 @@ class NetEqStereoTestLosses : public NetEqStereoTest { // TODO(hlundin): NetEq is not giving bitexact results for these cases. virtual void VerifyOutput(size_t num_samples) { for (size_t i = 0; i < num_samples; ++i) { - auto first_channel_sample = output_multi_channel_[i * num_channels_]; + auto first_channel_sample = + output_multi_channel_.data_[i * num_channels_]; for (size_t j = 0; j < num_channels_; ++j) { const int kErrorMargin = 200; - EXPECT_NEAR(output_[i], output_multi_channel_[i * num_channels_ + j], + EXPECT_NEAR(output_.data_[i], + output_multi_channel_.data_[i * num_channels_ + j], kErrorMargin) << "Diff in sample " << i << ", channel " << j << "."; EXPECT_EQ(first_channel_sample, - output_multi_channel_[i * num_channels_ + j]); + output_multi_channel_.data_[i * num_channels_ + j]); } } } diff --git a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc index 0a85466db0..8d401a257a 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc @@ -29,6 +29,7 @@ #include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" #include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/typedefs.h" @@ -279,7 +280,6 @@ class NetEqDecodingTest : public ::testing::Test { static const size_t kBlockSize16kHz = kTimeStepMs * 16; static const size_t kBlockSize32kHz = kTimeStepMs * 32; static const size_t kBlockSize48kHz = kTimeStepMs * 48; - static const size_t kMaxBlockSize = kBlockSize48kHz; static const int kInitSampleRateHz = 8000; NetEqDecodingTest(); @@ -288,7 +288,7 @@ class NetEqDecodingTest : public ::testing::Test { void SelectDecoders(NetEqDecoder* used_codec); void LoadDecoders(); void OpenInputFile(const std::string &rtp_file); - void Process(size_t* out_len); + void Process(); void DecodeAndCompare(const std::string& rtp_file, const std::string& ref_file, @@ -323,7 +323,7 @@ class NetEqDecodingTest : public ::testing::Test { std::unique_ptr rtp_source_; std::unique_ptr packet_; unsigned int sim_clock_; - int16_t out_data_[kMaxBlockSize]; + AudioFrame out_frame_; int output_sample_rate_; int algorithmic_delay_ms_; }; @@ -333,7 +333,6 @@ const int NetEqDecodingTest::kTimeStepMs; const size_t NetEqDecodingTest::kBlockSize8kHz; const size_t NetEqDecodingTest::kBlockSize16kHz; const size_t NetEqDecodingTest::kBlockSize32kHz; -const size_t NetEqDecodingTest::kMaxBlockSize; const int NetEqDecodingTest::kInitSampleRateHz; NetEqDecodingTest::NetEqDecodingTest() @@ -343,7 +342,6 @@ NetEqDecodingTest::NetEqDecodingTest() output_sample_rate_(kInitSampleRateHz), algorithmic_delay_ms_(0) { config_.sample_rate_hz = kInitSampleRateHz; - memset(out_data_, 0, sizeof(out_data_)); } void NetEqDecodingTest::SetUp() { @@ -406,7 +404,7 @@ void NetEqDecodingTest::OpenInputFile(const std::string &rtp_file) { rtp_source_.reset(test::RtpFileSource::Create(rtp_file)); } -void NetEqDecodingTest::Process(size_t* out_len) { +void NetEqDecodingTest::Process() { // Check if time to receive. while (packet_ && sim_clock_ >= packet_->time_ms()) { if (packet_->payload_length_bytes() > 0) { @@ -429,14 +427,12 @@ void NetEqDecodingTest::Process(size_t* out_len) { // Get audio from NetEq. NetEqOutputType type; - size_t num_channels; - ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, out_len, - &num_channels, &type)); - ASSERT_TRUE((*out_len == kBlockSize8kHz) || - (*out_len == kBlockSize16kHz) || - (*out_len == kBlockSize32kHz) || - (*out_len == kBlockSize48kHz)); - output_sample_rate_ = static_cast(*out_len / 10 * 1000); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_TRUE((out_frame_.samples_per_channel_ == kBlockSize8kHz) || + (out_frame_.samples_per_channel_ == kBlockSize16kHz) || + (out_frame_.samples_per_channel_ == kBlockSize32kHz) || + (out_frame_.samples_per_channel_ == kBlockSize48kHz)); + output_sample_rate_ = out_frame_.sample_rate_hz_; EXPECT_EQ(output_sample_rate_, neteq_->last_output_sample_rate_hz()); // Increase time. @@ -473,9 +469,9 @@ void NetEqDecodingTest::DecodeAndCompare(const std::string& rtp_file, std::ostringstream ss; ss << "Lap number " << i++ << " in DecodeAndCompare while loop"; SCOPED_TRACE(ss.str()); // Print out the parameter values on failure. - size_t out_len = 0; - ASSERT_NO_FATAL_FAILURE(Process(&out_len)); - ASSERT_NO_FATAL_FAILURE(ref_files.ProcessReference(out_data_, out_len)); + ASSERT_NO_FATAL_FAILURE(Process()); + ASSERT_NO_FATAL_FAILURE(ref_files.ProcessReference( + out_frame_.data_, out_frame_.samples_per_channel_)); // Query the network statistics API once per second if (sim_clock_ % 1000 == 0) { @@ -615,12 +611,9 @@ TEST_F(NetEqDecodingTestFaxMode, TestFrameWaitingTimeStatistics) { } // Pull out all data. for (size_t i = 0; i < num_frames; ++i) { - size_t out_len; - size_t num_channels; NetEqOutputType type; - ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, - &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); } NetEqNetworkStatistics stats; @@ -660,12 +653,9 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimeNegative) { } // Pull out data once. - size_t out_len; - size_t num_channels; NetEqOutputType type; - ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, - &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); } NetEqNetworkStatistics network_stats; @@ -691,12 +681,9 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimePositive) { } // Pull out data once. - size_t out_len; - size_t num_channels; NetEqOutputType type; - ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, - &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); } NetEqNetworkStatistics network_stats; @@ -716,8 +703,6 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, const size_t kPayloadBytes = kSamples * 2; double next_input_time_ms = 0.0; double t_ms; - size_t out_len; - size_t num_channels; NetEqOutputType type; // Insert speech for 5 seconds. @@ -735,9 +720,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, next_input_time_ms += static_cast(kFrameSizeMs) * drift_factor; } // Pull out data once. - ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, - &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); } EXPECT_EQ(kOutputNormal, type); @@ -763,9 +747,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, next_input_time_ms += static_cast(kCngPeriodMs) * drift_factor; } // Pull out data once. - ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, - &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); } EXPECT_EQ(kOutputCNG, type); @@ -777,10 +760,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, const double loop_end_time = t_ms + network_freeze_ms; for (; t_ms < loop_end_time; t_ms += 10) { // Pull out data once. - ASSERT_EQ(0, - neteq_->GetAudio( - kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); EXPECT_EQ(kOutputCNG, type); } bool pull_once = pull_audio_during_freeze; @@ -791,11 +772,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, if (pull_once && next_input_time_ms >= pull_time_ms) { pull_once = false; // Pull out data once. - ASSERT_EQ( - 0, - neteq_->GetAudio( - kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); EXPECT_EQ(kOutputCNG, type); t_ms += 10; } @@ -828,9 +806,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, next_input_time_ms += kFrameSizeMs * drift_factor; } // Pull out data once. - ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, - &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); // Increase clock. t_ms += 10; } @@ -953,14 +930,10 @@ TEST_F(NetEqDecodingTest, MAYBE_DecoderError) { NetEqOutputType type; // Set all of |out_data_| to 1, and verify that it was set to 0 by the call // to GetAudio. - for (size_t i = 0; i < kMaxBlockSize; ++i) { - out_data_[i] = 1; + for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) { + out_frame_.data_[i] = 1; } - size_t num_channels; - size_t samples_per_channel; - EXPECT_EQ(NetEq::kFail, - neteq_->GetAudio(kMaxBlockSize, out_data_, - &samples_per_channel, &num_channels, &type)); + EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&out_frame_, &type)); // Verify that there is a decoder error to check. EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError()); @@ -980,13 +953,14 @@ TEST_F(NetEqDecodingTest, MAYBE_DecoderError) { std::ostringstream ss; ss << "i = " << i; SCOPED_TRACE(ss.str()); // Print out the parameter values on failure. - EXPECT_EQ(0, out_data_[i]); + EXPECT_EQ(0, out_frame_.data_[i]); } - for (size_t i = kExpectedOutputLength; i < kMaxBlockSize; ++i) { + for (size_t i = kExpectedOutputLength; i < AudioFrame::kMaxDataSizeSamples; + ++i) { std::ostringstream ss; ss << "i = " << i; SCOPED_TRACE(ss.str()); // Print out the parameter values on failure. - EXPECT_EQ(1, out_data_[i]); + EXPECT_EQ(1, out_frame_.data_[i]); } } @@ -994,14 +968,10 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { NetEqOutputType type; // Set all of |out_data_| to 1, and verify that it was set to 0 by the call // to GetAudio. - for (size_t i = 0; i < kMaxBlockSize; ++i) { - out_data_[i] = 1; + for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) { + out_frame_.data_[i] = 1; } - size_t num_channels; - size_t samples_per_channel; - EXPECT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, - &samples_per_channel, - &num_channels, &type)); + EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); // Verify that the first block of samples is set to 0. static const int kExpectedOutputLength = kInitSampleRateHz / 100; // 10 ms at initial sample rate. @@ -1009,7 +979,7 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { std::ostringstream ss; ss << "i = " << i; SCOPED_TRACE(ss.str()); // Print out the parameter values on failure. - EXPECT_EQ(0, out_data_[i]); + EXPECT_EQ(0, out_frame_.data_[i]); } // Verify that the sample rate did not change from the initial configuration. EXPECT_EQ(config_.sample_rate_hz, neteq_->last_output_sample_rate_hz()); @@ -1037,7 +1007,7 @@ class NetEqBgnTest : public NetEqDecodingTest { } NetEqOutputType type; - int16_t output[kBlockSize32kHz]; // Maximum size is chosen. + AudioFrame output; test::AudioLoop input; // We are using the same 32 kHz input file for all tests, regardless of // |sampling_rate_hz|. The output may sound weird, but the test is still @@ -1053,9 +1023,6 @@ class NetEqBgnTest : public NetEqDecodingTest { PopulateRtpInfo(0, 0, &rtp_info); rtp_info.header.payloadType = payload_type; - size_t number_channels = 0; - size_t samples_per_channel = 0; - uint32_t receive_timestamp = 0; for (int n = 0; n < 10; ++n) { // Insert few packets and get audio. auto block = input.GetNextBlock(); @@ -1064,19 +1031,13 @@ class NetEqBgnTest : public NetEqDecodingTest { WebRtcPcm16b_Encode(block.data(), block.size(), payload); ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2); - number_channels = 0; - samples_per_channel = 0; ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView( payload, enc_len_bytes), receive_timestamp)); - ASSERT_EQ(0, - neteq_->GetAudio(kBlockSize32kHz, - output, - &samples_per_channel, - &number_channels, - &type)); - ASSERT_EQ(1u, number_channels); - ASSERT_EQ(expected_samples_per_channel, samples_per_channel); + output.Reset(); + ASSERT_EQ(0, neteq_->GetAudio(&output, &type)); + ASSERT_EQ(1u, output.num_channels_); + ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_); ASSERT_EQ(kOutputNormal, type); // Next packet. @@ -1085,20 +1046,14 @@ class NetEqBgnTest : public NetEqDecodingTest { receive_timestamp += expected_samples_per_channel; } - number_channels = 0; - samples_per_channel = 0; + output.Reset(); // Get audio without inserting packets, expecting PLC and PLC-to-CNG. Pull // one frame without checking speech-type. This is the first frame pulled // without inserting any packet, and might not be labeled as PLC. - ASSERT_EQ(0, - neteq_->GetAudio(kBlockSize32kHz, - output, - &samples_per_channel, - &number_channels, - &type)); - ASSERT_EQ(1u, number_channels); - ASSERT_EQ(expected_samples_per_channel, samples_per_channel); + ASSERT_EQ(0, neteq_->GetAudio(&output, &type)); + ASSERT_EQ(1u, output.num_channels_); + ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_); // To be able to test the fading of background noise we need at lease to // pull 611 frames. @@ -1109,22 +1064,17 @@ class NetEqBgnTest : public NetEqDecodingTest { const int kNumPlcToCngTestFrames = 20; bool plc_to_cng = false; for (int n = 0; n < kFadingThreshold + kNumPlcToCngTestFrames; ++n) { - number_channels = 0; - samples_per_channel = 0; - memset(output, 1, sizeof(output)); // Set to non-zero. - ASSERT_EQ(0, - neteq_->GetAudio(kBlockSize32kHz, - output, - &samples_per_channel, - &number_channels, - &type)); - ASSERT_EQ(1u, number_channels); - ASSERT_EQ(expected_samples_per_channel, samples_per_channel); + output.Reset(); + memset(output.data_, 1, sizeof(output.data_)); // Set to non-zero. + ASSERT_EQ(0, neteq_->GetAudio(&output, &type)); + ASSERT_EQ(1u, output.num_channels_); + ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_); if (type == kOutputPLCtoCNG) { plc_to_cng = true; double sum_squared = 0; - for (size_t k = 0; k < number_channels * samples_per_channel; ++k) - sum_squared += output[k] * output[k]; + for (size_t k = 0; + k < output.num_channels_ * output.samples_per_channel_; ++k) + sum_squared += output.data_[k] * output.data_[k]; TestCondition(sum_squared, n > kFadingThreshold); } else { EXPECT_EQ(kOutputPLC, type); @@ -1282,7 +1232,7 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { PopulateRtpInfo(0, 0, &rtp_info); const size_t kPayloadBytes = kBlockSize16kHz * sizeof(int16_t); uint8_t payload[kPayloadBytes]; - int16_t decoded[kBlockSize16kHz]; + AudioFrame output; int algorithmic_frame_delay = algorithmic_delay_ms_ / 10 + 1; for (size_t n = 0; n < kPayloadBytes; ++n) { payload[n] = (rand() & 0xF0) + 1; // Non-zero random sequence. @@ -1290,16 +1240,12 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { // Insert some packets which decode to noise. We are not interested in // actual decoded values. NetEqOutputType output_type; - size_t num_channels; - size_t samples_per_channel; uint32_t receive_timestamp = 0; for (int n = 0; n < 100; ++n) { ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); - ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, - &samples_per_channel, &num_channels, - &output_type)); - ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1u, num_channels); + ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type)); + ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); + ASSERT_EQ(1u, output.num_channels_); rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; @@ -1313,13 +1259,12 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { // Insert sync-packets, the decoded sequence should be all-zero. for (int n = 0; n < kNumSyncPackets; ++n) { ASSERT_EQ(0, neteq_->InsertSyncPacket(rtp_info, receive_timestamp)); - ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, - &samples_per_channel, &num_channels, - &output_type)); - ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1u, num_channels); + ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type)); + ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); + ASSERT_EQ(1u, output.num_channels_); if (n > algorithmic_frame_delay) { - EXPECT_TRUE(IsAllZero(decoded, samples_per_channel * num_channels)); + EXPECT_TRUE(IsAllZero( + output.data_, output.samples_per_channel_ * output.num_channels_)); } rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; @@ -1330,12 +1275,11 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { // network statistics would show some packet loss. for (int n = 0; n <= algorithmic_frame_delay + 10; ++n) { ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); - ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, - &samples_per_channel, &num_channels, - &output_type)); + ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type)); if (n >= algorithmic_frame_delay + 1) { // Expect that this frame contain samples from regular RTP. - EXPECT_TRUE(IsAllNonZero(decoded, samples_per_channel * num_channels)); + EXPECT_TRUE(IsAllNonZero( + output.data_, output.samples_per_channel_ * output.num_channels_)); } rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; @@ -1359,24 +1303,20 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { PopulateRtpInfo(0, 0, &rtp_info); const size_t kPayloadBytes = kBlockSize16kHz * sizeof(int16_t); uint8_t payload[kPayloadBytes]; - int16_t decoded[kBlockSize16kHz]; + AudioFrame output; for (size_t n = 0; n < kPayloadBytes; ++n) { payload[n] = (rand() & 0xF0) + 1; // Non-zero random sequence. } // Insert some packets which decode to noise. We are not interested in // actual decoded values. NetEqOutputType output_type; - size_t num_channels; - size_t samples_per_channel; uint32_t receive_timestamp = 0; int algorithmic_frame_delay = algorithmic_delay_ms_ / 10 + 1; for (int n = 0; n < algorithmic_frame_delay; ++n) { ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); - ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, - &samples_per_channel, &num_channels, - &output_type)); - ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1u, num_channels); + ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type)); + ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); + ASSERT_EQ(1u, output.num_channels_); rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; receive_timestamp += kBlockSize16kHz; @@ -1411,12 +1351,11 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { // Decode. for (int n = 0; n < kNumSyncPackets; ++n) { - ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, - &samples_per_channel, &num_channels, - &output_type)); - ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1u, num_channels); - EXPECT_TRUE(IsAllNonZero(decoded, samples_per_channel * num_channels)); + ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type)); + ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); + ASSERT_EQ(1u, output.num_channels_); + EXPECT_TRUE(IsAllNonZero( + output.data_, output.samples_per_channel_ * output.num_channels_)); } } @@ -1432,10 +1371,6 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no, const int kSamples = kBlockSize16kHz * kBlocksPerFrame; const size_t kPayloadBytes = kSamples * sizeof(int16_t); double next_input_time_ms = 0.0; - int16_t decoded[kBlockSize16kHz]; - size_t num_channels; - size_t samples_per_channel; - NetEqOutputType output_type; uint32_t receive_timestamp = 0; // Insert speech for 2 seconds. @@ -1482,11 +1417,11 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no, timestamp_wrapped |= timestamp < last_timestamp; } // Pull out data once. - ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, - &samples_per_channel, &num_channels, - &output_type)); - ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1u, num_channels); + AudioFrame output; + NetEqOutputType output_type; + ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type)); + ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); + ASSERT_EQ(1u, output.num_channels_); // Expect delay (in samples) to be less than 2 packets. EXPECT_LE(timestamp - PlayoutTimestamp(), @@ -1536,8 +1471,6 @@ void NetEqDecodingTest::DuplicateCng() { algorithmic_delay_ms_ * kSampleRateKhz, 5 * kSampleRateKhz / 8); // Insert three speech packets. Three are needed to get the frame length // correct. - size_t out_len; - size_t num_channels; NetEqOutputType type; uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; @@ -1548,10 +1481,8 @@ void NetEqDecodingTest::DuplicateCng() { timestamp += kSamples; // Pull audio once. - ASSERT_EQ(0, - neteq_->GetAudio( - kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); } // Verify speech output. EXPECT_EQ(kOutputNormal, type); @@ -1567,10 +1498,8 @@ void NetEqDecodingTest::DuplicateCng() { rtp_info, rtc::ArrayView(payload, payload_len), 0)); // Pull audio once and make sure CNG is played. - ASSERT_EQ(0, - neteq_->GetAudio( - kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); EXPECT_EQ(kOutputCNG, type); EXPECT_EQ(timestamp - algorithmic_delay_samples, PlayoutTimestamp()); @@ -1583,10 +1512,8 @@ void NetEqDecodingTest::DuplicateCng() { // Pull audio until we have played |kCngPeriodMs| of CNG. Start at 10 ms since // we have already pulled out CNG once. for (int cng_time_ms = 10; cng_time_ms < kCngPeriodMs; cng_time_ms += 10) { - ASSERT_EQ(0, - neteq_->GetAudio( - kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); EXPECT_EQ(kOutputCNG, type); EXPECT_EQ(timestamp - algorithmic_delay_samples, PlayoutTimestamp()); @@ -1599,10 +1526,8 @@ void NetEqDecodingTest::DuplicateCng() { ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); // Pull audio once and verify that the output is speech again. - ASSERT_EQ(0, - neteq_->GetAudio( - kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); EXPECT_EQ(kOutputNormal, type); EXPECT_EQ(timestamp + kSamples - algorithmic_delay_samples, PlayoutTimestamp()); @@ -1639,12 +1564,9 @@ TEST_F(NetEqDecodingTest, CngFirst) { timestamp += kCngPeriodSamples; // Pull audio once and make sure CNG is played. - size_t out_len; - size_t num_channels; NetEqOutputType type; - ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, - &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); EXPECT_EQ(kOutputCNG, type); // Insert some speech packets. @@ -1655,9 +1577,8 @@ TEST_F(NetEqDecodingTest, CngFirst) { timestamp += kSamples; // Pull audio once. - ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, - &num_channels, &type)); - ASSERT_EQ(kBlockSize16kHz, out_len); + ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type)); + ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); } // Verify speech output. EXPECT_EQ(kOutputNormal, type); diff --git a/webrtc/modules/audio_coding/neteq/sync_buffer.cc b/webrtc/modules/audio_coding/neteq/sync_buffer.cc index d1802e174f..543f78bdc4 100644 --- a/webrtc/modules/audio_coding/neteq/sync_buffer.cc +++ b/webrtc/modules/audio_coding/neteq/sync_buffer.cc @@ -8,10 +8,9 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include - #include // Access to min. +#include "webrtc/base/checks.h" #include "webrtc/modules/audio_coding/neteq/sync_buffer.h" namespace webrtc { @@ -71,16 +70,18 @@ void SyncBuffer::ReplaceAtIndex(const AudioMultiVector& insert_this, ReplaceAtIndex(insert_this, insert_this.Size(), position); } -size_t SyncBuffer::GetNextAudioInterleaved(size_t requested_len, - int16_t* output) { - if (!output) { - assert(false); - return 0; - } - size_t samples_to_read = std::min(FutureLength(), requested_len); - ReadInterleavedFromIndex(next_index_, samples_to_read, output); - next_index_ += samples_to_read; - return samples_to_read; +void SyncBuffer::GetNextAudioInterleaved(size_t requested_len, + AudioFrame* output) { + RTC_DCHECK(output); + const size_t samples_to_read = std::min(FutureLength(), requested_len); + output->Reset(); + const size_t tot_samples_read = + ReadInterleavedFromIndex(next_index_, samples_to_read, output->data_); + const size_t samples_read_per_channel = tot_samples_read / Channels(); + next_index_ += samples_read_per_channel; + output->interleaved_ = true; + output->num_channels_ = Channels(); + output->samples_per_channel_ = samples_read_per_channel; } void SyncBuffer::IncreaseEndTimestamp(uint32_t increment) { diff --git a/webrtc/modules/audio_coding/neteq/sync_buffer.h b/webrtc/modules/audio_coding/neteq/sync_buffer.h index 38e7887794..c3bb4a9069 100644 --- a/webrtc/modules/audio_coding/neteq/sync_buffer.h +++ b/webrtc/modules/audio_coding/neteq/sync_buffer.h @@ -13,6 +13,7 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/modules/audio_coding/neteq/audio_multi_vector.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -65,8 +66,10 @@ class SyncBuffer : public AudioMultiVector { // Reads |requested_len| samples from each channel and writes them interleaved // into |output|. The |next_index_| is updated to point to the sample to read - // next time. - size_t GetNextAudioInterleaved(size_t requested_len, int16_t* output); + // next time. The AudioFrame |output| is first reset, and the |data_|, + // |interleaved_|, |num_channels_|, and |samples_per_channel_| fields are + // updated. + void GetNextAudioInterleaved(size_t requested_len, AudioFrame* output); // Adds |increment| to |end_timestamp_|. void IncreaseEndTimestamp(uint32_t increment); diff --git a/webrtc/modules/audio_coding/neteq/sync_buffer_unittest.cc b/webrtc/modules/audio_coding/neteq/sync_buffer_unittest.cc index 332ec2f4e8..0f7b98978d 100644 --- a/webrtc/modules/audio_coding/neteq/sync_buffer_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/sync_buffer_unittest.cc @@ -140,20 +140,29 @@ TEST(SyncBuffer, GetNextAudioInterleaved) { // Read to interleaved output. Read in two batches, where each read operation // should automatically update the |net_index_| in the SyncBuffer. - int16_t output[kChannels * kNewLen]; // Note that |samples_read| is the number of samples read from each channel. // That is, the number of samples written to |output| is // |samples_read| * |kChannels|. - size_t samples_read = sync_buffer.GetNextAudioInterleaved(kNewLen / 2, - output); - samples_read += - sync_buffer.GetNextAudioInterleaved(kNewLen / 2, - &output[samples_read * kChannels]); - EXPECT_EQ(kNewLen, samples_read); + AudioFrame output1; + sync_buffer.GetNextAudioInterleaved(kNewLen / 2, &output1); + EXPECT_EQ(kChannels, output1.num_channels_); + EXPECT_EQ(kNewLen / 2, output1.samples_per_channel_); + + AudioFrame output2; + sync_buffer.GetNextAudioInterleaved(kNewLen / 2, &output2); + EXPECT_EQ(kChannels, output2.num_channels_); + EXPECT_EQ(kNewLen / 2, output2.samples_per_channel_); // Verify the data. - int16_t* output_ptr = output; - for (size_t i = 0; i < kNewLen; ++i) { + int16_t* output_ptr = output1.data_; + for (size_t i = 0; i < kNewLen / 2; ++i) { + for (size_t channel = 0; channel < kChannels; ++channel) { + EXPECT_EQ(new_data[channel][i], *output_ptr); + ++output_ptr; + } + } + output_ptr = output2.data_; + for (size_t i = kNewLen / 2; i < kNewLen; ++i) { for (size_t channel = 0; channel < kChannels; ++channel) { EXPECT_EQ(new_data[channel][i], *output_ptr); ++output_ptr; diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc index 694b9ed153..94436e193c 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc @@ -43,23 +43,14 @@ void NetEqExternalDecoderTest::InsertPacket( neteq_->InsertPacket(rtp_header, payload, receive_timestamp)); } -size_t NetEqExternalDecoderTest::GetOutputAudio(size_t max_length, - int16_t* output, - NetEqOutputType* output_type) { +void NetEqExternalDecoderTest::GetOutputAudio(AudioFrame* output, + NetEqOutputType* output_type) { // Get audio from regular instance. - size_t samples_per_channel; - size_t num_channels; - EXPECT_EQ(NetEq::kOK, - neteq_->GetAudio(max_length, - output, - &samples_per_channel, - &num_channels, - output_type)); - EXPECT_EQ(channels_, num_channels); + EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(output, output_type)); + EXPECT_EQ(channels_, output->num_channels_); EXPECT_EQ(static_cast(kOutputLengthMs * sample_rate_hz_ / 1000), - samples_per_channel); + output->samples_per_channel_); EXPECT_EQ(sample_rate_hz_, neteq_->last_output_sample_rate_hz()); - return samples_per_channel; } } // namespace test diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h index 1b36d8b0a2..bd9f01aae4 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h @@ -42,10 +42,8 @@ class NetEqExternalDecoderTest { rtc::ArrayView payload, uint32_t receive_timestamp); - // Get 10 ms of audio data. The data is written to |output|, which can hold - // (at least) |max_length| elements. Returns number of samples. - size_t GetOutputAudio(size_t max_length, int16_t* output, - NetEqOutputType* output_type); + // Get 10 ms of audio data. + void GetOutputAudio(AudioFrame* output, NetEqOutputType* output_type); NetEq* neteq() { return neteq_.get(); } diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.cc index 7d1f9f9798..f1577df26f 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.cc @@ -14,6 +14,7 @@ #include "webrtc/modules/audio_coding/neteq/include/neteq.h" #include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/system_wrappers/include/clock.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/typedefs.h" @@ -103,21 +104,15 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms, } // Get output audio, but don't do anything with it. - static const int kMaxChannels = 1; - static const size_t kMaxSamplesPerMs = 48000 / 1000; - static const int kOutputBlockSizeMs = 10; - static const size_t kOutDataLen = - kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels; - int16_t out_data[kOutDataLen]; - size_t num_channels; - size_t samples_per_channel; - int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, - &num_channels, NULL); + AudioFrame out_frame; + int error = neteq->GetAudio(&out_frame, NULL); if (error != NetEq::kOK) return -1; - assert(samples_per_channel == static_cast(kSampRateHz * 10 / 1000)); + assert(out_frame.samples_per_channel_ == + static_cast(kSampRateHz * 10 / 1000)); + static const int kOutputBlockSizeMs = 10; time_now_ms += kOutputBlockSizeMs; if (time_now_ms >= runtime_ms / 2 && !drift_flipped) { // Apply negative drift second half of simulation. diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc index 7118f4ed99..1155987706 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc @@ -220,7 +220,6 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms, out_sampling_khz_(out_sampling_khz), in_size_samples_( static_cast(in_sampling_khz_ * block_duration_ms_)), - out_size_samples_(static_cast(out_sampling_khz_ * kOutputSizeMs)), payload_size_bytes_(0), max_payload_bytes_(0), in_file_(new ResampleInputAudioFile(FLAGS_in_filename, @@ -249,7 +248,6 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms, neteq_.reset(NetEq::Create(config)); max_payload_bytes_ = in_size_samples_ * channels_ * sizeof(int16_t); in_data_.reset(new int16_t[in_size_samples_ * channels_]); - out_data_.reset(new int16_t[out_size_samples_ * channels_]); } NetEqQualityTest::~NetEqQualityTest() { @@ -393,18 +391,18 @@ int NetEqQualityTest::Transmit() { } int NetEqQualityTest::DecodeBlock() { - size_t channels; - size_t samples; - int ret = neteq_->GetAudio(out_size_samples_ * channels_, &out_data_[0], - &samples, &channels, NULL); + int ret = neteq_->GetAudio(&out_frame_, NULL); if (ret != NetEq::kOK) { return -1; } else { - assert(channels == channels_); - assert(samples == static_cast(kOutputSizeMs * out_sampling_khz_)); - RTC_CHECK(output_->WriteArray(out_data_.get(), samples * channels)); - return static_cast(samples); + RTC_DCHECK_EQ(out_frame_.num_channels_, channels_); + RTC_DCHECK_EQ(out_frame_.samples_per_channel_, + static_cast(kOutputSizeMs * out_sampling_khz_)); + RTC_CHECK(output_->WriteArray( + out_frame_.data_, + out_frame_.samples_per_channel_ * out_frame_.num_channels_)); + return static_cast(out_frame_.samples_per_channel_); } } diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h index 43c95b8062..11afe6886b 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h @@ -19,6 +19,7 @@ #include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h" #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" using google::RegisterFlagValidator; @@ -113,9 +114,6 @@ class NetEqQualityTest : public ::testing::Test { // Number of samples per channel in a frame. const size_t in_size_samples_; - // Expected output number of samples per channel in a frame. - const size_t out_size_samples_; - size_t payload_size_bytes_; size_t max_payload_bytes_; @@ -129,7 +127,7 @@ class NetEqQualityTest : public ::testing::Test { std::unique_ptr in_data_; rtc::Buffer payload_; - std::unique_ptr out_data_; + AudioFrame out_frame_; WebRtcRTPHeader rtp_header_; size_t total_payload_size_bytes_; diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc index 1701c476e8..a339199e2a 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc @@ -382,8 +382,6 @@ size_t ReplacePayload(webrtc::test::InputAudioFile* replacement_audio_file, } // namespace int main(int argc, char* argv[]) { - static const int kMaxChannels = 5; - static const size_t kMaxSamplesPerMs = 48000 / 1000; static const int kOutputBlockSizeMs = 10; std::string program_name = argv[0]; @@ -606,26 +604,19 @@ int main(int argc, char* argv[]) { // Check if it is time to get output audio. while (time_now_ms >= next_output_time_ms && output_event_available) { - static const size_t kOutDataLen = - kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels; - int16_t out_data[kOutDataLen]; - size_t num_channels; - size_t samples_per_channel; - int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, - &num_channels, NULL); + webrtc::AudioFrame out_frame; + int error = neteq->GetAudio(&out_frame, NULL); if (error != NetEq::kOK) { std::cerr << "GetAudio returned error code " << neteq->LastError() << std::endl; } else { - // Calculate sample rate from output size. - sample_rate_hz = rtc::checked_cast( - 1000 * samples_per_channel / kOutputBlockSizeMs); + sample_rate_hz = out_frame.sample_rate_hz_; } // Write to file. // TODO(hlundin): Make writing to file optional. - size_t write_len = samples_per_channel * num_channels; - if (!output->WriteArray(out_data, write_len)) { + if (!output->WriteArray(out_frame.data_, out_frame.samples_per_channel_ * + out_frame.num_channels_)) { std::cerr << "Error while writing to file" << std::endl; webrtc::Trace::ReturnTrace(); exit(1);