Setting Opus target application.

This CL is to allow to set Opus target application at the creation of an encoder.

According to Opus spec, there are three applications:

OPUS_APPLICATION_VOIP
OPUS_APPLICATION_AUDIO
OPUS_APPLICATION_RESTRICTED_LOWDELAY

BUG=
R=henrik.lundin@webrtc.org, tina.legrand@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/37479004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@8103 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
minyue@webrtc.org 2015-01-20 16:01:50 +00:00
parent 853049fa30
commit 7dba7860c7
21 changed files with 489 additions and 317 deletions

View File

@ -37,7 +37,10 @@ int16_t CastInt16(size_t x) {
} // namespace } // namespace
AudioEncoderOpus::Config::Config() AudioEncoderOpus::Config::Config()
: frame_size_ms(20), num_channels(1), payload_type(120) { : frame_size_ms(20),
num_channels(1),
payload_type(120),
application(kVoip) {
} }
bool AudioEncoderOpus::Config::IsOk() const { bool AudioEncoderOpus::Config::IsOk() const {
@ -52,10 +55,11 @@ AudioEncoderOpus::AudioEncoderOpus(const Config& config)
: num_10ms_frames_per_packet_(DivExact(config.frame_size_ms, 10)), : num_10ms_frames_per_packet_(DivExact(config.frame_size_ms, 10)),
num_channels_(config.num_channels), num_channels_(config.num_channels),
payload_type_(config.payload_type), payload_type_(config.payload_type),
application_(config.application),
samples_per_10ms_frame_(DivExact(kSampleRateHz, 100) * num_channels_) { samples_per_10ms_frame_(DivExact(kSampleRateHz, 100) * num_channels_) {
CHECK(config.IsOk()); CHECK(config.IsOk());
input_buffer_.reserve(num_10ms_frames_per_packet_ * samples_per_10ms_frame_); input_buffer_.reserve(num_10ms_frames_per_packet_ * samples_per_10ms_frame_);
CHECK_EQ(0, WebRtcOpus_EncoderCreate(&inst_, num_channels_)); CHECK_EQ(0, WebRtcOpus_EncoderCreate(&inst_, num_channels_, application_));
} }
AudioEncoderOpus::~AudioEncoderOpus() { AudioEncoderOpus::~AudioEncoderOpus() {

View File

@ -20,12 +20,18 @@ namespace webrtc {
class AudioEncoderOpus : public AudioEncoder { class AudioEncoderOpus : public AudioEncoder {
public: public:
enum ApplicationMode {
kVoip = 0,
kAudio = 1,
};
struct Config { struct Config {
Config(); Config();
bool IsOk() const; bool IsOk() const;
int frame_size_ms; int frame_size_ms;
int num_channels; int num_channels;
int payload_type; int payload_type;
ApplicationMode application;
}; };
explicit AudioEncoderOpus(const Config& config); explicit AudioEncoderOpus(const Config& config);
@ -47,6 +53,7 @@ class AudioEncoderOpus : public AudioEncoder {
const int num_10ms_frames_per_packet_; const int num_10ms_frames_per_packet_;
const int num_channels_; const int num_channels_;
const int payload_type_; const int payload_type_;
const ApplicationMode application_;
const int samples_per_10ms_frame_; const int samples_per_10ms_frame_;
std::vector<int16_t> input_buffer_; std::vector<int16_t> input_buffer_;
OpusEncInst* inst_; OpusEncInst* inst_;

View File

@ -21,7 +21,29 @@ extern "C" {
typedef struct WebRtcOpusEncInst OpusEncInst; typedef struct WebRtcOpusEncInst OpusEncInst;
typedef struct WebRtcOpusDecInst OpusDecInst; typedef struct WebRtcOpusDecInst OpusDecInst;
int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, int32_t channels); /****************************************************************************
* WebRtcOpus_EncoderCreate(...)
*
* This function create an Opus encoder.
*
* Input:
* - channels : number of channels.
* - application : 0 - VOIP applications.
* Favor speech intelligibility.
* 1 - Audio applications.
* Favor faithfulness to the original input.
*
* Output:
* - inst : a pointer to Encoder context that is created
* if success.
*
* Return value : 0 - Success
* -1 - Error
*/
int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
int32_t channels,
int32_t application);
int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst); int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst);
/**************************************************************************** /****************************************************************************

View File

@ -103,8 +103,11 @@ void OpusFecTest::SetUp() {
out_data_.reset(new int16_t[2 * block_length_sample_ * channels_]); out_data_.reset(new int16_t[2 * block_length_sample_ * channels_]);
bit_stream_.reset(new uint8_t[max_bytes_]); bit_stream_.reset(new uint8_t[max_bytes_]);
// If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
int app = channels_ == 1 ? 0 : 1;
// Create encoder memory. // Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_)); EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
// Set bitrate. // Set bitrate.
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_)); EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));

View File

@ -31,17 +31,31 @@ enum {
kWebRtcOpusDefaultFrameSize = 960, kWebRtcOpusDefaultFrameSize = 960,
}; };
int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, int32_t channels) { int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
int32_t channels,
int32_t application) {
OpusEncInst* state; OpusEncInst* state;
if (inst != NULL) { if (inst != NULL) {
state = (OpusEncInst*) calloc(1, sizeof(OpusEncInst)); state = (OpusEncInst*) calloc(1, sizeof(OpusEncInst));
if (state) { if (state) {
int error; int opus_app;
/* Default to VoIP application for mono, and AUDIO for stereo. */ switch (application) {
int application = (channels == 1) ? OPUS_APPLICATION_VOIP : case 0: {
OPUS_APPLICATION_AUDIO; opus_app = OPUS_APPLICATION_VOIP;
break;
}
case 1: {
opus_app = OPUS_APPLICATION_AUDIO;
break;
}
default: {
free(state);
return -1;
}
}
state->encoder = opus_encoder_create(48000, channels, application, int error;
state->encoder = opus_encoder_create(48000, channels, opus_app,
&error); &error);
state->in_dtx_mode = 0; state->in_dtx_mode = 0;
if (error == OPUS_OK && state->encoder != NULL) { if (error == OPUS_OK && state->encoder != NULL) {

View File

@ -41,8 +41,10 @@ OpusSpeedTest::OpusSpeedTest()
void OpusSpeedTest::SetUp() { void OpusSpeedTest::SetUp() {
AudioCodecSpeedTest::SetUp(); AudioCodecSpeedTest::SetUp();
// If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
int app = channels_ == 1 ? 0 : 1;
/* Create encoder memory. */ /* Create encoder memory. */
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_)); EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
/* Set bitrate. */ /* Set bitrate. */
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_)); EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));

View File

@ -18,6 +18,9 @@
namespace webrtc { namespace webrtc {
using test::AudioLoop; using test::AudioLoop;
using ::testing::TestWithParam;
using ::testing::Values;
using ::testing::Combine;
// Maximum number of bytes in output bitstream. // Maximum number of bytes in output bitstream.
const size_t kMaxBytes = 1000; const size_t kMaxBytes = 1000;
@ -28,11 +31,10 @@ const int kOpus20msFrameSamples = kOpusRateKhz * 20;
// Number of samples-per-channel in a 10 ms frame, sampled at 48 kHz. // Number of samples-per-channel in a 10 ms frame, sampled at 48 kHz.
const int kOpus10msFrameSamples = kOpusRateKhz * 10; const int kOpus10msFrameSamples = kOpusRateKhz * 10;
class OpusTest : public ::testing::Test { class OpusTest : public TestWithParam<::testing::tuple<int, int>> {
protected: protected:
OpusTest(); OpusTest();
void TestSetMaxPlaybackRate(opus_int32 expect, int32_t set);
void TestDtxEffect(bool dtx); void TestDtxEffect(bool dtx);
// Prepare |speech_data_| for encoding, read from a hard-coded file. // Prepare |speech_data_| for encoding, read from a hard-coded file.
@ -48,27 +50,33 @@ class OpusTest : public ::testing::Test {
int16_t* output_audio, int16_t* output_audio,
int16_t* audio_type); int16_t* audio_type);
WebRtcOpusEncInst* opus_mono_encoder_; void SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
WebRtcOpusEncInst* opus_stereo_encoder_; opus_int32 expect, int32_t set);
WebRtcOpusDecInst* opus_mono_decoder_;
WebRtcOpusDecInst* opus_stereo_decoder_; WebRtcOpusEncInst* opus_encoder_;
WebRtcOpusDecInst* opus_decoder_;
AudioLoop speech_data_; AudioLoop speech_data_;
uint8_t bitstream_[kMaxBytes]; uint8_t bitstream_[kMaxBytes];
int encoded_bytes_; int encoded_bytes_;
int channels_;
int application_;
}; };
OpusTest::OpusTest() OpusTest::OpusTest()
: opus_mono_encoder_(NULL), : opus_encoder_(NULL),
opus_stereo_encoder_(NULL), opus_decoder_(NULL),
opus_mono_decoder_(NULL), encoded_bytes_(0),
opus_stereo_decoder_(NULL) { channels_(::testing::get<0>(GetParam())),
application_(::testing::get<1>(GetParam())) {
} }
void OpusTest::PrepareSpeechData(int channel, int block_length_ms, void OpusTest::PrepareSpeechData(int channel, int block_length_ms,
int loop_length_ms) { int loop_length_ms) {
const std::string file_name = const std::string file_name =
webrtc::test::ResourcePath("audio_coding/speech_mono_32_48kHz", "pcm"); webrtc::test::ResourcePath((channel == 1) ?
"audio_coding/testfile32kHz" :
"audio_coding/teststereo32kHz", "pcm");
if (loop_length_ms < block_length_ms) { if (loop_length_ms < block_length_ms) {
loop_length_ms = block_length_ms; loop_length_ms = block_length_ms;
} }
@ -77,16 +85,12 @@ void OpusTest::PrepareSpeechData(int channel, int block_length_ms,
block_length_ms * kOpusRateKhz * channel)); block_length_ms * kOpusRateKhz * channel));
} }
void OpusTest::TestSetMaxPlaybackRate(opus_int32 expect, int32_t set) { void OpusTest::SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
opus_int32 expect,
int32_t set) {
opus_int32 bandwidth; opus_int32 bandwidth;
// Test mono encoder. EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, set));
EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_mono_encoder_, set)); opus_encoder_ctl(opus_encoder_->encoder,
opus_encoder_ctl(opus_mono_encoder_->encoder,
OPUS_GET_MAX_BANDWIDTH(&bandwidth));
EXPECT_EQ(expect, bandwidth);
// Test stereo encoder.
EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_stereo_encoder_, set));
opus_encoder_ctl(opus_stereo_encoder_->encoder,
OPUS_GET_MAX_BANDWIDTH(&bandwidth)); OPUS_GET_MAX_BANDWIDTH(&bandwidth));
EXPECT_EQ(expect, bandwidth); EXPECT_EQ(expect, bandwidth);
} }
@ -109,105 +113,109 @@ int OpusTest::EncodeDecode(WebRtcOpusEncInst* encoder,
// Test if encoder/decoder can enter DTX mode properly and do not enter DTX when // Test if encoder/decoder can enter DTX mode properly and do not enter DTX when
// they should not. This test is signal dependent. // they should not. This test is signal dependent.
void OpusTest::TestDtxEffect(bool dtx) { void OpusTest::TestDtxEffect(bool dtx) {
PrepareSpeechData(1, 20, 2000); PrepareSpeechData(channels_, 20, 2000);
// Create encoder memory. // Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1)); channels_,
application_));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
// Set bitrate. // Set bitrate.
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 32000)); EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_,
channels_ == 1 ? 32000 : 64000));
// Set input audio as silence. // Set input audio as silence.
int16_t silence[kOpus20msFrameSamples] = {0}; int16_t* silence = new int16_t[kOpus20msFrameSamples * channels_];
memset(silence, 0, sizeof(int16_t) * kOpus20msFrameSamples * channels_);
// Setting DTX. // Setting DTX.
EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_mono_encoder_) : EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_encoder_) :
WebRtcOpus_DisableDtx(opus_mono_encoder_)); WebRtcOpus_DisableDtx(opus_encoder_));
int16_t audio_type; int16_t audio_type;
int16_t output_data_decode[kOpus20msFrameSamples]; int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 100; ++i) {
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_mono_encoder_, speech_data_.GetNextBlock(), EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
kOpus20msFrameSamples, opus_mono_decoder_, kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type)); output_data_decode, &audio_type));
// If not DTX, it should never enter DTX mode. If DTX, we do not care since // If not DTX, it should never enter DTX mode. If DTX, we do not care since
// whether it enters DTX depends on the signal type. // whether it enters DTX depends on the signal type.
if (!dtx) { if (!dtx) {
EXPECT_GT(encoded_bytes_, 1); EXPECT_GT(encoded_bytes_, 1);
EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode); EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode); EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech. EXPECT_EQ(0, audio_type); // Speech.
} }
} }
// We input some silent segments. In DTX mode, the encoder will stop sending. // We input some silent segments. In DTX mode, the encoder will stop sending.
// However, DTX may happen after a while. // However, DTX may happen after a while.
for (int i = 0; i < 22; ++i) { for (int i = 0; i < 30; ++i) {
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_mono_encoder_, silence, EncodeDecode(opus_encoder_, silence,
kOpus20msFrameSamples, opus_mono_decoder_, kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type)); output_data_decode, &audio_type));
if (!dtx) { if (!dtx) {
EXPECT_GT(encoded_bytes_, 1); EXPECT_GT(encoded_bytes_, 1);
EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode); EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode); EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech. EXPECT_EQ(0, audio_type); // Speech.
} else if (1 == encoded_bytes_) { } else if (1 == encoded_bytes_) {
EXPECT_EQ(1, opus_mono_encoder_->in_dtx_mode); EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
EXPECT_EQ(1, opus_mono_decoder_->in_dtx_mode); EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
EXPECT_EQ(2, audio_type); // Comfort noise. EXPECT_EQ(2, audio_type); // Comfort noise.
break; break;
} }
} }
// DTX mode is maintained 400 ms. // DTX mode is maintained 400 ms.
for (int i = 0; i < 20; ++i) { for (int i = 0; i < 19; ++i) {
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_mono_encoder_, silence, EncodeDecode(opus_encoder_, silence,
kOpus20msFrameSamples, opus_mono_decoder_, kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type)); output_data_decode, &audio_type));
if (dtx) { if (dtx) {
EXPECT_EQ(0, encoded_bytes_) // Send 0 byte. EXPECT_EQ(0, encoded_bytes_) // Send 0 byte.
<< "Opus should have entered DTX mode."; << "Opus should have entered DTX mode.";
EXPECT_EQ(1, opus_mono_encoder_->in_dtx_mode); EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
EXPECT_EQ(1, opus_mono_decoder_->in_dtx_mode); EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
EXPECT_EQ(2, audio_type); // Comfort noise. EXPECT_EQ(2, audio_type); // Comfort noise.
} else { } else {
EXPECT_GT(encoded_bytes_, 1); EXPECT_GT(encoded_bytes_, 1);
EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode); EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode); EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech. EXPECT_EQ(0, audio_type); // Speech.
} }
} }
// Quit DTX after 400 ms // Quit DTX after 400 ms
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_mono_encoder_, silence, EncodeDecode(opus_encoder_, silence,
kOpus20msFrameSamples, opus_mono_decoder_, kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type)); output_data_decode, &audio_type));
EXPECT_GT(encoded_bytes_, 1); EXPECT_GT(encoded_bytes_, 1);
EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode); EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode); EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech. EXPECT_EQ(0, audio_type); // Speech.
// Enters DTX again immediately. // Enters DTX again immediately.
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_mono_encoder_, silence, EncodeDecode(opus_encoder_, silence,
kOpus20msFrameSamples, opus_mono_decoder_, kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type)); output_data_decode, &audio_type));
if (dtx) { if (dtx) {
EXPECT_EQ(1, encoded_bytes_); // Send 1 byte. EXPECT_EQ(1, encoded_bytes_); // Send 1 byte.
EXPECT_EQ(1, opus_mono_encoder_->in_dtx_mode); EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
EXPECT_EQ(1, opus_mono_decoder_->in_dtx_mode); EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
EXPECT_EQ(2, audio_type); // Comfort noise. EXPECT_EQ(2, audio_type); // Comfort noise.
} else { } else {
EXPECT_GT(encoded_bytes_, 1); EXPECT_GT(encoded_bytes_, 1);
EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode); EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode); EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech. EXPECT_EQ(0, audio_type); // Speech.
} }
@ -215,386 +223,340 @@ void OpusTest::TestDtxEffect(bool dtx) {
if (dtx) { if (dtx) {
// Verify that encoder/decoder can jump out from DTX mode. // Verify that encoder/decoder can jump out from DTX mode.
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_mono_encoder_, silence, EncodeDecode(opus_encoder_, silence,
kOpus20msFrameSamples, opus_mono_decoder_, kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type)); output_data_decode, &audio_type));
EXPECT_GT(encoded_bytes_, 1); EXPECT_GT(encoded_bytes_, 1);
EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode); EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode); EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech. EXPECT_EQ(0, audio_type); // Speech.
} }
// Free memory. // Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_)); delete[] output_data_decode;
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_)); delete[] silence;
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
} }
// Test failing Create. // Test failing Create.
TEST_F(OpusTest, OpusCreateFail) { TEST(OpusTest, OpusCreateFail) {
WebRtcOpusEncInst* opus_encoder;
WebRtcOpusDecInst* opus_decoder;
// Test to see that an invalid pointer is caught. // Test to see that an invalid pointer is caught.
EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1)); EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1, 0));
EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 3)); // Invalid channel number.
EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 3, 0));
// Invalid applciation mode.
EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 2));
EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1)); EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1));
EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 3)); // Invalid channel number.
EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 3));
} }
// Test failing Free. // Test failing Free.
TEST_F(OpusTest, OpusFreeFail) { TEST(OpusTest, OpusFreeFail) {
// Test to see that an invalid pointer is caught. // Test to see that an invalid pointer is caught.
EXPECT_EQ(-1, WebRtcOpus_EncoderFree(NULL)); EXPECT_EQ(-1, WebRtcOpus_EncoderFree(NULL));
EXPECT_EQ(-1, WebRtcOpus_DecoderFree(NULL)); EXPECT_EQ(-1, WebRtcOpus_DecoderFree(NULL));
} }
// Test normal Create and Free. // Test normal Create and Free.
TEST_F(OpusTest, OpusCreateFree) { TEST_P(OpusTest, OpusCreateFree) {
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1)); channels_,
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2)); application_));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2)); EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
EXPECT_TRUE(opus_mono_encoder_ != NULL); EXPECT_TRUE(opus_encoder_ != NULL);
EXPECT_TRUE(opus_mono_decoder_ != NULL); EXPECT_TRUE(opus_decoder_ != NULL);
EXPECT_TRUE(opus_stereo_encoder_ != NULL);
EXPECT_TRUE(opus_stereo_decoder_ != NULL);
// Free encoder and decoder memory. // Free encoder and decoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_)); EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_)); EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
} }
TEST_F(OpusTest, OpusEncodeDecodeMono) { TEST_P(OpusTest, OpusEncodeDecode) {
PrepareSpeechData(1, 20, 20); PrepareSpeechData(channels_, 20, 20);
// Create encoder memory. // Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1)); channels_,
application_));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_,
channels_));
// Set bitrate. // Set bitrate.
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 32000)); EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_,
channels_ == 1 ? 32000 : 64000));
// Check number of channels for decoder. // Check number of channels for decoder.
EXPECT_EQ(1, WebRtcOpus_DecoderChannels(opus_mono_decoder_)); EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
// Check application mode.
opus_int32 app;
opus_encoder_ctl(opus_encoder_->encoder,
OPUS_GET_APPLICATION(&app));
EXPECT_EQ(application_ == 0 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO,
app);
// Encode & decode. // Encode & decode.
int16_t audio_type; int16_t audio_type;
int16_t output_data_decode[kOpus20msFrameSamples]; int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_mono_encoder_, speech_data_.GetNextBlock(), EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
kOpus20msFrameSamples, opus_mono_decoder_, kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type)); output_data_decode, &audio_type));
// Free memory. // Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_)); delete[] output_data_decode;
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_)); EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
} }
TEST_F(OpusTest, OpusEncodeDecodeStereo) { TEST_P(OpusTest, OpusSetBitRate) {
PrepareSpeechData(2, 20, 20);
// Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
// Set bitrate.
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 64000));
// Check number of channels for decoder.
EXPECT_EQ(2, WebRtcOpus_DecoderChannels(opus_stereo_decoder_));
// Encode & decode.
int16_t audio_type;
int16_t output_data_decode[kOpus20msFrameSamples * 2];
EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_stereo_encoder_, speech_data_.GetNextBlock(),
kOpus20msFrameSamples, opus_stereo_decoder_,
output_data_decode, &audio_type));
// Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
}
TEST_F(OpusTest, OpusSetBitRate) {
// Test without creating encoder memory. // Test without creating encoder memory.
EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_mono_encoder_, 60000)); EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 60000));
// Create encoder memory, try with different bitrates. // Create encoder memory, try with different bitrates.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2)); channels_,
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 30000)); application_));
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 60000)); EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000));
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 300000)); EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 600000)); EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000));
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 600000));
// Free memory. // Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_)); EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
} }
TEST_F(OpusTest, OpusSetComplexity) { TEST_P(OpusTest, OpusSetComplexity) {
// Test without creating encoder memory. // Test without creating encoder memory.
EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_mono_encoder_, 9)); EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 9));
EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 9));
// Create encoder memory, try with different complexities. // Create encoder memory, try with different complexities.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2)); channels_,
application_));
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_mono_encoder_, 0)); EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0));
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 0)); EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10));
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_mono_encoder_, 10)); EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 11));
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 10));
EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_mono_encoder_, 11));
EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 11));
// Free memory. // Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_)); EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
} }
// Encode and decode one frame (stereo), initialize the decoder and // Encode and decode one frame, initialize the decoder and
// decode once more. // decode once more.
TEST_F(OpusTest, OpusDecodeInit) { TEST_P(OpusTest, OpusDecodeInit) {
PrepareSpeechData(2, 20, 20); PrepareSpeechData(channels_, 20, 20);
// Create encoder memory. // Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2)); channels_,
application_));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
// Encode & decode. // Encode & decode.
int16_t audio_type; int16_t audio_type;
int16_t output_data_decode[kOpus20msFrameSamples * 2]; int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_stereo_encoder_, speech_data_.GetNextBlock(), EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
kOpus20msFrameSamples, opus_stereo_decoder_, kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type)); output_data_decode, &audio_type));
EXPECT_EQ(0, WebRtcOpus_DecoderInit(opus_stereo_decoder_)); EXPECT_EQ(0, WebRtcOpus_DecoderInit(opus_decoder_));
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
WebRtcOpus_Decode(opus_stereo_decoder_, bitstream_, WebRtcOpus_Decode(opus_decoder_, bitstream_,
encoded_bytes_, output_data_decode, encoded_bytes_, output_data_decode,
&audio_type)); &audio_type));
// Free memory. // Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_)); delete[] output_data_decode;
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_)); EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
} }
TEST_F(OpusTest, OpusEnableDisableFec) { TEST_P(OpusTest, OpusEnableDisableFec) {
// Test without creating encoder memory. // Test without creating encoder memory.
EXPECT_EQ(-1, WebRtcOpus_EnableFec(opus_mono_encoder_)); EXPECT_EQ(-1, WebRtcOpus_EnableFec(opus_encoder_));
EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_stereo_encoder_)); EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_encoder_));
// Create encoder memory, try with different bitrates. // Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2)); channels_,
application_));
EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_mono_encoder_)); EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_stereo_encoder_)); EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_mono_encoder_));
EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_stereo_encoder_));
// Free memory. // Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_)); EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
} }
TEST_F(OpusTest, OpusEnableDisableDtx) { TEST_P(OpusTest, OpusEnableDisableDtx) {
// Test without creating encoder memory. // Test without creating encoder memory.
EXPECT_EQ(-1, WebRtcOpus_EnableDtx(opus_mono_encoder_)); EXPECT_EQ(-1, WebRtcOpus_EnableDtx(opus_encoder_));
EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_stereo_encoder_)); EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_encoder_));
// Create encoder memory, try with different bitrates. // Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2)); channels_,
application_));
opus_int32 dtx; opus_int32 dtx;
// DTX is off by default. // DTX is off by default.
opus_encoder_ctl(opus_mono_encoder_->encoder, opus_encoder_ctl(opus_encoder_->encoder,
OPUS_GET_DTX(&dtx));
EXPECT_EQ(0, dtx);
opus_encoder_ctl(opus_stereo_encoder_->encoder,
OPUS_GET_DTX(&dtx)); OPUS_GET_DTX(&dtx));
EXPECT_EQ(0, dtx); EXPECT_EQ(0, dtx);
// Test to enable DTX. // Test to enable DTX.
EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_mono_encoder_)); EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_encoder_));
opus_encoder_ctl(opus_mono_encoder_->encoder, opus_encoder_ctl(opus_encoder_->encoder,
OPUS_GET_DTX(&dtx));
EXPECT_EQ(1, dtx);
EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_stereo_encoder_));
opus_encoder_ctl(opus_stereo_encoder_->encoder,
OPUS_GET_DTX(&dtx)); OPUS_GET_DTX(&dtx));
EXPECT_EQ(1, dtx); EXPECT_EQ(1, dtx);
// Test to disable DTX. // Test to disable DTX.
EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_mono_encoder_)); EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_encoder_));
opus_encoder_ctl(opus_mono_encoder_->encoder, opus_encoder_ctl(opus_encoder_->encoder,
OPUS_GET_DTX(&dtx)); OPUS_GET_DTX(&dtx));
EXPECT_EQ(0, dtx); EXPECT_EQ(0, dtx);
EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_stereo_encoder_));
opus_encoder_ctl(opus_stereo_encoder_->encoder,
OPUS_GET_DTX(&dtx));
EXPECT_EQ(0, dtx);
// Free memory. // Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_)); EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
} }
TEST_F(OpusTest, OpusDtxOff) { TEST_P(OpusTest, OpusDtxOff) {
TestDtxEffect(false); TestDtxEffect(false);
} }
TEST_F(OpusTest, OpusDtxOn) { TEST_P(OpusTest, OpusDtxOn) {
if (application_ == 1) {
// We do not check DTX under OPUS_APPLICATION_AUDIO mode.
return;
}
TestDtxEffect(true); TestDtxEffect(true);
} }
TEST_F(OpusTest, OpusSetPacketLossRate) { TEST_P(OpusTest, OpusSetPacketLossRate) {
// Test without creating encoder memory. // Test without creating encoder memory.
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_mono_encoder_, 50)); EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_stereo_encoder_, 50));
// 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));
EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_mono_encoder_, 50));
EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_stereo_encoder_, 50));
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_mono_encoder_, -1));
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_stereo_encoder_, -1));
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_mono_encoder_, 101));
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_stereo_encoder_, 101));
// Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
}
TEST_F(OpusTest, OpusSetMaxPlaybackRate) {
// Test without creating encoder memory.
EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_mono_encoder_, 20000));
EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(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));
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_FULLBAND, 48000);
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_FULLBAND, 24001);
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_SUPERWIDEBAND, 24000);
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_SUPERWIDEBAND, 16001);
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_WIDEBAND, 16000);
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_WIDEBAND, 12001);
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_MEDIUMBAND, 12000);
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_MEDIUMBAND, 8001);
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_NARROWBAND, 8000);
TestSetMaxPlaybackRate(OPUS_BANDWIDTH_NARROWBAND, 4000);
// 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) {
PrepareSpeechData(1, 20, 20);
// Create encoder memory. // Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1)); channels_,
application_));
EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, -1));
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 101));
// Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
}
TEST_P(OpusTest, OpusSetMaxPlaybackRate) {
// Test without creating encoder memory.
EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, 20000));
// Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
channels_,
application_));
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 48000);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 24001);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 24000);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 16001);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 16000);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 12001);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 12000);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 8001);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 8000);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 4000);
// Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
}
// Test PLC.
TEST_P(OpusTest, OpusDecodePlc) {
PrepareSpeechData(channels_, 20, 20);
// Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
channels_,
application_));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
// Set bitrate. // Set bitrate.
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 32000)); EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_,
channels_== 1 ? 32000 : 64000));
// Check number of channels for decoder. // Check number of channels for decoder.
EXPECT_EQ(1, WebRtcOpus_DecoderChannels(opus_mono_decoder_)); EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
// Encode & decode. // Encode & decode.
int16_t audio_type; int16_t audio_type;
int16_t output_data_decode[kOpus20msFrameSamples]; int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_mono_encoder_, speech_data_.GetNextBlock(), EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
kOpus20msFrameSamples, opus_mono_decoder_, kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type)); output_data_decode, &audio_type));
// Call decoder PLC. // Call decoder PLC.
int16_t plc_buffer[kOpus20msFrameSamples]; int16_t* plc_buffer = new int16_t[kOpus20msFrameSamples * channels_];
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
WebRtcOpus_DecodePlc(opus_mono_decoder_, plc_buffer, 1)); WebRtcOpus_DecodePlc(opus_decoder_, plc_buffer, 1));
// Free memory. // Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_)); delete[] plc_buffer;
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_)); delete[] output_data_decode;
} EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
// PLC in stereo mode.
TEST_F(OpusTest, OpusDecodePlcStereo) {
PrepareSpeechData(2, 20, 20);
// Create encoder memory.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
// Set bitrate.
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 64000));
// Check number of channels for decoder.
EXPECT_EQ(2, WebRtcOpus_DecoderChannels(opus_stereo_decoder_));
// Encode & decode.
int16_t audio_type;
int16_t output_data_decode[kOpus20msFrameSamples * 2];
EXPECT_EQ(kOpus20msFrameSamples,
EncodeDecode(opus_stereo_encoder_, speech_data_.GetNextBlock(),
kOpus20msFrameSamples, opus_stereo_decoder_,
output_data_decode, &audio_type));
// Call decoder PLC.
int16_t plc_buffer[kOpus20msFrameSamples * 2];
EXPECT_EQ(kOpus20msFrameSamples,
WebRtcOpus_DecodePlc(opus_stereo_decoder_, plc_buffer, 1));
// Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
} }
// Duration estimation. // Duration estimation.
TEST_F(OpusTest, OpusDurationEstimation) { TEST_P(OpusTest, OpusDurationEstimation) {
PrepareSpeechData(2, 20, 20); PrepareSpeechData(channels_, 20, 20);
// Create. // Create.
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2)); EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2)); channels_,
application_));
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
// 10 ms. We use only first 10 ms of a 20 ms block. // 10 ms. We use only first 10 ms of a 20 ms block.
encoded_bytes_ = WebRtcOpus_Encode(opus_stereo_encoder_, encoded_bytes_ = WebRtcOpus_Encode(opus_encoder_,
speech_data_.GetNextBlock(), speech_data_.GetNextBlock(),
kOpus10msFrameSamples, kMaxBytes, kOpus10msFrameSamples, kMaxBytes,
bitstream_); bitstream_);
EXPECT_EQ(kOpus10msFrameSamples, EXPECT_EQ(kOpus10msFrameSamples,
WebRtcOpus_DurationEst(opus_stereo_decoder_, bitstream_, WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
encoded_bytes_)); encoded_bytes_));
// 20 ms // 20 ms
encoded_bytes_ = WebRtcOpus_Encode(opus_stereo_encoder_, encoded_bytes_ = WebRtcOpus_Encode(opus_encoder_,
speech_data_.GetNextBlock(), speech_data_.GetNextBlock(),
kOpus20msFrameSamples, kMaxBytes, kOpus20msFrameSamples, kMaxBytes,
bitstream_); bitstream_);
EXPECT_EQ(kOpus20msFrameSamples, EXPECT_EQ(kOpus20msFrameSamples,
WebRtcOpus_DurationEst(opus_stereo_decoder_, bitstream_, WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
encoded_bytes_)); encoded_bytes_));
// Free memory. // Free memory.
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_)); EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_)); EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
} }
INSTANTIATE_TEST_CASE_P(VariousMode,
OpusTest,
Combine(Values(1, 2), Values(0, 1)));
} // namespace webrtc } // namespace webrtc

