Generalize the C-language Opus interface.
Switch to explicit channel mappings (RFC 7845) when creating
multi-stream Opus en/de-coders. The responsibility of setting up the
channel mappings will shift from WebRTC to the WebRTC user.
See https://webrtc-review.googlesource.com/c/src/+/121764 for the
current vision. See also the first child CL
https://webrtc-review.googlesource.com/c/src/+/129768
that sets up the Decoder to use this code.
Bug: webrtc:8649
Change-Id: I55959a293d54bb4c982eff68ec107c5ef8666c5c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/129767
Commit-Queue: Alex Loiko <aleloi@webrtc.org>
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27452}
diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
index e64077e..ef5f024 100644
--- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -1510,7 +1510,9 @@
test::AcmReceiveTestOldApi::kStereoOutput);
}
-TEST_F(AcmSenderBitExactnessNewApi, OpusManyChannels) {
+// TODO(webrtc:8649): Disabled until the Encoder counterpart of
+// https://webrtc-review.googlesource.com/c/src/+/129768 lands.
+TEST_F(AcmSenderBitExactnessNewApi, DISABLED_OpusManyChannels) {
constexpr int kNumChannels = 4;
constexpr int kOpusPayloadType = 120;
constexpr int kBitrateBps = 128000;
diff --git a/modules/audio_coding/codecs/opus/opus_inst.h b/modules/audio_coding/codecs/opus/opus_inst.h
index 0b31181..08c1e0f 100644
--- a/modules/audio_coding/codecs/opus/opus_inst.h
+++ b/modules/audio_coding/codecs/opus/opus_inst.h
@@ -21,19 +21,15 @@
RTC_POP_IGNORING_WUNDEF()
struct WebRtcOpusEncInst {
- union {
- OpusEncoder* encoder;
- OpusMSEncoder* multistream_encoder;
- } encoder;
+ OpusEncoder* encoder;
+ OpusMSEncoder* multistream_encoder;
size_t channels;
int in_dtx_mode;
};
struct WebRtcOpusDecInst {
- union {
- OpusDecoder* decoder;
- OpusMSDecoder* multistream_decoder;
- } decoder;
+ OpusDecoder* decoder;
+ OpusMSDecoder* multistream_decoder;
int prev_decoded_samples;
size_t channels;
int in_dtx_mode;
diff --git a/modules/audio_coding/codecs/opus/opus_interface.c b/modules/audio_coding/codecs/opus/opus_interface.c
index 3369f8e..f6e053a 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.c
+++ b/modules/audio_coding/codecs/opus/opus_interface.c
@@ -37,40 +37,6 @@
kWebRtcOpusDefaultFrameSize = 960,
};
-int16_t GetSurroundParameters(int channels,
- int *streams,
- int *coupled_streams,
- unsigned char *mapping) {
- int opus_error;
- int ret = 0;
- // Use 'surround encoder create' to get values for 'coupled_streams',
- // 'streams' and 'mapping'.
- OpusMSEncoder* ms_encoder_ptr = opus_multistream_surround_encoder_create(
- 48000,
- channels,
- /* mapping family */ channels <= 2 ? 0 : 1,
- streams,
- coupled_streams,
- mapping,
- OPUS_APPLICATION_VOIP, // Application type shouldn't affect
- // streams/mapping values.
- &opus_error);
-
- // This shouldn't fail; if it fails,
- // signal an error and return invalid values.
- if (opus_error != OPUS_OK || ms_encoder_ptr == NULL) {
- ret = -1;
- *streams = -1;
- *coupled_streams = -1;
- }
-
- // We don't need the encoder.
- if (ms_encoder_ptr != NULL) {
- opus_multistream_encoder_destroy(ms_encoder_ptr);
- }
- return ret;
-}
-
int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
size_t channels,
int32_t application) {
@@ -93,30 +59,60 @@
RTC_DCHECK(state);
int error;
- if (channels <= 2) {
- state->encoder.encoder = opus_encoder_create(48000, (int)channels, opus_app,
- &error);
+ state->encoder = opus_encoder_create(48000, (int)channels, opus_app,
+ &error);
- } else {
- unsigned char mapping[255];
- memset(mapping, 0, 255);
- int streams = -1;
- int coupled_streams = -1;
-
- state->encoder.multistream_encoder =
- opus_multistream_surround_encoder_create(
- 48000,
- channels,
- /* mapping family */ 1,
- &streams,
- &coupled_streams,
- mapping,
- opus_app,
- &error);
+ if (error != OPUS_OK || (!state->encoder &&
+ !state->multistream_encoder)) {
+ WebRtcOpus_EncoderFree(state);
+ return -1;
}
- if (error != OPUS_OK || (!state->encoder.encoder &&
- !state->encoder.multistream_encoder)) {
+ state->in_dtx_mode = 0;
+ state->channels = channels;
+
+ *inst = state;
+ return 0;
+}
+
+int16_t WebRtcOpus_MultistreamEncoderCreate(
+ OpusEncInst** inst,
+ size_t channels,
+ int32_t application,
+ size_t coupled_streams,
+ const unsigned char *channel_mapping) {
+ int opus_app;
+ if (!inst)
+ return -1;
+
+ switch (application) {
+ case 0:
+ opus_app = OPUS_APPLICATION_VOIP;
+ break;
+ case 1:
+ opus_app = OPUS_APPLICATION_AUDIO;
+ break;
+ default:
+ return -1;
+ }
+
+ OpusEncInst* state = (OpusEncInst*)calloc(1, sizeof(OpusEncInst));
+ RTC_DCHECK(state);
+
+ int streams = channels - coupled_streams;
+ int error;
+ state->multistream_encoder =
+ opus_multistream_encoder_create(
+ 48000,
+ channels,
+ streams,
+ coupled_streams,
+ channel_mapping,
+ opus_app,
+ &error);
+
+ if (error != OPUS_OK || (!state->encoder &&
+ !state->multistream_encoder)) {
WebRtcOpus_EncoderFree(state);
return -1;
}
@@ -130,10 +126,10 @@
int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
if (inst) {
- if (inst->channels <= 2) {
- opus_encoder_destroy(inst->encoder.encoder);
+ if (inst->encoder) {
+ opus_encoder_destroy(inst->encoder);
} else {
- opus_multistream_encoder_destroy(inst->encoder.multistream_encoder);
+ opus_multistream_encoder_destroy(inst->multistream_encoder);
}
free(inst);
return 0;
@@ -153,14 +149,14 @@
return -1;
}
- if (inst->channels <= 2) {
- res = opus_encode(inst->encoder.encoder,
+ if (inst->encoder) {
+ res = opus_encode(inst->encoder,
(const opus_int16*)audio_in,
(int)samples,
encoded,
(opus_int32)length_encoded_buffer);
} else {
- res = opus_multistream_encode(inst->encoder.multistream_encoder,
+ res = opus_multistream_encode(inst->multistream_encoder,
(const opus_int16*)audio_in,
(int)samples,
encoded,
@@ -187,10 +183,10 @@
return res;
}
-#define ENCODER_CTL(inst, vargs) ( \
- inst->channels <= 2 ? \
- opus_encoder_ctl(inst->encoder.encoder, vargs) \
- : opus_multistream_encoder_ctl(inst->encoder.multistream_encoder, vargs))
+#define ENCODER_CTL(inst, vargs) ( \
+ inst->encoder ? \
+ opus_encoder_ctl(inst->encoder, vargs) \
+ : opus_multistream_encoder_ctl(inst->multistream_encoder, vargs))
int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
@@ -231,9 +227,9 @@
int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
int32_t* result_hz) {
- if (inst->channels <= 2) {
+ if (inst->encoder) {
if (opus_encoder_ctl(
- inst->encoder.encoder,
+ inst->encoder,
OPUS_GET_MAX_BANDWIDTH(result_hz)) == OPUS_OK) {
return 0;
}
@@ -388,30 +384,10 @@
return -1;
}
- if (channels <= 2) {
- state->decoder.decoder = opus_decoder_create(48000,
- (int)channels, &error);
- } else {
- unsigned char mapping[255];
- memset(mapping, 0, 255);
- int streams = -1;
- int coupled_streams = -1;
- if (GetSurroundParameters(channels, &streams,
- &coupled_streams, mapping) != 0) {
- free(state);
- return -1;
- }
-
- // Create new memory, always at 48000 Hz.
- state->decoder.multistream_decoder = opus_multistream_decoder_create(
- 48000, (int)channels,
- /* streams = */ streams,
- /* coupled streams = */ coupled_streams,
- mapping,
- &error);
- }
- if (error == OPUS_OK && (state->decoder.decoder ||
- state->decoder.multistream_decoder)) {
+ // Create new memory, always at 48000 Hz.
+ state->decoder = opus_decoder_create(48000,
+ (int)channels, &error);
+ if (error == OPUS_OK && state->decoder) {
// Creation of memory all ok.
state->channels = channels;
state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
@@ -421,23 +397,60 @@
}
// If memory allocation was unsuccessful, free the entire state.
- if (state->decoder.decoder) {
- opus_decoder_destroy(state->decoder.decoder);
-
- } else if (state->decoder.multistream_decoder) {
- opus_multistream_decoder_destroy(state->decoder.multistream_decoder);
+ if (state->decoder) {
+ opus_decoder_destroy(state->decoder);
}
free(state);
}
return -1;
}
+int16_t WebRtcOpus_MultistreamDecoderCreate(
+ OpusDecInst** inst, size_t channels,
+ size_t coupled_streams,
+ const unsigned char* channel_mapping) {
+ int error;
+ OpusDecInst* state;
+
+ if (inst != NULL) {
+ // Create Opus decoder state.
+ state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
+ if (state == NULL) {
+ return -1;
+ }
+
+ int streams = channels - coupled_streams;
+
+ // Create new memory, always at 48000 Hz.
+ state->multistream_decoder = opus_multistream_decoder_create(
+ 48000, (int)channels,
+ streams,
+ coupled_streams,
+ channel_mapping,
+ &error);
+
+ if (error == OPUS_OK && state->multistream_decoder) {
+ // Creation of memory all ok.
+ state->channels = channels;
+ state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
+ state->in_dtx_mode = 0;
+ *inst = state;
+ return 0;
+ }
+
+ // If memory allocation was unsuccessful, free the entire state.
+ opus_multistream_decoder_destroy(state->multistream_decoder);
+ free(state);
+ }
+ return -1;
+}
+
int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
if (inst) {
- if (inst->channels <= 2) {
- opus_decoder_destroy(inst->decoder.decoder);
- } else if (inst->channels > 2) {
- opus_multistream_decoder_destroy(inst->decoder.multistream_decoder);
+ if (inst->decoder) {
+ opus_decoder_destroy(inst->decoder);
+ } else if (inst->multistream_decoder) {
+ opus_multistream_decoder_destroy(inst->multistream_decoder);
}
free(inst);
return 0;
@@ -451,10 +464,10 @@
}
void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
- if (inst->channels <= 2) {
- opus_decoder_ctl(inst->decoder.decoder, OPUS_RESET_STATE);
+ if (inst->decoder) {
+ opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
} else {
- opus_multistream_decoder_ctl(inst->decoder.multistream_decoder,
+ opus_multistream_decoder_ctl(inst->multistream_decoder,
OPUS_RESET_STATE);
}
inst->in_dtx_mode = 0;
@@ -490,12 +503,12 @@
size_t encoded_bytes, int frame_size,
int16_t* decoded, int16_t* audio_type, int decode_fec) {
int res = -1;
- if (inst->channels <= 2) {
- res = opus_decode(inst->decoder.decoder, encoded, (opus_int32)encoded_bytes,
+ if (inst->decoder) {
+ res = opus_decode(inst->decoder, encoded, (opus_int32)encoded_bytes,
(opus_int16*)decoded, frame_size, decode_fec);
} else {
res = opus_multistream_decode(
- inst->decoder.multistream_decoder, encoded, (opus_int32)encoded_bytes,
+ inst->multistream_decoder, encoded, (opus_int32)encoded_bytes,
(opus_int16*)decoded, frame_size, decode_fec);
}
diff --git a/modules/audio_coding/codecs/opus/opus_interface.h b/modules/audio_coding/codecs/opus/opus_interface.h
index 0e97734..04eaba9 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.h
+++ b/modules/audio_coding/codecs/opus/opus_interface.h
@@ -27,10 +27,10 @@
/****************************************************************************
* WebRtcOpus_EncoderCreate(...)
*
- * This function create an Opus encoder.
+ * This function creates an Opus encoder that encodes mono or stereo.
*
* Input:
- * - channels : number of channels.
+ * - channels : number of channels; 1 or 2.
* - application : 0 - VOIP applications.
* Favor speech intelligibility.
* 1 - Audio applications.
@@ -47,6 +47,36 @@
size_t channels,
int32_t application);
+/****************************************************************************
+ * WebRtcOpus_MultistreamEncoderCreate(...)
+ *
+ * This function creates an Opus encoder with any supported channel count.
+ *
+ * Input:
+ * - channels : number of channels.
+ * - application : 0 - VOIP applications.
+ * Favor speech intelligibility.
+ * 1 - Audio applications.
+ * Favor faithfulness to the original input.
+ * - coupled_streams : number of coupled streams, as described in
+ * RFC 7845.
+ * - channel_mapping : the channel mapping; pointer to array of
+ * `channel` bytes, as described in RFC 7845.
+ *
+ * Output:
+ * - inst : a pointer to Encoder context that is created
+ * if success.
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_MultistreamEncoderCreate(
+ OpusEncInst** inst,
+ size_t channels,
+ int32_t application,
+ size_t coupled_streams,
+ const unsigned char* channel_mapping);
+
int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst);
/****************************************************************************
@@ -295,6 +325,32 @@
int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels);
int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels);
+
+/****************************************************************************
+ * WebRtcOpus_MultistreamDecoderCreate(...)
+ *
+ * This function creates an Opus decoder with any supported channel count.
+ *
+ * Input:
+ * - channels : number of channels.
+ * - coupled_streams : number of coupled streams, as described in
+ * RFC 7845.
+ * - channel_mapping : the channel mapping; pointer to array of
+ * `channel` bytes, as described in RFC 7845.
+ *
+ * Output:
+ * - inst : a pointer to a Decoder context that is created
+ * if success.
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_MultistreamDecoderCreate(
+ OpusDecInst** inst,
+ size_t channels,
+ size_t coupled_streams,
+ const unsigned char* channel_mapping);
+
int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst);
/****************************************************************************
diff --git a/modules/audio_coding/codecs/opus/opus_unittest.cc b/modules/audio_coding/codecs/opus/opus_unittest.cc
index 56dfd6a..aa7eee9 100644
--- a/modules/audio_coding/codecs/opus/opus_unittest.cc
+++ b/modules/audio_coding/codecs/opus/opus_unittest.cc
@@ -21,6 +21,64 @@
namespace webrtc {
+namespace {
+// Equivalent to SDP params
+// {{"channel_mapping", "0,1,2,3"}, {"coupled_streams", "2"}}.
+constexpr unsigned char kQuadChannelMapping[] = {0, 1, 2, 3};
+constexpr int kQuadCoupledStreams = 2;
+
+constexpr unsigned char kStereoChannelMapping[] = {0, 1};
+constexpr int kStereoCoupledStreams = 1;
+
+constexpr unsigned char kMonoChannelMapping[] = {0};
+constexpr int kMonoCoupledStreams = 0;
+
+void CreateSingleOrMultiStreamEncoder(WebRtcOpusEncInst** opus_encoder,
+ int channels,
+ int application,
+ bool force_multistream = false) {
+ if (!force_multistream && (channels == 1 || channels == 2)) {
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(opus_encoder, channels, application));
+ } else if (force_multistream && channels == 1) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
+ opus_encoder, channels, application, kMonoCoupledStreams,
+ kMonoChannelMapping));
+ } else if (force_multistream && channels == 2) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
+ opus_encoder, channels, application, kStereoCoupledStreams,
+ kStereoChannelMapping));
+ } else if (channels == 4) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
+ opus_encoder, channels, application, kQuadCoupledStreams,
+ kQuadChannelMapping));
+ } else {
+ EXPECT_TRUE(false) << channels;
+ }
+}
+
+void CreateSingleOrMultiStreamDecoder(WebRtcOpusDecInst** opus_decoder,
+ int channels,
+ bool force_multistream = false) {
+ if (!force_multistream && (channels == 1 || channels == 2)) {
+ EXPECT_EQ(0, WebRtcOpus_DecoderCreate(opus_decoder, channels));
+ } else if (channels == 1) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(opus_decoder, channels,
+ kMonoCoupledStreams,
+ kMonoChannelMapping));
+ } else if (channels == 2) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(opus_decoder, channels,
+ kStereoCoupledStreams,
+ kStereoChannelMapping));
+ } else if (channels == 4) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(opus_decoder, channels,
+ kQuadCoupledStreams,
+ kQuadChannelMapping));
+ } else {
+ EXPECT_TRUE(false) << channels;
+ }
+}
+} // namespace
+
using test::AudioLoop;
using ::testing::TestWithParam;
using ::testing::Values;
@@ -35,7 +93,7 @@
// Number of samples-per-channel in a 10 ms frame, sampled at 48 kHz.
const size_t kOpus10msFrameSamples = kOpusRateKhz * 10;
-class OpusTest : public TestWithParam<::testing::tuple<int, int>> {
+class OpusTest : public TestWithParam<::testing::tuple<int, int, bool>> {
protected:
OpusTest();
@@ -74,6 +132,7 @@
size_t encoded_bytes_;
size_t channels_;
int application_;
+ bool force_multistream_;
};
OpusTest::OpusTest()
@@ -81,7 +140,8 @@
opus_decoder_(NULL),
encoded_bytes_(0),
channels_(static_cast<size_t>(::testing::get<0>(GetParam()))),
- application_(::testing::get<1>(GetParam())) {}
+ application_(::testing::get<1>(GetParam())),
+ force_multistream_(::testing::get<2>(GetParam())) {}
void OpusTest::PrepareSpeechData(size_t channel,
int block_length_ms,
@@ -148,9 +208,10 @@
const size_t samples = kOpusRateKhz * block_length_ms;
// Create encoder memory.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
+ force_multistream_);
// Set bitrate.
EXPECT_EQ(
@@ -313,9 +374,10 @@
int32_t prev_pkt_size = 0;
// Create encoder memory.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
+ force_multistream_);
// Set bitrate.
EXPECT_EQ(
@@ -376,9 +438,10 @@
// Test normal Create and Free.
TEST_P(OpusTest, OpusCreateFree) {
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
+ force_multistream_);
EXPECT_TRUE(opus_encoder_ != NULL);
EXPECT_TRUE(opus_decoder_ != NULL);
// Free encoder and decoder memory.
@@ -386,18 +449,19 @@
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
}
-#define ENCODER_CTL(inst, vargs) \
- inst->channels <= 2 \
- ? opus_encoder_ctl(inst->encoder.encoder, vargs) \
- : opus_multistream_encoder_ctl(inst->encoder.multistream_encoder, vargs)
+#define ENCODER_CTL(inst, vargs) \
+ inst->encoder \
+ ? opus_encoder_ctl(inst->encoder, vargs) \
+ : opus_multistream_encoder_ctl(inst->multistream_encoder, vargs)
TEST_P(OpusTest, OpusEncodeDecode) {
PrepareSpeechData(channels_, 20, 20);
// Create encoder memory.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
+ force_multistream_);
// Set bitrate.
EXPECT_EQ(
@@ -431,8 +495,8 @@
EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
// Create encoder memory, try with different bitrates.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000));
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000));
@@ -447,8 +511,8 @@
EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 9));
// Create encoder memory, try with different complexities.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0));
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10));
@@ -476,9 +540,10 @@
EXPECT_EQ(-1, WebRtcOpus_GetBandwidth(opus_encoder_));
// Create encoder memory, try with different bandwidths.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
+ force_multistream_);
EXPECT_EQ(-1, WebRtcOpus_SetBandwidth(opus_encoder_,
OPUS_BANDWIDTH_NARROWBAND - 1));
@@ -506,8 +571,9 @@
// Test without creating encoder memory.
EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
- ASSERT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ ASSERT_NE(nullptr, opus_encoder_);
if (channels_ >= 2) {
EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 3));
@@ -529,9 +595,10 @@
PrepareSpeechData(channels_, 20, 20);
// Create encoder memory.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
+ force_multistream_);
// Encode & decode.
int16_t audio_type;
@@ -560,8 +627,8 @@
EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_encoder_));
// Create encoder memory.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
@@ -576,8 +643,8 @@
EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_encoder_));
// Create encoder memory.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
opus_int32 dtx;
@@ -633,8 +700,8 @@
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
// Create encoder memory.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, -1));
@@ -649,8 +716,8 @@
EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, 20000));
// Create encoder memory.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 48000);
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 24001);
@@ -672,9 +739,10 @@
PrepareSpeechData(channels_, 20, 20);
// Create encoder memory.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
+ force_multistream_);
// Set bitrate.
EXPECT_EQ(
@@ -708,9 +776,10 @@
PrepareSpeechData(channels_, 20, 20);
// Create.
- EXPECT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
- EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
+ force_multistream_);
// 10 ms. We use only first 10 ms of a 20 ms block.
auto speech_block = speech_data_.GetNextBlock();
@@ -753,9 +822,12 @@
PrepareSpeechData(channels_, 20, 20 * kPackets);
// Create encoder memory.
- ASSERT_EQ(0,
- WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
- ASSERT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ force_multistream_);
+ ASSERT_NE(nullptr, opus_encoder_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
+ force_multistream_);
+ ASSERT_NE(nullptr, opus_decoder_);
// Set bitrate.
EXPECT_EQ(
@@ -812,6 +884,13 @@
INSTANTIATE_TEST_SUITE_P(VariousMode,
OpusTest,
- Combine(Values(1, 2, 4), Values(0, 1)));
+ ::testing::ValuesIn({
+ std::make_tuple(1, 0, true),
+ std::make_tuple(1, 1, true),
+ std::make_tuple(2, 0, false),
+ std::make_tuple(4, 0, false),
+ std::make_tuple(1, 1, false),
+ std::make_tuple(4, 1, false),
+ }));
} // namespace webrtc