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
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 1cfc302..358647f 100644
--- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -37,7 +37,10 @@
} // namespace
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 {
@@ -52,10 +55,11 @@
: num_10ms_frames_per_packet_(DivExact(config.frame_size_ms, 10)),
num_channels_(config.num_channels),
payload_type_(config.payload_type),
+ application_(config.application),
samples_per_10ms_frame_(DivExact(kSampleRateHz, 100) * num_channels_) {
CHECK(config.IsOk());
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() {
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 f44627d..e9d0fb8 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
@@ -20,12 +20,18 @@
class AudioEncoderOpus : public AudioEncoder {
public:
+ enum ApplicationMode {
+ kVoip = 0,
+ kAudio = 1,
+ };
+
struct Config {
Config();
bool IsOk() const;
int frame_size_ms;
int num_channels;
int payload_type;
+ ApplicationMode application;
};
explicit AudioEncoderOpus(const Config& config);
@@ -47,6 +53,7 @@
const int num_10ms_frames_per_packet_;
const int num_channels_;
const int payload_type_;
+ const ApplicationMode application_;
const int samples_per_10ms_frame_;
std::vector<int16_t> input_buffer_;
OpusEncInst* inst_;
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 d788af7..27009a8 100644
--- a/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h
+++ b/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h
@@ -21,7 +21,29 @@
typedef struct WebRtcOpusEncInst OpusEncInst;
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);
/****************************************************************************
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc b/webrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc
index 35f3972..b91aa45 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc
@@ -103,8 +103,11 @@
out_data_.reset(new int16_t[2 * block_length_sample_ * channels_]);
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.
- 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_));
// Set bitrate.
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
index 1b99864..955fb00 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
@@ -31,17 +31,31 @@
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;
if (inst != NULL) {
state = (OpusEncInst*) calloc(1, sizeof(OpusEncInst));
if (state) {
- int error;
- /* Default to VoIP application for mono, and AUDIO for stereo. */
- int application = (channels == 1) ? OPUS_APPLICATION_VOIP :
- OPUS_APPLICATION_AUDIO;
+ int opus_app;
+ switch (application) {
+ case 0: {
+ 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);
state->in_dtx_mode = 0;
if (error == OPUS_OK && state->encoder != NULL) {
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc b/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
index e7811e3..ebe4a35 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
@@ -41,8 +41,10 @@
void OpusSpeedTest::SetUp() {
AudioCodecSpeedTest::SetUp();
+ // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
+ int app = channels_ == 1 ? 0 : 1;
/* 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_));
/* Set bitrate. */
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc b/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
index 5439df4..e93cd7c 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
@@ -18,6 +18,9 @@
namespace webrtc {
using test::AudioLoop;
+using ::testing::TestWithParam;
+using ::testing::Values;
+using ::testing::Combine;
// Maximum number of bytes in output bitstream.
const size_t kMaxBytes = 1000;
@@ -28,11 +31,10 @@
// Number of samples-per-channel in a 10 ms frame, sampled at 48 kHz.
const int kOpus10msFrameSamples = kOpusRateKhz * 10;
-class OpusTest : public ::testing::Test {
+class OpusTest : public TestWithParam<::testing::tuple<int, int>> {
protected:
OpusTest();
- void TestSetMaxPlaybackRate(opus_int32 expect, int32_t set);
void TestDtxEffect(bool dtx);
// Prepare |speech_data_| for encoding, read from a hard-coded file.
@@ -48,27 +50,33 @@
int16_t* output_audio,
int16_t* audio_type);
- WebRtcOpusEncInst* opus_mono_encoder_;
- WebRtcOpusEncInst* opus_stereo_encoder_;
- WebRtcOpusDecInst* opus_mono_decoder_;
- WebRtcOpusDecInst* opus_stereo_decoder_;
+ void SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
+ opus_int32 expect, int32_t set);
+
+ WebRtcOpusEncInst* opus_encoder_;
+ WebRtcOpusDecInst* opus_decoder_;
AudioLoop speech_data_;
uint8_t bitstream_[kMaxBytes];
int encoded_bytes_;
+ int channels_;
+ int application_;
};
OpusTest::OpusTest()
- : opus_mono_encoder_(NULL),
- opus_stereo_encoder_(NULL),
- opus_mono_decoder_(NULL),
- opus_stereo_decoder_(NULL) {
+ : opus_encoder_(NULL),
+ opus_decoder_(NULL),
+ encoded_bytes_(0),
+ channels_(::testing::get<0>(GetParam())),
+ application_(::testing::get<1>(GetParam())) {
}
void OpusTest::PrepareSpeechData(int channel, int block_length_ms,
int loop_length_ms) {
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) {
loop_length_ms = block_length_ms;
}
@@ -77,16 +85,12 @@
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;
- // Test mono encoder.
- EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(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_SetMaxPlaybackRate(opus_stereo_encoder_, set));
- opus_encoder_ctl(opus_stereo_encoder_->encoder,
+ EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, set));
+ opus_encoder_ctl(opus_encoder_->encoder,
OPUS_GET_MAX_BANDWIDTH(&bandwidth));
EXPECT_EQ(expect, bandwidth);
}
@@ -109,105 +113,109 @@
// Test if encoder/decoder can enter DTX mode properly and do not enter DTX when
// they should not. This test is signal dependent.
void OpusTest::TestDtxEffect(bool dtx) {
- PrepareSpeechData(1, 20, 2000);
+ PrepareSpeechData(channels_, 20, 2000);
// Create encoder memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1));
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ channels_,
+ application_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
// 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.
- int16_t silence[kOpus20msFrameSamples] = {0};
+ int16_t* silence = new int16_t[kOpus20msFrameSamples * channels_];
+ memset(silence, 0, sizeof(int16_t) * kOpus20msFrameSamples * channels_);
// Setting DTX.
- EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_mono_encoder_) :
- WebRtcOpus_DisableDtx(opus_mono_encoder_));
+ EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_encoder_) :
+ WebRtcOpus_DisableDtx(opus_encoder_));
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) {
EXPECT_EQ(kOpus20msFrameSamples,
- EncodeDecode(opus_mono_encoder_, speech_data_.GetNextBlock(),
- kOpus20msFrameSamples, opus_mono_decoder_,
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+ kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type));
// 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.
if (!dtx) {
EXPECT_GT(encoded_bytes_, 1);
- EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
- EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech.
}
}
// We input some silent segments. In DTX mode, the encoder will stop sending.
// However, DTX may happen after a while.
- for (int i = 0; i < 22; ++i) {
+ for (int i = 0; i < 30; ++i) {
EXPECT_EQ(kOpus20msFrameSamples,
- EncodeDecode(opus_mono_encoder_, silence,
- kOpus20msFrameSamples, opus_mono_decoder_,
+ EncodeDecode(opus_encoder_, silence,
+ kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type));
if (!dtx) {
EXPECT_GT(encoded_bytes_, 1);
- EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
- EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech.
} else if (1 == encoded_bytes_) {
- EXPECT_EQ(1, opus_mono_encoder_->in_dtx_mode);
- EXPECT_EQ(1, opus_mono_decoder_->in_dtx_mode);
+ EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
EXPECT_EQ(2, audio_type); // Comfort noise.
break;
}
}
// DTX mode is maintained 400 ms.
- for (int i = 0; i < 20; ++i) {
+ for (int i = 0; i < 19; ++i) {
EXPECT_EQ(kOpus20msFrameSamples,
- EncodeDecode(opus_mono_encoder_, silence,
- kOpus20msFrameSamples, opus_mono_decoder_,
+ EncodeDecode(opus_encoder_, silence,
+ kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type));
if (dtx) {
EXPECT_EQ(0, encoded_bytes_) // Send 0 byte.
<< "Opus should have entered DTX mode.";
- EXPECT_EQ(1, opus_mono_encoder_->in_dtx_mode);
- EXPECT_EQ(1, opus_mono_decoder_->in_dtx_mode);
+ EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
EXPECT_EQ(2, audio_type); // Comfort noise.
} else {
EXPECT_GT(encoded_bytes_, 1);
- EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
- EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech.
}
}
// Quit DTX after 400 ms
EXPECT_EQ(kOpus20msFrameSamples,
- EncodeDecode(opus_mono_encoder_, silence,
- kOpus20msFrameSamples, opus_mono_decoder_,
+ EncodeDecode(opus_encoder_, silence,
+ kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type));
EXPECT_GT(encoded_bytes_, 1);
- EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
- EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech.
// Enters DTX again immediately.
EXPECT_EQ(kOpus20msFrameSamples,
- EncodeDecode(opus_mono_encoder_, silence,
- kOpus20msFrameSamples, opus_mono_decoder_,
+ EncodeDecode(opus_encoder_, silence,
+ kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type));
if (dtx) {
EXPECT_EQ(1, encoded_bytes_); // Send 1 byte.
- EXPECT_EQ(1, opus_mono_encoder_->in_dtx_mode);
- EXPECT_EQ(1, opus_mono_decoder_->in_dtx_mode);
+ EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
EXPECT_EQ(2, audio_type); // Comfort noise.
} else {
EXPECT_GT(encoded_bytes_, 1);
- EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
- EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech.
}
@@ -215,386 +223,340 @@
if (dtx) {
// Verify that encoder/decoder can jump out from DTX mode.
EXPECT_EQ(kOpus20msFrameSamples,
- EncodeDecode(opus_mono_encoder_, silence,
- kOpus20msFrameSamples, opus_mono_decoder_,
+ EncodeDecode(opus_encoder_, silence,
+ kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type));
EXPECT_GT(encoded_bytes_, 1);
- EXPECT_EQ(0, opus_mono_encoder_->in_dtx_mode);
- EXPECT_EQ(0, opus_mono_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
EXPECT_EQ(0, audio_type); // Speech.
}
// Free memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
- EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_));
+ delete[] output_data_decode;
+ delete[] silence;
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
}
// 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.
- EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1));
- EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 3));
+ EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1, 0));
+ // 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(&opus_mono_decoder_, 3));
+ // Invalid channel number.
+ EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 3));
}
// Test failing Free.
-TEST_F(OpusTest, OpusFreeFail) {
+TEST(OpusTest, OpusFreeFail) {
// Test to see that an invalid pointer is caught.
EXPECT_EQ(-1, WebRtcOpus_EncoderFree(NULL));
EXPECT_EQ(-1, WebRtcOpus_DecoderFree(NULL));
}
// Test normal Create and Free.
-TEST_F(OpusTest, OpusCreateFree) {
- EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1));
- EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
- EXPECT_TRUE(opus_mono_encoder_ != NULL);
- EXPECT_TRUE(opus_mono_decoder_ != NULL);
- EXPECT_TRUE(opus_stereo_encoder_ != NULL);
- EXPECT_TRUE(opus_stereo_decoder_ != NULL);
+TEST_P(OpusTest, OpusCreateFree) {
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ channels_,
+ application_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ EXPECT_TRUE(opus_encoder_ != NULL);
+ EXPECT_TRUE(opus_decoder_ != NULL);
// Free encoder and decoder memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
- EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_decoder_));
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
- 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, OpusEncodeDecodeMono) {
- PrepareSpeechData(1, 20, 20);
+TEST_P(OpusTest, OpusEncodeDecode) {
+ PrepareSpeechData(channels_, 20, 20);
// Create encoder memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1));
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ channels_,
+ application_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_,
+ channels_));
// 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.
- 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.
int16_t audio_type;
- int16_t output_data_decode[kOpus20msFrameSamples];
+ int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
EXPECT_EQ(kOpus20msFrameSamples,
- EncodeDecode(opus_mono_encoder_, speech_data_.GetNextBlock(),
- kOpus20msFrameSamples, opus_mono_decoder_,
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+ kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type));
// Free memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
- 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_));
}
-TEST_F(OpusTest, OpusEncodeDecodeStereo) {
- 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_P(OpusTest, OpusSetBitRate) {
// Test without creating encoder memory.
- EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_mono_encoder_, 60000));
- EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 60000));
+ EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
// 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_SetBitRate(opus_mono_encoder_, 30000));
- EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 60000));
- EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_mono_encoder_, 300000));
- EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_stereo_encoder_, 600000));
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ channels_,
+ application_));
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000));
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000));
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 600000));
// Free memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
}
-TEST_F(OpusTest, OpusSetComplexity) {
+TEST_P(OpusTest, OpusSetComplexity) {
// Test without creating encoder memory.
- EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_mono_encoder_, 9));
- EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 9));
+ EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 9));
// Create encoder memory, try with different complexities.
- EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
- EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ channels_,
+ application_));
- EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_mono_encoder_, 0));
- EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 0));
- EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_mono_encoder_, 10));
- 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));
+ EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0));
+ EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10));
+ EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 11));
// Free memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
}
-// Encode and decode one frame (stereo), initialize the decoder and
+// Encode and decode one frame, initialize the decoder and
// decode once more.
-TEST_F(OpusTest, OpusDecodeInit) {
- PrepareSpeechData(2, 20, 20);
+TEST_P(OpusTest, OpusDecodeInit) {
+ PrepareSpeechData(channels_, 20, 20);
// Create encoder memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ channels_,
+ application_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
// Encode & decode.
int16_t audio_type;
- int16_t output_data_decode[kOpus20msFrameSamples * 2];
+ int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
EXPECT_EQ(kOpus20msFrameSamples,
- EncodeDecode(opus_stereo_encoder_, speech_data_.GetNextBlock(),
- kOpus20msFrameSamples, opus_stereo_decoder_,
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+ kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type));
- EXPECT_EQ(0, WebRtcOpus_DecoderInit(opus_stereo_decoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderInit(opus_decoder_));
EXPECT_EQ(kOpus20msFrameSamples,
- WebRtcOpus_Decode(opus_stereo_decoder_, bitstream_,
+ WebRtcOpus_Decode(opus_decoder_, bitstream_,
encoded_bytes_, output_data_decode,
&audio_type));
// Free memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
- EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
+ delete[] output_data_decode;
+ 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.
- EXPECT_EQ(-1, WebRtcOpus_EnableFec(opus_mono_encoder_));
- EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_stereo_encoder_));
+ EXPECT_EQ(-1, WebRtcOpus_EnableFec(opus_encoder_));
+ EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_encoder_));
- // 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));
+ // Create encoder memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ channels_,
+ application_));
- EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_mono_encoder_));
- EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_stereo_encoder_));
- EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_mono_encoder_));
- EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_stereo_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
// Free memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
}
-TEST_F(OpusTest, OpusEnableDisableDtx) {
+TEST_P(OpusTest, OpusEnableDisableDtx) {
// Test without creating encoder memory.
- EXPECT_EQ(-1, WebRtcOpus_EnableDtx(opus_mono_encoder_));
- EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_stereo_encoder_));
+ EXPECT_EQ(-1, WebRtcOpus_EnableDtx(opus_encoder_));
+ EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_encoder_));
- // 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));
+ // Create encoder memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ channels_,
+ application_));
opus_int32 dtx;
// DTX is off by default.
- opus_encoder_ctl(opus_mono_encoder_->encoder,
- OPUS_GET_DTX(&dtx));
- EXPECT_EQ(0, dtx);
-
- opus_encoder_ctl(opus_stereo_encoder_->encoder,
+ opus_encoder_ctl(opus_encoder_->encoder,
OPUS_GET_DTX(&dtx));
EXPECT_EQ(0, dtx);
// Test to enable DTX.
- EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_mono_encoder_));
- opus_encoder_ctl(opus_mono_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,
+ EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_encoder_));
+ opus_encoder_ctl(opus_encoder_->encoder,
OPUS_GET_DTX(&dtx));
EXPECT_EQ(1, dtx);
// Test to disable DTX.
- EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_mono_encoder_));
- opus_encoder_ctl(opus_mono_encoder_->encoder,
+ EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_encoder_));
+ opus_encoder_ctl(opus_encoder_->encoder,
OPUS_GET_DTX(&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.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
}
-TEST_F(OpusTest, OpusDtxOff) {
+TEST_P(OpusTest, OpusDtxOff) {
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);
}
-TEST_F(OpusTest, OpusSetPacketLossRate) {
+TEST_P(OpusTest, OpusSetPacketLossRate) {
// Test without creating encoder memory.
- EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_mono_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);
+ EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
// Create encoder memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1));
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ 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.
- 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.
- EXPECT_EQ(1, WebRtcOpus_DecoderChannels(opus_mono_decoder_));
+ EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
// Encode & decode.
int16_t audio_type;
- int16_t output_data_decode[kOpus20msFrameSamples];
+ int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
EXPECT_EQ(kOpus20msFrameSamples,
- EncodeDecode(opus_mono_encoder_, speech_data_.GetNextBlock(),
- kOpus20msFrameSamples, opus_mono_decoder_,
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+ kOpus20msFrameSamples, opus_decoder_,
output_data_decode, &audio_type));
// Call decoder PLC.
- int16_t plc_buffer[kOpus20msFrameSamples];
+ int16_t* plc_buffer = new int16_t[kOpus20msFrameSamples * channels_];
EXPECT_EQ(kOpus20msFrameSamples,
- WebRtcOpus_DecodePlc(opus_mono_decoder_, plc_buffer, 1));
+ WebRtcOpus_DecodePlc(opus_decoder_, plc_buffer, 1));
// Free memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
- EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_mono_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_));
+ delete[] plc_buffer;
+ delete[] output_data_decode;
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
}
// Duration estimation.
-TEST_F(OpusTest, OpusDurationEstimation) {
- PrepareSpeechData(2, 20, 20);
+TEST_P(OpusTest, OpusDurationEstimation) {
+ PrepareSpeechData(channels_, 20, 20);
// Create.
- EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_stereo_decoder_, 2));
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_,
+ channels_,
+ application_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
// 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(),
kOpus10msFrameSamples, kMaxBytes,
bitstream_);
EXPECT_EQ(kOpus10msFrameSamples,
- WebRtcOpus_DurationEst(opus_stereo_decoder_, bitstream_,
+ WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
encoded_bytes_));
// 20 ms
- encoded_bytes_ = WebRtcOpus_Encode(opus_stereo_encoder_,
+ encoded_bytes_ = WebRtcOpus_Encode(opus_encoder_,
speech_data_.GetNextBlock(),
kOpus20msFrameSamples, kMaxBytes,
bitstream_);
EXPECT_EQ(kOpus20msFrameSamples,
- WebRtcOpus_DurationEst(opus_stereo_decoder_, bitstream_,
+ WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
encoded_bytes_));
// Free memory.
- EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
- EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_stereo_decoder_));
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
}
+INSTANTIATE_TEST_CASE_P(VariousMode,
+ OpusTest,
+ Combine(Values(1, 2), Values(0, 1)));
+
+
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
index b1c4214..6b18095 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
@@ -999,6 +999,12 @@
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 */) {
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
"The send-codec is not Opus, failed to set maximum playback rate.");
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
index d55d91e..b13719f 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
@@ -526,6 +526,20 @@
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()
// Sets maximum playback rate the receiver will render, if the codec is Opus.
// This is to tell Opus that it is enough to code the input audio up to a
@@ -636,8 +650,8 @@
// See InitEncoder() for the description of function, input(s)/output(s)
// and return value.
//
- int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
- bool force_initialization)
+ virtual int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
+ bool force_initialization)
EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_);
///////////////////////////////////////////////////////////////////////////
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus.cc b/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
index 8991dae..005e910 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
@@ -68,7 +68,8 @@
sample_freq_(32000), // Default sampling frequency.
bitrate_(20000), // Default bit-rate.
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;
// Opus has internal DTX, but we dont use it for now.
has_internal_dtx_ = false;
@@ -113,6 +114,16 @@
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 ret;
if (encoder_inst_ptr_ != NULL) {
@@ -120,7 +131,8 @@
encoder_inst_ptr_ = NULL;
}
ret = WebRtcOpus_EncoderCreate(&encoder_inst_ptr_,
- codec_params->codec_inst.channels);
+ codec_params->codec_inst.channels,
+ application_);
// Store number of channels.
channels_ = codec_params->codec_inst.channels;
@@ -251,6 +263,13 @@
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
} // namespace acm2
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus.h b/webrtc/modules/audio_coding/main/acm2/acm_opus.h
index 8ef6406..3c7aea6 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_opus.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus.h
@@ -29,23 +29,29 @@
ACMGenericCodec* CreateInstance(void);
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_);
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:
void DestructEncoderSafe();
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_);
WebRtcOpusEncInst* encoder_inst_ptr_;
@@ -54,6 +60,8 @@
int channels_;
int packet_loss_rate_;
+
+ OpusApplicationMode application_;
};
} // namespace acm2
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc b/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc
index e33c9d3..421bbe5 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc
@@ -35,6 +35,11 @@
: ACMOpus(codec_id) {}
~AcmOpusTest() {}
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);
};
@@ -82,6 +87,54 @@
kPacketLossRate1);
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(¶ms, false));
+ EXPECT_EQ(kAudio, opus.application());
+
+ params.codec_inst.channels = 1;
+ EXPECT_EQ(0, opus.InitEncoder(¶ms, 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(¶ms, 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(¶ms, false));
+ EXPECT_EQ(kAudio, opus.application());
+
+ opus.ResetEncoder();
+ EXPECT_EQ(kAudio, opus.application());
+}
+
#else
void AcmOpusTest:TestSetPacketLossRate(int /* from */, int /* to */,
int /* expected_return */) {
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h b/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h
index e990284..5953cab 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h
@@ -54,6 +54,8 @@
size_t payload_len_bytes,
const RTPFragmentationHeader* fragmentation) OVERRIDE;
+ AudioCodingModule* acm() { return acm_.get(); }
+
private:
static const int kBlockSizeMs = 10;
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 fe2b547..c9139bd 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
@@ -1544,6 +1544,14 @@
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.
int AudioCodingModuleImpl::SetOpusMaxPlaybackRate(int frequency_hz) {
CriticalSectionScoped lock(acm_crit_sect_);
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
index df9e334..d393427 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
@@ -224,6 +224,8 @@
int rate_bit_per_sec,
bool enforce_frame_size = false) OVERRIDE;
+ int SetOpusApplication(OpusApplicationMode application) override;
+
// If current send codec is Opus, informs it about the maximum playback rate
// the receiver will render.
virtual int SetOpusMaxPlaybackRate(int frequency_hz) OVERRIDE;
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
index 0151568..84d5558 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
@@ -977,6 +977,22 @@
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
// frequency during the call. The input packets are simply PCM16b-wb encoded
// payloads with a constant value of |kSampleValue|. The test fixture itself
diff --git a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
index a16b005..7de0a12 100644
--- a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
+++ b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
@@ -875,6 +875,20 @@
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()
// If current send codec is Opus, informs it about maximum playback rate the
// receiver will render. Opus can use this information to optimize the bit
diff --git a/webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h b/webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h
index 199be96..dce5352 100644
--- a/webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h
+++ b/webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h
@@ -200,6 +200,18 @@
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
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_INTERFACE_AUDIO_CODING_MODULE_TYPEDEFS_H_
diff --git a/webrtc/modules/audio_coding/main/test/opus_test.cc b/webrtc/modules/audio_coding/main/test/opus_test.cc
index ecc056a..8fda4b3 100644
--- a/webrtc/modules/audio_coding/main/test/opus_test.cc
+++ b/webrtc/modules/audio_coding/main/test/opus_test.cc
@@ -79,8 +79,8 @@
in_file_mono_.ReadStereo(false);
// Create Opus encoders for mono and stereo.
- ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1), -1);
- ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2), -1);
+ ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1, 0), -1);
+ ASSERT_GT(WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2, 1), -1);
// Create Opus decoders for mono and stereo for stand-alone testing of Opus.
ASSERT_GT(WebRtcOpus_DecoderCreate(&opus_mono_decoder_, 1), -1);
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
index 0f058d0..bcbc4c2 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -447,6 +447,7 @@
AudioEncoderOpus::Config config;
config.frame_size_ms = static_cast<int>(frame_size_) / 48;
config.payload_type = payload_type_;
+ config.application = AudioEncoderOpus::kVoip;
audio_encoder_.reset(new AudioEncoderOpus(config));
}
};
@@ -461,6 +462,7 @@
config.frame_size_ms = static_cast<int>(frame_size_) / 48;
config.num_channels = 2;
config.payload_type = payload_type_;
+ config.application = AudioEncoderOpus::kAudio;
audio_encoder_.reset(new AudioEncoderOpus(config));
}
};
diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_opus_fec_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_opus_fec_quality_test.cc
index eddbffd..e1f53af 100644
--- a/webrtc/modules/audio_coding/neteq/test/neteq_opus_fec_quality_test.cc
+++ b/webrtc/modules/audio_coding/neteq/test/neteq_opus_fec_quality_test.cc
@@ -145,8 +145,10 @@
}
void NetEqOpusFecQualityTest::SetUp() {
+ // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
+ int app = channels_ == 1 ? 0 : 1;
// Create encoder memory.
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_);
+ WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app);
ASSERT_TRUE(opus_encoder_ != NULL);
// Set bitrate.
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_kbps_ * 1000));