View File

@ -999,6 +999,12 @@ int16_t ACMGenericCodec::REDPayloadISAC(const int32_t /* isac_rate */,
return -1; return -1;
} }
int ACMGenericCodec::SetOpusApplication(OpusApplicationMode /*application*/) {
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
"The send-codec is not Opus, failed to set application.");
return -1;
}
int ACMGenericCodec::SetOpusMaxPlaybackRate(int /* frequency_hz */) { int ACMGenericCodec::SetOpusMaxPlaybackRate(int /* frequency_hz */) {
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_, WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
"The send-codec is not Opus, failed to set maximum playback rate."); "The send-codec is not Opus, failed to set maximum playback rate.");

View File

@ -525,6 +525,20 @@ class ACMGenericCodec {
uint8_t* payload, uint8_t* payload,
int16_t* payload_len_bytes); int16_t* payload_len_bytes);
///////////////////////////////////////////////////////////////////////////
// int SetOpusApplication()
// Sets the intended application for the Opus encoder. Opus uses this to
// optimize the encoding for applications like VOIP and music.
//
// Input:
// - application : intended application.
//
// Return value:
// -1 if failed or on codecs other than Opus.
// 0 if succeeded.
//
virtual int SetOpusApplication(OpusApplicationMode /*application*/);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// int SetOpusMaxPlaybackRate() // int SetOpusMaxPlaybackRate()
// Sets maximum playback rate the receiver will render, if the codec is Opus. // Sets maximum playback rate the receiver will render, if the codec is Opus.
@ -636,8 +650,8 @@ class ACMGenericCodec {
// See InitEncoder() for the description of function, input(s)/output(s) // See InitEncoder() for the description of function, input(s)/output(s)
// and return value. // and return value.
// //
int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params, virtual int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
bool force_initialization) bool force_initialization)
EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

