diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder.h b/webrtc/modules/audio_coding/codecs/audio_encoder.h index 9025834dfa..fe6fd87dfd 100644 --- a/webrtc/modules/audio_coding/codecs/audio_encoder.h +++ b/webrtc/modules/audio_coding/codecs/audio_encoder.h @@ -96,6 +96,11 @@ class AudioEncoder { // Num10MsFramesInNextPacket(). virtual int Max10MsFramesInAPacket() const = 0; + // Returns the current target bitrate in bits/s. The value -1 means that the + // codec adapts the target automatically, and a current target cannot be + // provided. + virtual int GetTargetBitrate() const = 0; + // Changes the target bitrate. The implementation is free to alter this value, // e.g., if the desired value is outside the valid range. virtual void SetTargetBitrate(int bits_per_second) {} diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h b/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h index 0bf818a037..553d8ad4b8 100644 --- a/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h +++ b/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h @@ -82,6 +82,10 @@ class AudioEncoderMutableImpl : public P { CriticalSectionScoped cs(encoder_lock_.get()); return encoder_->Max10MsFramesInAPacket(); } + int GetTargetBitrate() const override { + CriticalSectionScoped cs(encoder_lock_.get()); + return encoder_->GetTargetBitrate(); + } void SetTargetBitrate(int bits_per_second) override { CriticalSectionScoped cs(encoder_lock_.get()); encoder_->SetTargetBitrate(bits_per_second); diff --git a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc index c662b5ba5a..d2acaa1a1a 100644 --- a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc +++ b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc @@ -97,6 +97,10 @@ int AudioEncoderCng::Max10MsFramesInAPacket() const { return speech_encoder_->Max10MsFramesInAPacket(); } +int AudioEncoderCng::GetTargetBitrate() const { + return speech_encoder_->GetTargetBitrate(); +} + void AudioEncoderCng::SetTargetBitrate(int bits_per_second) { speech_encoder_->SetTargetBitrate(bits_per_second); } diff --git a/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h b/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h index 094b73074b..51d2febad6 100644 --- a/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h +++ b/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h @@ -52,6 +52,7 @@ class AudioEncoderCng final : public AudioEncoder { int RtpTimestampRateHz() const override; int Num10MsFramesInNextPacket() const override; int Max10MsFramesInAPacket() const override; + int GetTargetBitrate() const override; void SetTargetBitrate(int bits_per_second) override; void SetProjectedPacketLossRate(double fraction) override; EncodedInfo EncodeInternal(uint32_t rtp_timestamp, diff --git a/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc b/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc index ed49618646..905a7152dd 100644 --- a/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc +++ b/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc @@ -60,7 +60,7 @@ int AudioEncoderPcm::NumChannels() const { } size_t AudioEncoderPcm::MaxEncodedBytes() const { - return full_frame_samples_; + return full_frame_samples_ * BytesPerSample(); } int AudioEncoderPcm::Num10MsFramesInNextPacket() const { @@ -71,6 +71,10 @@ int AudioEncoderPcm::Max10MsFramesInAPacket() const { return num_10ms_frames_per_packet_; } +int AudioEncoderPcm::GetTargetBitrate() const { + return 8 * BytesPerSample() * SampleRateHz() * NumChannels(); +} + AudioEncoder::EncodedInfo AudioEncoderPcm::EncodeInternal( uint32_t rtp_timestamp, const int16_t* audio, @@ -104,12 +108,20 @@ int16_t AudioEncoderPcmA::EncodeCall(const int16_t* audio, return WebRtcG711_EncodeA(audio, static_cast(input_len), encoded); } +int AudioEncoderPcmA::BytesPerSample() const { + return 1; +} + int16_t AudioEncoderPcmU::EncodeCall(const int16_t* audio, size_t input_len, uint8_t* encoded) { return WebRtcG711_EncodeU(audio, static_cast(input_len), encoded); } +int AudioEncoderPcmU::BytesPerSample() const { + return 1; +} + namespace { template typename T::Config CreateConfig(const CodecInst& codec_inst) { diff --git a/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h b/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h index 870b4ddfb6..c8690379c6 100644 --- a/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h +++ b/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h @@ -41,6 +41,7 @@ class AudioEncoderPcm : public AudioEncoder { size_t MaxEncodedBytes() const override; int Num10MsFramesInNextPacket() const override; int Max10MsFramesInAPacket() const override; + int GetTargetBitrate() const override; EncodedInfo EncodeInternal(uint32_t rtp_timestamp, const int16_t* audio, size_t max_encoded_bytes, @@ -53,6 +54,8 @@ class AudioEncoderPcm : public AudioEncoder { size_t input_len, uint8_t* encoded) = 0; + virtual int BytesPerSample() const = 0; + private: const int sample_rate_hz_; const int num_channels_; @@ -63,7 +66,7 @@ class AudioEncoderPcm : public AudioEncoder { uint32_t first_timestamp_in_buffer_; }; -class AudioEncoderPcmA : public AudioEncoderPcm { +class AudioEncoderPcmA final : public AudioEncoderPcm { public: struct Config : public AudioEncoderPcm::Config { Config() : AudioEncoderPcm::Config(8) {} @@ -77,11 +80,13 @@ class AudioEncoderPcmA : public AudioEncoderPcm { size_t input_len, uint8_t* encoded) override; + int BytesPerSample() const override; + private: static const int kSampleRateHz = 8000; }; -class AudioEncoderPcmU : public AudioEncoderPcm { +class AudioEncoderPcmU final : public AudioEncoderPcm { public: struct Config : public AudioEncoderPcm::Config { Config() : AudioEncoderPcm::Config(0) {} @@ -95,6 +100,8 @@ class AudioEncoderPcmU : public AudioEncoderPcm { size_t input_len, uint8_t* encoded) override; + int BytesPerSample() const override; + private: static const int kSampleRateHz = 8000; }; diff --git a/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc b/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc index 8e10dffe8e..a0d1720e46 100644 --- a/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc +++ b/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc @@ -82,6 +82,11 @@ int AudioEncoderG722::Max10MsFramesInAPacket() const { return num_10ms_frames_per_packet_; } +int AudioEncoderG722::GetTargetBitrate() const { + // 4 bits/sample, 16000 samples/s/channel. + return 64000 * NumChannels(); +} + AudioEncoder::EncodedInfo AudioEncoderG722::EncodeInternal( uint32_t rtp_timestamp, const int16_t* audio, diff --git a/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h b/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h index f5e0a9899f..9b57fbe625 100644 --- a/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h +++ b/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h @@ -19,7 +19,7 @@ namespace webrtc { -class AudioEncoderG722 : public AudioEncoder { +class AudioEncoderG722 final : public AudioEncoder { public: struct Config { Config() : payload_type(9), frame_size_ms(20), num_channels(1) {} @@ -39,6 +39,7 @@ class AudioEncoderG722 : public AudioEncoder { int RtpTimestampRateHz() const override; int Num10MsFramesInNextPacket() const override; int Max10MsFramesInAPacket() const override; + int GetTargetBitrate() const override; EncodedInfo EncodeInternal(uint32_t rtp_timestamp, const int16_t* audio, size_t max_encoded_bytes, diff --git a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc index 66d24650a6..8dc9bdf4bd 100644 --- a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc +++ b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc @@ -66,6 +66,19 @@ int AudioEncoderIlbc::Max10MsFramesInAPacket() const { return num_10ms_frames_per_packet_; } +int AudioEncoderIlbc::GetTargetBitrate() const { + switch (num_10ms_frames_per_packet_) { + case 2: case 4: + // 38 bytes per frame of 20 ms => 15200 bits/s. + return 15200; + case 3: case 6: + // 50 bytes per frame of 30 ms => (approx) 13333 bits/s. + return 13333; + default: + FATAL(); + } +} + AudioEncoder::EncodedInfo AudioEncoderIlbc::EncodeInternal( uint32_t rtp_timestamp, const int16_t* audio, diff --git a/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h b/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h index c172db1b8f..b627c3a087 100644 --- a/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h +++ b/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h @@ -18,7 +18,7 @@ namespace webrtc { -class AudioEncoderIlbc : public AudioEncoder { +class AudioEncoderIlbc final : public AudioEncoder { public: struct Config { Config() : payload_type(102), frame_size_ms(30) {} @@ -38,6 +38,7 @@ class AudioEncoderIlbc : public AudioEncoder { size_t MaxEncodedBytes() const override; int Num10MsFramesInNextPacket() const override; int Max10MsFramesInAPacket() const override; + int GetTargetBitrate() const override; EncodedInfo EncodeInternal(uint32_t rtp_timestamp, const int16_t* audio, size_t max_encoded_bytes, diff --git a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h index b67a9b09fc..49df3c68be 100644 --- a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h +++ b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h @@ -59,6 +59,7 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder { size_t MaxEncodedBytes() const override; int Num10MsFramesInNextPacket() const override; int Max10MsFramesInAPacket() const override; + int GetTargetBitrate() const override; // AudioDecoder methods. bool HasDecodePlc() const override; @@ -113,6 +114,8 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder { // Timestamp of the previously encoded packet. uint32_t last_encoded_timestamp_ GUARDED_BY(lock_); + const int target_bitrate_bps_; + DISALLOW_COPY_AND_ASSIGN(AudioEncoderDecoderIsacT); }; diff --git a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h index befb3558be..d2b20e3b94 100644 --- a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h +++ b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h @@ -70,16 +70,18 @@ AudioEncoderDecoderIsacT::AudioEncoderDecoderIsacT(const Config& config) state_lock_(CriticalSectionWrapper::CreateCriticalSection()), decoder_sample_rate_hz_(0), lock_(CriticalSectionWrapper::CreateCriticalSection()), - packet_in_progress_(false) { + packet_in_progress_(false), + target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0 + ? kDefaultBitRate + : config.bit_rate)) { CHECK(config.IsOk()); CHECK_EQ(0, T::Create(&isac_state_)); CHECK_EQ(0, T::EncoderInit(isac_state_, config.adaptive_mode ? 0 : 1)); CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz)); const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate; if (config.adaptive_mode) { - CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, - config.frame_size_ms, config.enforce_frame_size)); - + CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms, + config.enforce_frame_size)); } else { CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms)); } @@ -129,6 +131,11 @@ int AudioEncoderDecoderIsacT::Max10MsFramesInAPacket() const { return 6; // iSAC puts at most 60 ms in a packet. } +template +int AudioEncoderDecoderIsacT::GetTargetBitrate() const { + return target_bitrate_bps_; +} + template AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT::EncodeInternal( uint32_t rtp_timestamp, diff --git a/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h b/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h index 786c83cd6a..18d4068873 100644 --- a/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h +++ b/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h @@ -26,6 +26,7 @@ class MockAudioEncoder : public AudioEncoder { MOCK_CONST_METHOD0(MaxEncodedBytes, size_t()); MOCK_CONST_METHOD0(Num10MsFramesInNextPacket, int()); MOCK_CONST_METHOD0(Max10MsFramesInAPacket, int()); + MOCK_CONST_METHOD0(GetTargetBitrate, int()); MOCK_METHOD1(SetTargetBitrate, void(int)); MOCK_METHOD1(SetProjectedPacketLossRate, void(double)); // Note, we explicitly chose not to create a mock for the Encode method. @@ -43,6 +44,7 @@ class MockAudioEncoderMutable : public AudioEncoderMutable { MOCK_CONST_METHOD0(MaxEncodedBytes, size_t()); MOCK_CONST_METHOD0(Num10MsFramesInNextPacket, int()); MOCK_CONST_METHOD0(Max10MsFramesInAPacket, int()); + MOCK_CONST_METHOD0(GetTargetBitrate, int()); MOCK_METHOD1(SetTargetBitrate, void(int)); MOCK_METHOD1(SetProjectedPacketLossRate, void(double)); // Note, we explicitly chose not to create a mock for the Encode method. diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc index ed3f52fff7..3a083985df 100644 --- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc +++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc @@ -79,6 +79,30 @@ TEST_F(AudioEncoderMutableOpusTest, ToggleDtx) { // Turn off DTX. EXPECT_TRUE(encoder_->SetDtx(false)); } + +TEST_F(AudioEncoderMutableOpusTest, SetBitrate) { + CreateCodec(1); + // Constants are replicated from audio_encoder_opus.cc. + const int kMinBitrateBps = 500; + const int kMaxBitrateBps = 512000; + // Set a too low bitrate. + encoder_->SetTargetBitrate(kMinBitrateBps - 1); + EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate()); + // Set a too high bitrate. + encoder_->SetTargetBitrate(kMaxBitrateBps + 1); + EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate()); + // Set the minimum rate. + encoder_->SetTargetBitrate(kMinBitrateBps); + EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate()); + // Set the maximum rate. + encoder_->SetTargetBitrate(kMaxBitrateBps); + EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate()); + // Set rates from 1000 up to 32000 bps. + for (int rate = 1000; rate <= 32000; rate += 1000) { + encoder_->SetTargetBitrate(rate); + EXPECT_EQ(rate, encoder_->GetTargetBitrate()); + } +} #endif // WEBRTC_CODEC_OPUS } // namespace acm2 diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc index 328698380a..88e084fe1d 100644 --- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc +++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc @@ -129,6 +129,10 @@ int AudioEncoderOpus::Max10MsFramesInAPacket() const { return num_10ms_frames_per_packet_; } +int AudioEncoderOpus::GetTargetBitrate() const { + return bitrate_bps_; +} + void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) { bitrate_bps_ = std::max(std::min(bits_per_second, kMaxBitrateBps), kMinBitrateBps); diff --git a/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h b/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h index 4de4e26273..3393bd516d 100644 --- a/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h +++ b/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h @@ -52,12 +52,14 @@ class AudioEncoderOpus final : public AudioEncoder { size_t MaxEncodedBytes() const override; int Num10MsFramesInNextPacket() const override; int Max10MsFramesInAPacket() const override; + int GetTargetBitrate() const override; void SetTargetBitrate(int bits_per_second) override; void SetProjectedPacketLossRate(double fraction) override; double packet_loss_rate() const { return packet_loss_rate_; } ApplicationMode application() const { return application_; } bool dtx_enabled() const { return dtx_enabled_; } + EncodedInfo EncodeInternal(uint32_t rtp_timestamp, const int16_t* audio, size_t max_encoded_bytes, diff --git a/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc b/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc index 491fdfdb14..0c246c34bd 100644 --- a/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc +++ b/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc @@ -29,6 +29,10 @@ int16_t AudioEncoderPcm16B::EncodeCall(const int16_t* audio, return WebRtcPcm16b_Encode(audio, static_cast(input_len), encoded); } +int AudioEncoderPcm16B::BytesPerSample() const { + return 2; +} + namespace { AudioEncoderPcm16B::Config CreateConfig(const CodecInst& codec_inst) { AudioEncoderPcm16B::Config config; diff --git a/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h b/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h index f1e1c51da8..f02cf92dd9 100644 --- a/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h +++ b/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h @@ -17,7 +17,7 @@ namespace webrtc { -class AudioEncoderPcm16B : public AudioEncoderPcm { +class AudioEncoderPcm16B final : public AudioEncoderPcm { public: struct Config : public AudioEncoderPcm::Config { public: @@ -34,6 +34,8 @@ class AudioEncoderPcm16B : public AudioEncoderPcm { int16_t EncodeCall(const int16_t* audio, size_t input_len, uint8_t* encoded) override; + + int BytesPerSample() const override; }; struct CodecInst; diff --git a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc index cc657a6838..16ba290fc3 100644 --- a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc +++ b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc @@ -49,6 +49,10 @@ int AudioEncoderCopyRed::Max10MsFramesInAPacket() const { return speech_encoder_->Max10MsFramesInAPacket(); } +int AudioEncoderCopyRed::GetTargetBitrate() const { + return speech_encoder_->GetTargetBitrate(); +} + void AudioEncoderCopyRed::SetTargetBitrate(int bits_per_second) { speech_encoder_->SetTargetBitrate(bits_per_second); } diff --git a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h index 49ab948fab..78e1e9aff3 100644 --- a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h +++ b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h @@ -42,6 +42,7 @@ class AudioEncoderCopyRed : public AudioEncoder { int RtpTimestampRateHz() const override; int Num10MsFramesInNextPacket() const override; int Max10MsFramesInAPacket() const override; + int GetTargetBitrate() const override; void SetTargetBitrate(int bits_per_second) override; void SetProjectedPacketLossRate(double fraction) override; EncodedInfo EncodeInternal(uint32_t rtp_timestamp, diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc index 1850807783..d54fbe9099 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc @@ -485,6 +485,24 @@ TEST_F(AudioDecoderPcmUTest, EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +namespace { +int SetAndGetTargetBitrate(AudioEncoder* audio_encoder, int rate) { + audio_encoder->SetTargetBitrate(rate); + return audio_encoder->GetTargetBitrate(); +} +void TestSetAndGetTargetBitratesWithFixedCodec(AudioEncoder* audio_encoder, + int fixed_rate) { + EXPECT_EQ(fixed_rate, SetAndGetTargetBitrate(audio_encoder, 32000)); + EXPECT_EQ(fixed_rate, SetAndGetTargetBitrate(audio_encoder, fixed_rate - 1)); + EXPECT_EQ(fixed_rate, SetAndGetTargetBitrate(audio_encoder, fixed_rate)); + EXPECT_EQ(fixed_rate, SetAndGetTargetBitrate(audio_encoder, fixed_rate + 1)); +} +} // namespace + +TEST_F(AudioDecoderPcmUTest, SetTargetBitrate) { + TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 64000); +} + TEST_F(AudioDecoderPcmATest, EncodeDecode) { int tolerance = 308; double mse = 1931.0; @@ -494,6 +512,10 @@ TEST_F(AudioDecoderPcmATest, EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +TEST_F(AudioDecoderPcmATest, SetTargetBitrate) { + TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 64000); +} + TEST_F(AudioDecoderPcm16BTest, EncodeDecode) { int tolerance = 0; double mse = 0.0; @@ -506,6 +528,11 @@ TEST_F(AudioDecoderPcm16BTest, EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +TEST_F(AudioDecoderPcm16BTest, SetTargetBitrate) { + TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), + codec_input_rate_hz_ * 16); +} + TEST_F(AudioDecoderIlbcTest, EncodeDecode) { int tolerance = 6808; double mse = 2.13e6; @@ -517,6 +544,10 @@ TEST_F(AudioDecoderIlbcTest, EncodeDecode) { DecodePlcTest(); } +TEST_F(AudioDecoderIlbcTest, SetTargetBitrate) { + TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 13333); +} + TEST_F(AudioDecoderIsacFloatTest, EncodeDecode) { int tolerance = 3399; double mse = 434951.0; @@ -527,6 +558,10 @@ TEST_F(AudioDecoderIsacFloatTest, EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +TEST_F(AudioDecoderIsacFloatTest, SetTargetBitrate) { + TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 32000); +} + TEST_F(AudioDecoderIsacSwbTest, EncodeDecode) { int tolerance = 19757; double mse = 8.18e6; @@ -537,6 +572,10 @@ TEST_F(AudioDecoderIsacSwbTest, EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +TEST_F(AudioDecoderIsacSwbTest, SetTargetBitrate) { + TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 32000); +} + // Fails Android ARM64. https://code.google.com/p/webrtc/issues/detail?id=4198 #if defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM64) #define MAYBE_EncodeDecode DISABLED_EncodeDecode @@ -558,6 +597,10 @@ TEST_F(AudioDecoderIsacFixTest, MAYBE_EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +TEST_F(AudioDecoderIsacFixTest, SetTargetBitrate) { + TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 32000); +} + TEST_F(AudioDecoderG722Test, EncodeDecode) { int tolerance = 6176; double mse = 238630.0; @@ -568,6 +611,10 @@ TEST_F(AudioDecoderG722Test, EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +TEST_F(AudioDecoderG722Test, SetTargetBitrate) { + TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 64000); +} + TEST_F(AudioDecoderG722StereoTest, CreateAndDestroy) { EXPECT_TRUE(CodecSupported(kDecoderG722_2ch)); } @@ -583,6 +630,10 @@ TEST_F(AudioDecoderG722StereoTest, EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +TEST_F(AudioDecoderG722StereoTest, SetTargetBitrate) { + TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 128000); +} + TEST_F(AudioDecoderOpusTest, EncodeDecode) { int tolerance = 6176; double mse = 238630.0; @@ -593,6 +644,20 @@ TEST_F(AudioDecoderOpusTest, EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +namespace { +void TestOpusSetTargetBitrates(AudioEncoder* audio_encoder) { + EXPECT_EQ(500, SetAndGetTargetBitrate(audio_encoder, 499)); + EXPECT_EQ(500, SetAndGetTargetBitrate(audio_encoder, 500)); + EXPECT_EQ(32000, SetAndGetTargetBitrate(audio_encoder, 32000)); + EXPECT_EQ(512000, SetAndGetTargetBitrate(audio_encoder, 512000)); + EXPECT_EQ(512000, SetAndGetTargetBitrate(audio_encoder, 513000)); +} +} // namespace + +TEST_F(AudioDecoderOpusTest, SetTargetBitrate) { + TestOpusSetTargetBitrates(audio_encoder_.get()); +} + TEST_F(AudioDecoderOpusStereoTest, EncodeDecode) { int tolerance = 6176; int channel_diff_tolerance = 0; @@ -604,6 +669,10 @@ TEST_F(AudioDecoderOpusStereoTest, EncodeDecode) { EXPECT_FALSE(decoder_->HasDecodePlc()); } +TEST_F(AudioDecoderOpusStereoTest, SetTargetBitrate) { + TestOpusSetTargetBitrates(audio_encoder_.get()); +} + TEST(AudioDecoder, CodecSampleRateHz) { EXPECT_EQ(8000, CodecSampleRateHz(kDecoderPCMu)); EXPECT_EQ(8000, CodecSampleRateHz(kDecoderPCMa));