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}
This commit is contained in:
@ -1510,7 +1510,9 @@ TEST_F(AcmSenderBitExactnessNewApi, MAYBE_OpusFromFormat_stereo_20ms) {
|
|||||||
test::AcmReceiveTestOldApi::kStereoOutput);
|
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 kNumChannels = 4;
|
||||||
constexpr int kOpusPayloadType = 120;
|
constexpr int kOpusPayloadType = 120;
|
||||||
constexpr int kBitrateBps = 128000;
|
constexpr int kBitrateBps = 128000;
|
||||||
|
@ -21,19 +21,15 @@ RTC_PUSH_IGNORING_WUNDEF()
|
|||||||
RTC_POP_IGNORING_WUNDEF()
|
RTC_POP_IGNORING_WUNDEF()
|
||||||
|
|
||||||
struct WebRtcOpusEncInst {
|
struct WebRtcOpusEncInst {
|
||||||
union {
|
OpusEncoder* encoder;
|
||||||
OpusEncoder* encoder;
|
OpusMSEncoder* multistream_encoder;
|
||||||
OpusMSEncoder* multistream_encoder;
|
|
||||||
} encoder;
|
|
||||||
size_t channels;
|
size_t channels;
|
||||||
int in_dtx_mode;
|
int in_dtx_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WebRtcOpusDecInst {
|
struct WebRtcOpusDecInst {
|
||||||
union {
|
OpusDecoder* decoder;
|
||||||
OpusDecoder* decoder;
|
OpusMSDecoder* multistream_decoder;
|
||||||
OpusMSDecoder* multistream_decoder;
|
|
||||||
} decoder;
|
|
||||||
int prev_decoded_samples;
|
int prev_decoded_samples;
|
||||||
size_t channels;
|
size_t channels;
|
||||||
int in_dtx_mode;
|
int in_dtx_mode;
|
||||||
|
@ -37,40 +37,6 @@ enum {
|
|||||||
kWebRtcOpusDefaultFrameSize = 960,
|
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,
|
int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
|
||||||
size_t channels,
|
size_t channels,
|
||||||
int32_t application) {
|
int32_t application) {
|
||||||
@ -93,30 +59,60 @@ int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
|
|||||||
RTC_DCHECK(state);
|
RTC_DCHECK(state);
|
||||||
|
|
||||||
int error;
|
int error;
|
||||||
if (channels <= 2) {
|
state->encoder = opus_encoder_create(48000, (int)channels, opus_app,
|
||||||
state->encoder.encoder = opus_encoder_create(48000, (int)channels, opus_app,
|
&error);
|
||||||
&error);
|
|
||||||
|
|
||||||
} else {
|
if (error != OPUS_OK || (!state->encoder &&
|
||||||
unsigned char mapping[255];
|
!state->multistream_encoder)) {
|
||||||
memset(mapping, 0, 255);
|
WebRtcOpus_EncoderFree(state);
|
||||||
int streams = -1;
|
return -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.encoder &&
|
state->in_dtx_mode = 0;
|
||||||
!state->encoder.multistream_encoder)) {
|
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);
|
WebRtcOpus_EncoderFree(state);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -130,10 +126,10 @@ int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
|
|||||||
|
|
||||||
int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
|
int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
|
||||||
if (inst) {
|
if (inst) {
|
||||||
if (inst->channels <= 2) {
|
if (inst->encoder) {
|
||||||
opus_encoder_destroy(inst->encoder.encoder);
|
opus_encoder_destroy(inst->encoder);
|
||||||
} else {
|
} else {
|
||||||
opus_multistream_encoder_destroy(inst->encoder.multistream_encoder);
|
opus_multistream_encoder_destroy(inst->multistream_encoder);
|
||||||
}
|
}
|
||||||
free(inst);
|
free(inst);
|
||||||
return 0;
|
return 0;
|
||||||
@ -153,14 +149,14 @@ int WebRtcOpus_Encode(OpusEncInst* inst,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst->channels <= 2) {
|
if (inst->encoder) {
|
||||||
res = opus_encode(inst->encoder.encoder,
|
res = opus_encode(inst->encoder,
|
||||||
(const opus_int16*)audio_in,
|
(const opus_int16*)audio_in,
|
||||||
(int)samples,
|
(int)samples,
|
||||||
encoded,
|
encoded,
|
||||||
(opus_int32)length_encoded_buffer);
|
(opus_int32)length_encoded_buffer);
|
||||||
} else {
|
} else {
|
||||||
res = opus_multistream_encode(inst->encoder.multistream_encoder,
|
res = opus_multistream_encode(inst->multistream_encoder,
|
||||||
(const opus_int16*)audio_in,
|
(const opus_int16*)audio_in,
|
||||||
(int)samples,
|
(int)samples,
|
||||||
encoded,
|
encoded,
|
||||||
@ -187,10 +183,10 @@ int WebRtcOpus_Encode(OpusEncInst* inst,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ENCODER_CTL(inst, vargs) ( \
|
#define ENCODER_CTL(inst, vargs) ( \
|
||||||
inst->channels <= 2 ? \
|
inst->encoder ? \
|
||||||
opus_encoder_ctl(inst->encoder.encoder, vargs) \
|
opus_encoder_ctl(inst->encoder, vargs) \
|
||||||
: opus_multistream_encoder_ctl(inst->encoder.multistream_encoder, vargs))
|
: opus_multistream_encoder_ctl(inst->multistream_encoder, vargs))
|
||||||
|
|
||||||
|
|
||||||
int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
|
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,
|
int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
|
||||||
int32_t* result_hz) {
|
int32_t* result_hz) {
|
||||||
if (inst->channels <= 2) {
|
if (inst->encoder) {
|
||||||
if (opus_encoder_ctl(
|
if (opus_encoder_ctl(
|
||||||
inst->encoder.encoder,
|
inst->encoder,
|
||||||
OPUS_GET_MAX_BANDWIDTH(result_hz)) == OPUS_OK) {
|
OPUS_GET_MAX_BANDWIDTH(result_hz)) == OPUS_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -388,30 +384,10 @@ int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channels <= 2) {
|
// Create new memory, always at 48000 Hz.
|
||||||
state->decoder.decoder = opus_decoder_create(48000,
|
state->decoder = opus_decoder_create(48000,
|
||||||
(int)channels, &error);
|
(int)channels, &error);
|
||||||
} else {
|
if (error == OPUS_OK && state->decoder) {
|
||||||
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)) {
|
|
||||||
// Creation of memory all ok.
|
// Creation of memory all ok.
|
||||||
state->channels = channels;
|
state->channels = channels;
|
||||||
state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
|
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 memory allocation was unsuccessful, free the entire state.
|
||||||
if (state->decoder.decoder) {
|
if (state->decoder) {
|
||||||
opus_decoder_destroy(state->decoder.decoder);
|
opus_decoder_destroy(state->decoder);
|
||||||
|
|
||||||
} else if (state->decoder.multistream_decoder) {
|
|
||||||
opus_multistream_decoder_destroy(state->decoder.multistream_decoder);
|
|
||||||
}
|
}
|
||||||
free(state);
|
free(state);
|
||||||
}
|
}
|
||||||
return -1;
|
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) {
|
int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
|
||||||
if (inst) {
|
if (inst) {
|
||||||
if (inst->channels <= 2) {
|
if (inst->decoder) {
|
||||||
opus_decoder_destroy(inst->decoder.decoder);
|
opus_decoder_destroy(inst->decoder);
|
||||||
} else if (inst->channels > 2) {
|
} else if (inst->multistream_decoder) {
|
||||||
opus_multistream_decoder_destroy(inst->decoder.multistream_decoder);
|
opus_multistream_decoder_destroy(inst->multistream_decoder);
|
||||||
}
|
}
|
||||||
free(inst);
|
free(inst);
|
||||||
return 0;
|
return 0;
|
||||||
@ -451,10 +464,10 @@ size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
|
void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
|
||||||
if (inst->channels <= 2) {
|
if (inst->decoder) {
|
||||||
opus_decoder_ctl(inst->decoder.decoder, OPUS_RESET_STATE);
|
opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
|
||||||
} else {
|
} else {
|
||||||
opus_multistream_decoder_ctl(inst->decoder.multistream_decoder,
|
opus_multistream_decoder_ctl(inst->multistream_decoder,
|
||||||
OPUS_RESET_STATE);
|
OPUS_RESET_STATE);
|
||||||
}
|
}
|
||||||
inst->in_dtx_mode = 0;
|
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,
|
size_t encoded_bytes, int frame_size,
|
||||||
int16_t* decoded, int16_t* audio_type, int decode_fec) {
|
int16_t* decoded, int16_t* audio_type, int decode_fec) {
|
||||||
int res = -1;
|
int res = -1;
|
||||||
if (inst->channels <= 2) {
|
if (inst->decoder) {
|
||||||
res = opus_decode(inst->decoder.decoder, encoded, (opus_int32)encoded_bytes,
|
res = opus_decode(inst->decoder, encoded, (opus_int32)encoded_bytes,
|
||||||
(opus_int16*)decoded, frame_size, decode_fec);
|
(opus_int16*)decoded, frame_size, decode_fec);
|
||||||
} else {
|
} else {
|
||||||
res = opus_multistream_decode(
|
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);
|
(opus_int16*)decoded, frame_size, decode_fec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,10 +27,10 @@ typedef struct WebRtcOpusDecInst OpusDecInst;
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* WebRtcOpus_EncoderCreate(...)
|
* WebRtcOpus_EncoderCreate(...)
|
||||||
*
|
*
|
||||||
* This function create an Opus encoder.
|
* This function creates an Opus encoder that encodes mono or stereo.
|
||||||
*
|
*
|
||||||
* Input:
|
* Input:
|
||||||
* - channels : number of channels.
|
* - channels : number of channels; 1 or 2.
|
||||||
* - application : 0 - VOIP applications.
|
* - application : 0 - VOIP applications.
|
||||||
* Favor speech intelligibility.
|
* Favor speech intelligibility.
|
||||||
* 1 - Audio applications.
|
* 1 - Audio applications.
|
||||||
@ -47,6 +47,36 @@ int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
|
|||||||
size_t channels,
|
size_t channels,
|
||||||
int32_t application);
|
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);
|
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_SetForceChannels(OpusEncInst* inst, size_t num_channels);
|
||||||
|
|
||||||
int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t 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);
|
int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -21,6 +21,64 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
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 test::AudioLoop;
|
||||||
using ::testing::TestWithParam;
|
using ::testing::TestWithParam;
|
||||||
using ::testing::Values;
|
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.
|
// Number of samples-per-channel in a 10 ms frame, sampled at 48 kHz.
|
||||||
const size_t kOpus10msFrameSamples = kOpusRateKhz * 10;
|
const size_t kOpus10msFrameSamples = kOpusRateKhz * 10;
|
||||||
|
|
||||||
class OpusTest : public TestWithParam<::testing::tuple<int, int>> {
|
class OpusTest : public TestWithParam<::testing::tuple<int, int, bool>> {
|
||||||
protected:
|
protected:
|
||||||
OpusTest();
|
OpusTest();
|
||||||
|
|
||||||
@ -74,6 +132,7 @@ class OpusTest : public TestWithParam<::testing::tuple<int, int>> {
|
|||||||
size_t encoded_bytes_;
|
size_t encoded_bytes_;
|
||||||
size_t channels_;
|
size_t channels_;
|
||||||
int application_;
|
int application_;
|
||||||
|
bool force_multistream_;
|
||||||
};
|
};
|
||||||
|
|
||||||
OpusTest::OpusTest()
|
OpusTest::OpusTest()
|
||||||
@ -81,7 +140,8 @@ OpusTest::OpusTest()
|
|||||||
opus_decoder_(NULL),
|
opus_decoder_(NULL),
|
||||||
encoded_bytes_(0),
|
encoded_bytes_(0),
|
||||||
channels_(static_cast<size_t>(::testing::get<0>(GetParam()))),
|
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,
|
void OpusTest::PrepareSpeechData(size_t channel,
|
||||||
int block_length_ms,
|
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;
|
const size_t samples = kOpusRateKhz * block_length_ms;
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
|
||||||
|
force_multistream_);
|
||||||
|
|
||||||
// Set bitrate.
|
// Set bitrate.
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
@ -313,9 +374,10 @@ void OpusTest::TestCbrEffect(bool cbr, int block_length_ms) {
|
|||||||
int32_t prev_pkt_size = 0;
|
int32_t prev_pkt_size = 0;
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
|
||||||
|
force_multistream_);
|
||||||
|
|
||||||
// Set bitrate.
|
// Set bitrate.
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
@ -376,9 +438,10 @@ TEST(OpusTest, OpusFreeFail) {
|
|||||||
|
|
||||||
// Test normal Create and Free.
|
// Test normal Create and Free.
|
||||||
TEST_P(OpusTest, OpusCreateFree) {
|
TEST_P(OpusTest, OpusCreateFree) {
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
|
||||||
|
force_multistream_);
|
||||||
EXPECT_TRUE(opus_encoder_ != NULL);
|
EXPECT_TRUE(opus_encoder_ != NULL);
|
||||||
EXPECT_TRUE(opus_decoder_ != NULL);
|
EXPECT_TRUE(opus_decoder_ != NULL);
|
||||||
// Free encoder and decoder memory.
|
// Free encoder and decoder memory.
|
||||||
@ -386,18 +449,19 @@ TEST_P(OpusTest, OpusCreateFree) {
|
|||||||
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
|
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ENCODER_CTL(inst, vargs) \
|
#define ENCODER_CTL(inst, vargs) \
|
||||||
inst->channels <= 2 \
|
inst->encoder \
|
||||||
? opus_encoder_ctl(inst->encoder.encoder, vargs) \
|
? opus_encoder_ctl(inst->encoder, vargs) \
|
||||||
: opus_multistream_encoder_ctl(inst->encoder.multistream_encoder, vargs)
|
: opus_multistream_encoder_ctl(inst->multistream_encoder, vargs)
|
||||||
|
|
||||||
TEST_P(OpusTest, OpusEncodeDecode) {
|
TEST_P(OpusTest, OpusEncodeDecode) {
|
||||||
PrepareSpeechData(channels_, 20, 20);
|
PrepareSpeechData(channels_, 20, 20);
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
|
||||||
|
force_multistream_);
|
||||||
|
|
||||||
// Set bitrate.
|
// Set bitrate.
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
@ -431,8 +495,8 @@ TEST_P(OpusTest, OpusSetBitRate) {
|
|||||||
EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
|
EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
|
||||||
|
|
||||||
// Create encoder memory, try with different bitrates.
|
// Create encoder memory, try with different bitrates.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000));
|
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000));
|
||||||
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
|
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
|
||||||
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000));
|
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000));
|
||||||
@ -447,8 +511,8 @@ TEST_P(OpusTest, OpusSetComplexity) {
|
|||||||
EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 9));
|
EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 9));
|
||||||
|
|
||||||
// Create encoder memory, try with different complexities.
|
// Create encoder memory, try with different complexities.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
|
|
||||||
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0));
|
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0));
|
||||||
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10));
|
EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10));
|
||||||
@ -476,9 +540,10 @@ TEST_P(OpusTest, OpusSetBandwidth) {
|
|||||||
EXPECT_EQ(-1, WebRtcOpus_GetBandwidth(opus_encoder_));
|
EXPECT_EQ(-1, WebRtcOpus_GetBandwidth(opus_encoder_));
|
||||||
|
|
||||||
// Create encoder memory, try with different bandwidths.
|
// Create encoder memory, try with different bandwidths.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
|
||||||
|
force_multistream_);
|
||||||
|
|
||||||
EXPECT_EQ(-1, WebRtcOpus_SetBandwidth(opus_encoder_,
|
EXPECT_EQ(-1, WebRtcOpus_SetBandwidth(opus_encoder_,
|
||||||
OPUS_BANDWIDTH_NARROWBAND - 1));
|
OPUS_BANDWIDTH_NARROWBAND - 1));
|
||||||
@ -506,8 +571,9 @@ TEST_P(OpusTest, OpusForceChannels) {
|
|||||||
// Test without creating encoder memory.
|
// Test without creating encoder memory.
|
||||||
EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
|
EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
|
||||||
|
|
||||||
ASSERT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
|
ASSERT_NE(nullptr, opus_encoder_);
|
||||||
|
|
||||||
if (channels_ >= 2) {
|
if (channels_ >= 2) {
|
||||||
EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 3));
|
EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 3));
|
||||||
@ -529,9 +595,10 @@ TEST_P(OpusTest, OpusDecodeInit) {
|
|||||||
PrepareSpeechData(channels_, 20, 20);
|
PrepareSpeechData(channels_, 20, 20);
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
|
||||||
|
force_multistream_);
|
||||||
|
|
||||||
// Encode & decode.
|
// Encode & decode.
|
||||||
int16_t audio_type;
|
int16_t audio_type;
|
||||||
@ -560,8 +627,8 @@ TEST_P(OpusTest, OpusEnableDisableFec) {
|
|||||||
EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_encoder_));
|
EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_encoder_));
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
|
|
||||||
EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
|
EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
|
||||||
EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
|
EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
|
||||||
@ -576,8 +643,8 @@ TEST_P(OpusTest, OpusEnableDisableDtx) {
|
|||||||
EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_encoder_));
|
EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_encoder_));
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
|
|
||||||
opus_int32 dtx;
|
opus_int32 dtx;
|
||||||
|
|
||||||
@ -633,8 +700,8 @@ TEST_P(OpusTest, OpusSetPacketLossRate) {
|
|||||||
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
|
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
|
|
||||||
EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
|
EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
|
||||||
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, -1));
|
EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, -1));
|
||||||
@ -649,8 +716,8 @@ TEST_P(OpusTest, OpusSetMaxPlaybackRate) {
|
|||||||
EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, 20000));
|
EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, 20000));
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
|
|
||||||
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 48000);
|
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 48000);
|
||||||
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 24001);
|
SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 24001);
|
||||||
@ -672,9 +739,10 @@ TEST_P(OpusTest, OpusDecodePlc) {
|
|||||||
PrepareSpeechData(channels_, 20, 20);
|
PrepareSpeechData(channels_, 20, 20);
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
|
||||||
|
force_multistream_);
|
||||||
|
|
||||||
// Set bitrate.
|
// Set bitrate.
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
@ -708,9 +776,10 @@ TEST_P(OpusTest, OpusDurationEstimation) {
|
|||||||
PrepareSpeechData(channels_, 20, 20);
|
PrepareSpeechData(channels_, 20, 20);
|
||||||
|
|
||||||
// Create.
|
// Create.
|
||||||
EXPECT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
|
||||||
|
force_multistream_);
|
||||||
|
|
||||||
// 10 ms. We use only first 10 ms of a 20 ms block.
|
// 10 ms. We use only first 10 ms of a 20 ms block.
|
||||||
auto speech_block = speech_data_.GetNextBlock();
|
auto speech_block = speech_data_.GetNextBlock();
|
||||||
@ -753,9 +822,12 @@ TEST_P(OpusTest, OpusDecodeRepacketized) {
|
|||||||
PrepareSpeechData(channels_, 20, 20 * kPackets);
|
PrepareSpeechData(channels_, 20, 20 * kPackets);
|
||||||
|
|
||||||
// Create encoder memory.
|
// Create encoder memory.
|
||||||
ASSERT_EQ(0,
|
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
|
force_multistream_);
|
||||||
ASSERT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
ASSERT_NE(nullptr, opus_encoder_);
|
||||||
|
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_,
|
||||||
|
force_multistream_);
|
||||||
|
ASSERT_NE(nullptr, opus_decoder_);
|
||||||
|
|
||||||
// Set bitrate.
|
// Set bitrate.
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
@ -812,6 +884,13 @@ TEST_P(OpusTest, OpusDecodeRepacketized) {
|
|||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(VariousMode,
|
INSTANTIATE_TEST_SUITE_P(VariousMode,
|
||||||
OpusTest,
|
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
|
} // namespace webrtc
|
||||||
|
Reference in New Issue
Block a user