View File

@ -68,7 +68,8 @@ ACMOpus::ACMOpus(int16_t codec_id)
sample_freq_(32000), // Default sampling frequency. sample_freq_(32000), // Default sampling frequency.
bitrate_(20000), // Default bit-rate. bitrate_(20000), // Default bit-rate.
channels_(1), // Default mono. channels_(1), // Default mono.
packet_loss_rate_(0) { // Initial packet loss rate. packet_loss_rate_(0), // Initial packet loss rate.
application_(kVoip) { // Initial application mode.
codec_id_ = codec_id; codec_id_ = codec_id;
// Opus has internal DTX, but we dont use it for now. // Opus has internal DTX, but we dont use it for now.
has_internal_dtx_ = false; has_internal_dtx_ = false;
@ -113,6 +114,16 @@ int16_t ACMOpus::InternalEncode(uint8_t* bitstream,
return *bitstream_len_byte; return *bitstream_len_byte;
} }
int16_t ACMOpus::InitEncoderSafe(WebRtcACMCodecParams* codec_params,
bool force_initialization) {
// Determine target application if codec is not initialized or a forced
// initialization is requested.
if (!encoder_initialized_ || force_initialization) {
application_ = (codec_params->codec_inst.channels == 1) ? kVoip : kAudio;
}
return ACMGenericCodec::InitEncoderSafe(codec_params, force_initialization);
}
int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codec_params) { int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
int16_t ret; int16_t ret;
if (encoder_inst_ptr_ != NULL) { if (encoder_inst_ptr_ != NULL) {
@ -120,7 +131,8 @@ int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
encoder_inst_ptr_ = NULL; encoder_inst_ptr_ = NULL;
} }
ret = WebRtcOpus_EncoderCreate(&encoder_inst_ptr_, ret = WebRtcOpus_EncoderCreate(&encoder_inst_ptr_,
codec_params->codec_inst.channels); codec_params->codec_inst.channels,
application_);
// Store number of channels. // Store number of channels.
channels_ = codec_params->codec_inst.channels; channels_ = codec_params->codec_inst.channels;
@ -251,6 +263,13 @@ int ACMOpus::SetOpusMaxPlaybackRate(int frequency_hz) {
return WebRtcOpus_SetMaxPlaybackRate(encoder_inst_ptr_, frequency_hz); return WebRtcOpus_SetMaxPlaybackRate(encoder_inst_ptr_, frequency_hz);
} }
int ACMOpus::SetOpusApplication(OpusApplicationMode application) {
WriteLockScoped lockCodec(codec_wrapper_lock_);
application_ = application;
// Set Opus application invokes a reset of the encoder.
return InternalResetEncoder();
}
#endif // WEBRTC_CODEC_OPUS #endif // WEBRTC_CODEC_OPUS
} // namespace acm2 } // namespace acm2

