diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc index e64077e24f..ef5f0244a4 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_F(AcmSenderBitExactnessNewApi, MAYBE_OpusFromFormat_stereo_20ms) { 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 0b311817d0..08c1e0f361 100644 --- a/modules/audio_coding/codecs/opus/opus_inst.h +++ b/modules/audio_coding/codecs/opus/opus_inst.h @@ -21,19 +21,15 @@ RTC_PUSH_IGNORING_WUNDEF() 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 3369f8e9cd..f6e053a7fc 100644 --- a/modules/audio_coding/codecs/opus/opus_interface.c +++ b/modules/audio_coding/codecs/opus/opus_interface.c @@ -37,40 +37,6 @@ enum { 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 @@ int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, 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_EncoderCreate(OpusEncInst** inst, 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 @@ int WebRtcOpus_Encode(OpusEncInst* inst, 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 @@ int WebRtcOpus_Encode(OpusEncInst* inst, 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_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz) { 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 @@ int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) { 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 @@ int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) { } // 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 @@ size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) { } 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 @@ static int DecodeNative(OpusDecInst* inst, const uint8_t* encoded, 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 0e97734f38..04eaba95f7 100644 --- a/modules/audio_coding/codecs/opus/opus_interface.h +++ b/modules/audio_coding/codecs/opus/opus_interface.h @@ -27,10 +27,10 @@ typedef struct WebRtcOpusDecInst OpusDecInst; /**************************************************************************** * 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 @@ int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, 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_SetBandwidth(OpusEncInst* inst, int32_t bandwidth); 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 56dfd6a257..aa7eee97d6 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 @@ const size_t kOpus20msFrameSamples = kOpusRateKhz * 20; // 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> { +class OpusTest : public TestWithParam<::testing::tuple> { protected: OpusTest(); @@ -74,6 +132,7 @@ class OpusTest : public TestWithParam<::testing::tuple> { size_t encoded_bytes_; size_t channels_; int application_; + bool force_multistream_; }; OpusTest::OpusTest() @@ -81,7 +140,8 @@ OpusTest::OpusTest() opus_decoder_(NULL), encoded_bytes_(0), channels_(static_cast(::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 @@ void OpusTest::TestDtxEffect(bool dtx, int block_length_ms) { 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 @@ void OpusTest::TestCbrEffect(bool cbr, int block_length_ms) { 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(OpusTest, OpusFreeFail) { // 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 @@ TEST_P(OpusTest, OpusCreateFree) { 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 @@ TEST_P(OpusTest, OpusSetBitRate) { 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 @@ TEST_P(OpusTest, OpusSetComplexity) { 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 @@ TEST_P(OpusTest, OpusSetBandwidth) { 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_P(OpusTest, OpusForceChannels) { // 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 @@ TEST_P(OpusTest, OpusDecodeInit) { 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 @@ TEST_P(OpusTest, OpusEnableDisableFec) { 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 @@ TEST_P(OpusTest, OpusEnableDisableDtx) { 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 @@ TEST_P(OpusTest, OpusSetPacketLossRate) { 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 @@ TEST_P(OpusTest, OpusSetMaxPlaybackRate) { 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 @@ 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_)); + CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, + force_multistream_); + CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, + force_multistream_); // Set bitrate. EXPECT_EQ( @@ -708,9 +776,10 @@ TEST_P(OpusTest, OpusDurationEstimation) { 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 @@ TEST_P(OpusTest, OpusDecodeRepacketized) { 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 @@ TEST_P(OpusTest, OpusDecodeRepacketized) { 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