diff --git a/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h b/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h index 7998fdbdeb..3bc7d0e891 100644 --- a/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h +++ b/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h @@ -72,6 +72,27 @@ int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate); */ int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate); +/**************************************************************************** + * WebRtcOpus_SetMaxBandwidth(...) + * + * Configures the maximum bandwidth for encoding. This can be taken as a hint + * about the maximum output bandwidth that the receiver is capable to render, + * due to hardware limitations. Sending signals with higher audio bandwidth + * results in higher than necessary network usage and encoding complexity. + * + * Input: + * - inst : Encoder context + * - bandwidth : Maximum encoding bandwidth in Hz. + * This parameter can take any value, but values + * other than Opus typical bandwidths: 4000, 6000, + * 8000, 12000, and 20000 will be rounded up (values + * greater than 20000 will be rounded down) to + * these values. + * Return value : 0 - Success + * -1 - Error + */ +int16_t WebRtcOpus_SetMaxBandwidth(OpusEncInst* inst, int32_t bandwidth); + /* TODO(minyue): Check whether an API to check the FEC and the packet loss rate * is needed. It might not be very useful since there are not many use cases and * the caller can always maintain the states. */ diff --git a/webrtc/modules/audio_coding/codecs/opus/opus.gypi b/webrtc/modules/audio_coding/codecs/opus/opus.gypi index b1dedd7d4a..89f0a54a76 100644 --- a/webrtc/modules/audio_coding/codecs/opus/opus.gypi +++ b/webrtc/modules/audio_coding/codecs/opus/opus.gypi @@ -28,6 +28,7 @@ ], 'sources': [ 'interface/opus_interface.h', + 'opus_inst.h', 'opus_interface.c', ], }, diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_inst.h b/webrtc/modules/audio_coding/codecs/opus/opus_inst.h new file mode 100644 index 0000000000..50caf8373f --- /dev/null +++ b/webrtc/modules/audio_coding/codecs/opus/opus_inst.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INST_H_ +#define WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INST_H_ + +#include "opus.h" + +struct WebRtcOpusEncInst { + OpusEncoder* encoder; +}; + +struct WebRtcOpusDecInst { + OpusDecoder* decoder_left; + OpusDecoder* decoder_right; + int prev_decoded_samples; + int channels; +}; + + +#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INST_H_ diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c index ea535ea97a..94ad1bd92b 100644 --- a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c +++ b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c @@ -9,12 +9,11 @@ */ #include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h" +#include "webrtc/modules/audio_coding/codecs/opus/opus_inst.h" #include #include -#include "opus.h" - enum { /* Maximum supported frame size in WebRTC is 60 ms. */ kWebRtcOpusMaxEncodeFrameSizeMs = 60, @@ -32,10 +31,6 @@ enum { kWebRtcOpusDefaultFrameSize = 960, }; -struct WebRtcOpusEncInst { - OpusEncoder* encoder; -}; - int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, int32_t channels) { OpusEncInst* state; if (inst != NULL) { @@ -104,6 +99,27 @@ int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) { } } +int16_t WebRtcOpus_SetMaxBandwidth(OpusEncInst* inst, int32_t bandwidth) { + opus_int32 set_bandwidth; + + if (!inst) + return -1; + + if (bandwidth <= 4000) { + set_bandwidth = OPUS_BANDWIDTH_NARROWBAND; + } else if (bandwidth <= 6000) { + set_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + } else if (bandwidth <= 8000) { + set_bandwidth = OPUS_BANDWIDTH_WIDEBAND; + } else if (bandwidth <= 12000) { + set_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; + } else { + set_bandwidth = OPUS_BANDWIDTH_FULLBAND; + } + return opus_encoder_ctl(inst->encoder, + OPUS_SET_MAX_BANDWIDTH(set_bandwidth)); +} + int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) { if (inst) { return opus_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(1)); @@ -128,13 +144,6 @@ int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) { } } -struct WebRtcOpusDecInst { - OpusDecoder* decoder_left; - OpusDecoder* decoder_right; - int prev_decoded_samples; - int channels; -}; - int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, int channels) { int error_l; int error_r; diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc b/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc index 2ec77a5366..582bb735ef 100644 --- a/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc +++ b/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc @@ -11,11 +11,9 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h" +#include "webrtc/modules/audio_coding/codecs/opus/opus_inst.h" #include "webrtc/test/testsupport/fileutils.h" -struct WebRtcOpusEncInst; -struct WebRtcOpusDecInst; - namespace webrtc { // Number of samples in a 60 ms stereo frame, sampled at 48 kHz. @@ -32,6 +30,8 @@ class OpusTest : public ::testing::Test { OpusTest(); virtual void SetUp(); + void TestSetMaxBandwidth(opus_int32 expect, int32_t set); + WebRtcOpusEncInst* opus_mono_encoder_; WebRtcOpusEncInst* opus_stereo_encoder_; WebRtcOpusDecInst* opus_mono_decoder_; @@ -66,6 +66,20 @@ void OpusTest::SetUp() { input_file = NULL; } +void OpusTest::TestSetMaxBandwidth(opus_int32 expect, int32_t set) { + opus_int32 bandwidth; + // Test mono encoder. + EXPECT_EQ(0, WebRtcOpus_SetMaxBandwidth(opus_mono_encoder_, set)); + opus_encoder_ctl(opus_mono_encoder_->encoder, + OPUS_GET_MAX_BANDWIDTH(&bandwidth)); + EXPECT_EQ(expect, bandwidth); + // Test stereo encoder. + EXPECT_EQ(0, WebRtcOpus_SetMaxBandwidth(opus_stereo_encoder_, set)); + opus_encoder_ctl(opus_stereo_encoder_->encoder, + OPUS_GET_MAX_BANDWIDTH(&bandwidth)); + EXPECT_EQ(expect, bandwidth); +} + // Test failing Create. TEST_F(OpusTest, OpusCreateFail) { // Test to see that an invalid pointer is caught. @@ -341,6 +355,27 @@ TEST_F(OpusTest, OpusSetPacketLossRate) { EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_)); } +TEST_F(OpusTest, OpusSetMaxBandwidth) { + // Test without creating encoder memory. + EXPECT_EQ(-1, WebRtcOpus_SetMaxBandwidth(opus_mono_encoder_, 20000)); + EXPECT_EQ(-1, WebRtcOpus_SetMaxBandwidth(opus_stereo_encoder_, 20000)); + + // Create encoder memory, try with different bitrates. + EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1)); + EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2)); + + TestSetMaxBandwidth(OPUS_BANDWIDTH_FULLBAND, 24000); + TestSetMaxBandwidth(OPUS_BANDWIDTH_FULLBAND, 14000); + TestSetMaxBandwidth(OPUS_BANDWIDTH_SUPERWIDEBAND, 10000); + TestSetMaxBandwidth(OPUS_BANDWIDTH_WIDEBAND, 7000); + TestSetMaxBandwidth(OPUS_BANDWIDTH_MEDIUMBAND, 6000); + TestSetMaxBandwidth(OPUS_BANDWIDTH_NARROWBAND, 4000); + TestSetMaxBandwidth(OPUS_BANDWIDTH_NARROWBAND, 3000); + + // Free memory. + EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_)); + EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_)); +} // PLC in mono mode. TEST_F(OpusTest, OpusDecodePlcMono) {