View File

@ -29,23 +29,29 @@ class ACMOpus : public ACMGenericCodec {
ACMGenericCodec* CreateInstance(void); ACMGenericCodec* CreateInstance(void);
int16_t InternalEncode(uint8_t* bitstream, int16_t InternalEncode(uint8_t* bitstream,
int16_t* bitstream_len_byte) OVERRIDE int16_t* bitstream_len_byte) override
EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
bool force_initialization) override
EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
int16_t InternalInitEncoder(WebRtcACMCodecParams *codec_params); int16_t InternalInitEncoder(WebRtcACMCodecParams *codec_params);
virtual int SetFEC(bool enable_fec) OVERRIDE; int SetFEC(bool enable_fec) override;
virtual int SetPacketLossRate(int loss_rate) OVERRIDE; int SetOpusApplication(OpusApplicationMode mode) override;
virtual int SetOpusMaxPlaybackRate(int frequency_hz) OVERRIDE; int SetPacketLossRate(int loss_rate) override;
int SetOpusMaxPlaybackRate(int frequency_hz) override;
protected: protected:
void DestructEncoderSafe(); void DestructEncoderSafe();
int16_t InternalCreateEncoder(); int16_t InternalCreateEncoder();
int16_t SetBitRateSafe(const int32_t rate) OVERRIDE int16_t SetBitRateSafe(const int32_t rate) override
EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
WebRtcOpusEncInst* encoder_inst_ptr_; WebRtcOpusEncInst* encoder_inst_ptr_;
@ -54,6 +60,8 @@ class ACMOpus : public ACMGenericCodec {
int channels_; int channels_;
int packet_loss_rate_; int packet_loss_rate_;
OpusApplicationMode application_;
}; };
} // namespace acm2 } // namespace acm2

