diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc index b4dfe3ad93..17750291da 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc @@ -123,7 +123,6 @@ AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) id_(config.id), last_audio_decoder_(nullptr), previous_audio_activity_(AudioFrame::kVadPassive), - current_sample_rate_hz_(config.neteq_config.sample_rate_hz), audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), neteq_(NetEq::Create(config.neteq_config)), @@ -157,9 +156,8 @@ int AcmReceiver::LeastRequiredDelayMs() const { return neteq_->LeastRequiredDelayMs(); } -int AcmReceiver::current_sample_rate_hz() const { - CriticalSectionScoped lock(crit_sect_.get()); - return current_sample_rate_hz_; +int AcmReceiver::last_output_sample_rate_hz() const { + return neteq_->last_output_sample_rate_hz(); } int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header, @@ -224,23 +222,18 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) { return -1; } - // NetEq always returns 10 ms of audio. - current_sample_rate_hz_ = static_cast(samples_per_channel * 100); + const int current_sample_rate_hz = neteq_->last_output_sample_rate_hz(); // Update if resampling is required. - bool need_resampling = (desired_freq_hz != -1) && - (current_sample_rate_hz_ != desired_freq_hz); + const bool need_resampling = + (desired_freq_hz != -1) && (current_sample_rate_hz != desired_freq_hz); if (need_resampling && !resampled_last_output_frame_) { // Prime the resampler with the last 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); + int samples_per_channel_int = resampler_.Resample10Msec( + last_audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz, + num_channels, AudioFrame::kMaxDataSizeSamples, temp_output); if (samples_per_channel_int < 0) { LOG(LERROR) << "AcmReceiver::GetAudio - " "Resampling last_audio_buffer_ failed."; @@ -254,13 +247,9 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) { // 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_); + int samples_per_channel_int = resampler_.Resample10Msec( + audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz, + num_channels, AudioFrame::kMaxDataSizeSamples, audio_frame->data_); if (samples_per_channel_int < 0) { LOG(LERROR) << "AcmReceiver::GetAudio - Resampling audio_buffer_ failed."; return -1; diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver.h b/webrtc/modules/audio_coding/main/acm2/acm_receiver.h index 7dc851a1ba..f02605bb71 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_receiver.h +++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver.h @@ -154,12 +154,8 @@ class AcmReceiver { // void ResetInitialDelay(); - // - // Get the current sampling frequency in Hz. - // - // Return value : Sampling frequency in Hz. - // - int current_sample_rate_hz() const; + // Returns last_output_sample_rate_hz from the NetEq instance. + int last_output_sample_rate_hz() const; // // Get the current network statistics from NetEq. @@ -287,7 +283,6 @@ class AcmReceiver { int id_; // TODO(henrik.lundin) Make const. const Decoder* last_audio_decoder_ GUARDED_BY(crit_sect_); AudioFrame::VADActivity previous_audio_activity_ GUARDED_BY(crit_sect_); - int current_sample_rate_hz_ 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? diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc b/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc index 37bb131f03..3bda1168d4 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc @@ -261,8 +261,7 @@ TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(SampleRate)) { for (int k = 0; k < num_10ms_frames; ++k) { EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame)); } - EXPECT_EQ(std::min(32000, codec.inst.plfreq), - receiver_->current_sample_rate_hz()); + EXPECT_EQ(codec.inst.plfreq, receiver_->last_output_sample_rate_hz()); } } diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc index d4d5853e71..19ae4cbc2b 100644 --- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc +++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc @@ -532,17 +532,14 @@ int AudioCodingModuleImpl::ReceiveFrequency() const { auto codec_id = RentACodec::CodecIdFromIndex(receiver_.last_audio_codec_id()); return codec_id ? RentACodec::CodecInstById(*codec_id)->plfreq - : receiver_.current_sample_rate_hz(); + : receiver_.last_output_sample_rate_hz(); } // Get current playout frequency. int AudioCodingModuleImpl::PlayoutFrequency() const { WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_, "PlayoutFrequency()"); - - CriticalSectionScoped lock(acm_crit_sect_.get()); - - return receiver_.current_sample_rate_hz(); + return receiver_.last_output_sample_rate_hz(); } // Register possible receive codecs, can be called multiple times, diff --git a/webrtc/modules/audio_coding/neteq/include/neteq.h b/webrtc/modules/audio_coding/neteq/include/neteq.h index 9a1bc17b8b..88677d8355 100644 --- a/webrtc/modules/audio_coding/neteq/include/neteq.h +++ b/webrtc/modules/audio_coding/neteq/include/neteq.h @@ -251,6 +251,11 @@ class NetEq { // Returns true if the RTP timestamp is valid, otherwise false. virtual bool GetPlayoutTimestamp(uint32_t* timestamp) = 0; + // Returns the sample rate in Hz of the audio produced in the last GetAudio + // call. If GetAudio has not been called yet, the configured sample rate + // (Config::sample_rate_hz) is returned. + virtual int last_output_sample_rate_hz() const = 0; + // Not implemented. virtual int SetTargetNumberOfChannels() = 0; diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc index 5fa2cbd586..ed0c83f08b 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -106,6 +106,7 @@ NetEqImpl::NetEqImpl(const NetEq::Config& config, } fs_hz_ = fs; fs_mult_ = fs / 8000; + last_output_sample_rate_hz_ = fs; output_size_samples_ = static_cast(kOutputSizeMs * 8 * fs_mult_); decoder_frame_length_ = 3 * output_size_samples_; WebRtcSpl_Init(); @@ -160,6 +161,13 @@ 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); + RTC_DCHECK(last_output_sample_rate_hz_ == 8000 || + last_output_sample_rate_hz_ == 16000 || + last_output_sample_rate_hz_ == 32000 || + last_output_sample_rate_hz_ == 48000) + << "Unexpected sample rate " << last_output_sample_rate_hz_; return kOK; } @@ -359,6 +367,11 @@ bool NetEqImpl::GetPlayoutTimestamp(uint32_t* timestamp) { return true; } +int NetEqImpl::last_output_sample_rate_hz() const { + CriticalSectionScoped lock(crit_sect_.get()); + return last_output_sample_rate_hz_; +} + int NetEqImpl::SetTargetNumberOfChannels() { return kNotImplemented; } diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.h b/webrtc/modules/audio_coding/neteq/neteq_impl.h index 60c846d619..0fc204f0e8 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.h +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.h @@ -168,6 +168,8 @@ class NetEqImpl : public webrtc::NetEq { bool GetPlayoutTimestamp(uint32_t* timestamp) override; + int last_output_sample_rate_hz() const override; + int SetTargetNumberOfChannels() override; int SetTargetSampleRate() override; @@ -375,6 +377,7 @@ class NetEqImpl : public webrtc::NetEq { StatisticsCalculator stats_ GUARDED_BY(crit_sect_); int fs_hz_ GUARDED_BY(crit_sect_); int fs_mult_ GUARDED_BY(crit_sect_); + int last_output_sample_rate_hz_ GUARDED_BY(crit_sect_); size_t output_size_samples_ GUARDED_BY(crit_sect_); size_t decoder_frame_length_ GUARDED_BY(crit_sect_); Modes last_mode_ GUARDED_BY(crit_sect_); diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc index 11fdfe9a45..5d1dc0c8c2 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -1230,4 +1230,13 @@ TEST_F(NetEqImplTest, DecodingErrorDuringInternalCng) { EXPECT_CALL(mock_decoder, Die()); } +// Tests that the return value from last_output_sample_rate_hz() is equal to the +// configured inital sample rate. +TEST_F(NetEqImplTest, InitialLastOutputSampleRate) { + UseNoMocks(); + config_.sample_rate_hz = 48000; + CreateInstance(); + EXPECT_EQ(48000, neteq_->last_output_sample_rate_hz()); +} + }// namespace webrtc diff --git a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc index 2088cd13af..5d75a4ff39 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc @@ -362,6 +362,7 @@ void NetEqDecodingTest::Process(size_t* out_len) { (*out_len == kBlockSize16kHz) || (*out_len == kBlockSize32kHz)); output_sample_rate_ = static_cast(*out_len / 10 * 1000); + EXPECT_EQ(output_sample_rate_, neteq_->last_output_sample_rate_hz()); // Increase time. sim_clock_ += kTimeStepMs; @@ -895,6 +896,8 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { SCOPED_TRACE(ss.str()); // Print out the parameter values on failure. EXPECT_EQ(0, out_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()); } class NetEqBgnTest : public NetEqDecodingTest { 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 dcf5f616d9..13b418504a 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 @@ -56,6 +56,7 @@ size_t NetEqExternalDecoderTest::GetOutputAudio(size_t max_length, EXPECT_EQ(channels_, num_channels); EXPECT_EQ(static_cast(kOutputLengthMs * sample_rate_hz_ / 1000), samples_per_channel); + EXPECT_EQ(sample_rate_hz_, neteq_->last_output_sample_rate_hz()); return samples_per_channel; }