View File

@ -35,6 +35,11 @@ class AcmOpusTest : public ACMOpus {
: ACMOpus(codec_id) {} : ACMOpus(codec_id) {}
~AcmOpusTest() {} ~AcmOpusTest() {}
int packet_loss_rate() { return packet_loss_rate_; } int packet_loss_rate() { return packet_loss_rate_; }
OpusApplicationMode application() { return application_; }
bool encoder_initialized() {
ReadLockScoped cs(codec_wrapper_lock_);
return encoder_initialized_;
}
void TestSetPacketLossRate(int from, int to, int expected_return); void TestSetPacketLossRate(int from, int to, int expected_return);
}; };
@ -82,6 +87,54 @@ TEST(AcmOpusTest, PacketLossRateOptimized) {
kPacketLossRate1); kPacketLossRate1);
opus.TestSetPacketLossRate(0, 0, 0); opus.TestSetPacketLossRate(0, 0, 0);
} }
TEST(AcmOpusTest, DefaultApplicationMode) {
AcmOpusTest opus(ACMCodecDB::kOpus);
WebRtcACMCodecParams params;
memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst));
params.codec_inst.channels = 2;
// Codec is not initialized, and hence without force initialization (2nd
// argument being false), an initialization will take place.
EXPECT_FALSE(opus.encoder_initialized());
EXPECT_EQ(0, opus.InitEncoder(&params, false));
EXPECT_EQ(kAudio, opus.application());
params.codec_inst.channels = 1;
EXPECT_EQ(0, opus.InitEncoder(&params, true));
EXPECT_EQ(kVoip, opus.application());
}
TEST(AcmOpusTest, ChangeApplicationMode) {
AcmOpusTest opus(ACMCodecDB::kOpus);
WebRtcACMCodecParams params;
memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst));
params.codec_inst.channels = 2;
// Codec is not initialized, and hence without force initialization (2nd
// argument being false), an initialization will take place.
EXPECT_EQ(0, opus.InitEncoder(&params, false));
EXPECT_EQ(kAudio, opus.application());
opus.SetOpusApplication(kVoip);
EXPECT_EQ(kVoip, opus.application());
}
TEST(AcmOpusTest, ResetWontChangeApplicationMode) {
AcmOpusTest opus(ACMCodecDB::kOpus);
WebRtcACMCodecParams params;
memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst));
params.codec_inst.channels = 2;
// Codec is not initialized, and hence without force initialization (2nd
// argument being false), an initialization will take place.
EXPECT_EQ(0, opus.InitEncoder(&params, false));
EXPECT_EQ(kAudio, opus.application());
opus.ResetEncoder();
EXPECT_EQ(kAudio, opus.application());
}
#else #else
void AcmOpusTest:TestSetPacketLossRate(int /* from */, int /* to */, void AcmOpusTest:TestSetPacketLossRate(int /* from */, int /* to */,
int /* expected_return */) { int /* expected_return */) {

View File

@ -54,6 +54,8 @@ class AcmSendTestOldApi : public AudioPacketizationCallback,
size_t payload_len_bytes, size_t payload_len_bytes,
const RTPFragmentationHeader* fragmentation) OVERRIDE; const RTPFragmentationHeader* fragmentation) OVERRIDE;
AudioCodingModule* acm() { return acm_.get(); }
private: private:
static const int kBlockSizeMs = 10; static const int kBlockSizeMs = 10;

View File

@ -1544,6 +1544,14 @@ int AudioCodingModuleImpl::ConfigISACBandwidthEstimator(
frame_size_ms, rate_bit_per_sec, enforce_frame_size); frame_size_ms, rate_bit_per_sec, enforce_frame_size);
} }
int AudioCodingModuleImpl::SetOpusApplication(OpusApplicationMode application) {
CriticalSectionScoped lock(acm_crit_sect_);
if (!HaveValidEncoder("SetOpusApplication")) {
return -1;
}
return codecs_[current_send_codec_idx_]->SetOpusApplication(application);
}
// Informs Opus encoder of the maximum playback rate the receiver will render. // Informs Opus encoder of the maximum playback rate the receiver will render.
int AudioCodingModuleImpl::SetOpusMaxPlaybackRate(int frequency_hz) { int AudioCodingModuleImpl::SetOpusMaxPlaybackRate(int frequency_hz) {
CriticalSectionScoped lock(acm_crit_sect_); CriticalSectionScoped lock(acm_crit_sect_);

View File

@ -224,6 +224,8 @@ class AudioCodingModuleImpl : public AudioCodingModule {
int rate_bit_per_sec, int rate_bit_per_sec,
bool enforce_frame_size = false) OVERRIDE; bool enforce_frame_size = false) OVERRIDE;
int SetOpusApplication(OpusApplicationMode application) override;
// If current send codec is Opus, informs it about the maximum playback rate // If current send codec is Opus, informs it about the maximum playback rate
// the receiver will render. // the receiver will render.
virtual int SetOpusMaxPlaybackRate(int frequency_hz) OVERRIDE; virtual int SetOpusMaxPlaybackRate(int frequency_hz) OVERRIDE;

View File

@ -977,6 +977,22 @@ TEST_F(AcmSenderBitExactnessOldApi, MAYBE_Opus_stereo_20ms) {
test::AcmReceiveTestOldApi::kStereoOutput); test::AcmReceiveTestOldApi::kStereoOutput);
} }
TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms_voip) {
ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960));
// If not set, default will be kAudio in case of stereo.
send_test_->acm()->SetOpusApplication(kVoip);
Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
"9b9e12bc3cc793740966e11cbfa8b35b",
"57412a4b5771d19ff03ec35deffe7067",
"9b9e12bc3cc793740966e11cbfa8b35b"),
AcmReceiverBitExactnessOldApi::PlatformChecksum(
"c7340b1189652ab6b5e80dade7390cb4",
"cdfe85939c411d12b61701c566e22d26",
"c7340b1189652ab6b5e80dade7390cb4"),
50,
test::AcmReceiveTestOldApi::kStereoOutput);
}
// This test fixture is implemented to run ACM and change the desired output // This test fixture is implemented to run ACM and change the desired output
// frequency during the call. The input packets are simply PCM16b-wb encoded // frequency during the call. The input packets are simply PCM16b-wb encoded
// payloads with a constant value of |kSampleValue|. The test fixture itself // payloads with a constant value of |kSampleValue|. The test fixture itself

View File

@ -874,6 +874,20 @@ class AudioCodingModule: public Module {
int init_rate_bps, int init_rate_bps,
bool enforce_frame_size = false) = 0; bool enforce_frame_size = false) = 0;
///////////////////////////////////////////////////////////////////////////
// int SetOpusApplication()
// Sets the intended application for the Opus encoder. Opus uses this to
// optimize the encoding for applications like VOIP and music.
//
// Input:
// - application : intended application.
//
// Return value:
// -1 if failed or on codecs other than Opus.
// 0 if succeeded.
//
virtual int SetOpusApplication(OpusApplicationMode /*application*/) = 0;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// int SetOpusMaxPlaybackRate() // int SetOpusMaxPlaybackRate()
// If current send codec is Opus, informs it about maximum playback rate the // If current send codec is Opus, informs it about maximum playback rate the

View File

@ -200,6 +200,18 @@ enum ACMBackgroundNoiseMode {
Off Off
}; };
///////////////////////////////////////////////////////////////////////////
//
// Enumeration of Opus mode for intended application.
//
// kVoip : optimized for voice signals.
// kAudio : optimized for non-voice signals like music.
//
enum OpusApplicationMode {
kVoip = 0,
kAudio = 1,
};
} // namespace webrtc } // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_INTERFACE_AUDIO_CODING_MODULE_TYPEDEFS_H_ #endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_INTERFACE_AUDIO_CODING_MODULE_TYPEDEFS_H_

View File

@ -79,8 +79,8 @@ void OpusTest::Perform() {
in_file_mono_.ReadStereo(false); in_file_mono_.ReadStereo(false);
// Create Opus encoders for mono and stereo. // Create Opus encoders for mono and stereo.
ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1), -1); ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1, 0), -1);
ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2), -1); ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2, 1), -1);
// Create Opus decoders for mono and stereo for stand-alone testing of Opus. // Create Opus decoders for mono and stereo for stand-alone testing of Opus.
ASSERT_GT(WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1), -1); ASSERT_GT(WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1), -1);

View File

@ -447,6 +447,7 @@ class AudioDecoderOpusTest : public AudioDecoderTest {
AudioEncoderOpus::Config config; AudioEncoderOpus::Config config;
config.frame_size_ms = static_cast<int>(frame_size_) / 48; config.frame_size_ms = static_cast<int>(frame_size_) / 48;
config.payload_type = payload_type_; config.payload_type = payload_type_;
config.application = AudioEncoderOpus::kVoip;
audio_encoder_.reset(new AudioEncoderOpus(config)); audio_encoder_.reset(new AudioEncoderOpus(config));
} }
}; };
@ -461,6 +462,7 @@ class AudioDecoderOpusStereoTest : public AudioDecoderOpusTest {
config.frame_size_ms = static_cast<int>(frame_size_) / 48; config.frame_size_ms = static_cast<int>(frame_size_) / 48;
config.num_channels = 2; config.num_channels = 2;
config.payload_type = payload_type_; config.payload_type = payload_type_;
config.application = AudioEncoderOpus::kAudio;
audio_encoder_.reset(new AudioEncoderOpus(config)); audio_encoder_.reset(new AudioEncoderOpus(config));
} }
}; };

View File

@ -145,8 +145,10 @@ NetEqOpusFecQualityTest::NetEqOpusFecQualityTest()
} }
void NetEqOpusFecQualityTest::SetUp() { void NetEqOpusFecQualityTest::SetUp() {
// If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
int app = channels_ == 1 ? 0 : 1;
// Create encoder memory. // Create encoder memory.
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_); WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app);
ASSERT_TRUE(opus_encoder_ != NULL); ASSERT_TRUE(opus_encoder_ != NULL);
// Set bitrate. // Set bitrate.
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_kbps_ * 1000)); EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_kbps_ * 1000));