diff options
Diffstat (limited to 'thirdparty/opus/opus_multistream_encoder.c')
-rw-r--r-- | thirdparty/opus/opus_multistream_encoder.c | 351 |
1 files changed, 187 insertions, 164 deletions
diff --git a/thirdparty/opus/opus_multistream_encoder.c b/thirdparty/opus/opus_multistream_encoder.c index 93204a14c1..1698223a16 100644 --- a/thirdparty/opus/opus_multistream_encoder.c +++ b/thirdparty/opus/opus_multistream_encoder.c @@ -61,6 +61,38 @@ static const VorbisLayout vorbis_mappings[8] = { {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */ }; +typedef void (*opus_copy_channel_in_func)( + opus_val16 *dst, + int dst_stride, + const void *src, + int src_stride, + int src_channel, + int frame_size +); + +typedef enum { + MAPPING_TYPE_NONE, + MAPPING_TYPE_SURROUND +#ifdef ENABLE_EXPERIMENTAL_AMBISONICS + , /* Do not include comma at end of enumerator list */ + MAPPING_TYPE_AMBISONICS +#endif +} MappingType; + +struct OpusMSEncoder { + ChannelLayout layout; + int arch; + int lfe_stream; + int application; + int variable_duration; + MappingType mapping_type; + opus_int32 bitrate_bps; + float subframe_mem[3]; + /* Encoder states go here */ + /* then opus_val32 window_mem[channels*120]; */ + /* then opus_val32 preemph_mem[channels]; */ +}; + static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st) { int s; @@ -101,29 +133,6 @@ static opus_val32 *ms_get_window_mem(OpusMSEncoder *st) return (opus_val32*)(void*)ptr; } -static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams) -{ - int order_plus_one; - int acn_channels; - int nondiegetic_channels; - - if (nb_channels < 1 || nb_channels > 227) - return 0; - - order_plus_one = isqrt32(nb_channels); - acn_channels = order_plus_one * order_plus_one; - nondiegetic_channels = nb_channels - acn_channels; - - if (nondiegetic_channels != 0 && nondiegetic_channels != 2) - return 0; - - if (nb_streams) - *nb_streams = acn_channels + (nondiegetic_channels != 0); - if (nb_coupled_streams) - *nb_coupled_streams = nondiegetic_channels != 0; - return 1; -} - static int validate_encoder_layout(const ChannelLayout *layout) { int s; @@ -231,7 +240,6 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b int pos[8] = {0}; int upsample; int frame_size; - int freq_size; opus_val16 channel_offset; opus_val32 bandE[21]; opus_val16 maskLogE[3][21]; @@ -242,7 +250,6 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b upsample = resampling_factor(rate); frame_size = len*upsample; - freq_size = IMIN(960, frame_size); /* LM = log2(frame_size / 120) */ for (LM=0;LM<celt_mode->maxLM;LM++) @@ -251,7 +258,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b ALLOC(in, frame_size+overlap, opus_val32); ALLOC(x, len, opus_val16); - ALLOC(freq, freq_size, opus_val32); + ALLOC(freq, frame_size, opus_val32); channel_pos(channels, pos); @@ -261,11 +268,8 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b for (c=0;c<channels;c++) { - int frame; - int nb_frames = frame_size/freq_size; - celt_assert(nb_frames*freq_size == frame_size); OPUS_COPY(in, mem+c*overlap, overlap); - (*copy_channel_in)(x, 1, pcm, channels, c, len, NULL); + (*copy_channel_in)(x, 1, pcm, channels, c, len); celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0); #ifndef FIXED_POINT { @@ -280,26 +284,18 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b } } #endif - OPUS_CLEAR(bandE, 21); - for (frame=0;frame<nb_frames;frame++) + clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, + overlap, celt_mode->maxLM-LM, 1, arch); + if (upsample != 1) { - opus_val32 tmpE[21]; - clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window, - overlap, celt_mode->maxLM-LM, 1, arch); - if (upsample != 1) - { - int bound = freq_size/upsample; - for (i=0;i<bound;i++) - freq[i] *= upsample; - for (;i<freq_size;i++) - freq[i] = 0; - } - - compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM, arch); - /* If we have multiple frames, take the max energy. */ - for (i=0;i<21;i++) - bandE[i] = MAX32(bandE[i], tmpE[i]); + int bound = len; + for (i=0;i<bound;i++) + freq[i] *= upsample; + for (;i<frame_size;i++) + freq[i] = 0; } + + compute_band_energies(celt_mode, freq, bandE, 21, 1, LM); amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1); /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */ for (i=1;i<21;i++) @@ -412,10 +408,12 @@ opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_ { nb_streams=channels; nb_coupled_streams=0; - } else if (mapping_family==2) +#ifdef ENABLE_EXPERIMENTAL_AMBISONICS + } else if (mapping_family==254) { - if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams)) - return 0; + nb_streams=channels; + nb_coupled_streams=0; +#endif } else return 0; size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams); @@ -450,6 +448,7 @@ static int opus_multistream_encoder_init_impl( st->layout.nb_channels = channels; st->layout.nb_streams = streams; st->layout.nb_coupled_streams = coupled_streams; + st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0; if (mapping_type != MAPPING_TYPE_SURROUND) st->lfe_stream = -1; st->bitrate_bps = OPUS_AUTO; @@ -457,13 +456,7 @@ static int opus_multistream_encoder_init_impl( st->variable_duration = OPUS_FRAMESIZE_ARG; for (i=0;i<st->layout.nb_channels;i++) st->layout.mapping[i] = mapping[i]; - if (!validate_layout(&st->layout)) - return OPUS_BAD_ARG; - if (mapping_type == MAPPING_TYPE_SURROUND && - !validate_encoder_layout(&st->layout)) - return OPUS_BAD_ARG; - if (mapping_type == MAPPING_TYPE_AMBISONICS && - !validate_ambisonics(st->layout.nb_channels, NULL, NULL)) + if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout)) return OPUS_BAD_ARG; ptr = (char*)st + align(sizeof(OpusMSEncoder)); coupled_size = opus_encoder_get_size(2); @@ -556,23 +549,25 @@ int opus_multistream_surround_encoder_init( *coupled_streams=0; for(i=0;i<channels;i++) mapping[i] = i; - } else if (mapping_family==2) +#ifdef ENABLE_EXPERIMENTAL_AMBISONICS + } else if (mapping_family==254) { int i; - if (!validate_ambisonics(channels, streams, coupled_streams)) - return OPUS_BAD_ARG; - for(i = 0; i < (*streams - *coupled_streams); i++) - mapping[i] = i + (*coupled_streams * 2); - for(i = 0; i < *coupled_streams * 2; i++) - mapping[i + (*streams - *coupled_streams)] = i; + *streams=channels; + *coupled_streams=0; + for(i=0;i<channels;i++) + mapping[i] = i; +#endif } else return OPUS_UNIMPLEMENTED; if (channels>2 && mapping_family==1) { mapping_type = MAPPING_TYPE_SURROUND; - } else if (mapping_family==2) +#ifdef ENABLE_EXPERIMENTAL_AMBISONICS + } else if (mapping_family==254) { mapping_type = MAPPING_TYPE_AMBISONICS; +#endif } else { mapping_type = MAPPING_TYPE_NONE; @@ -677,62 +672,62 @@ static void surround_rate_allocation( int lfe_offset; int coupled_ratio; /* Q8 */ int lfe_ratio; /* Q8 */ - int nb_lfe; - int nb_uncoupled; - int nb_coupled; - int nb_normal; - opus_int32 channel_offset; - opus_int32 bitrate; - int total; - - nb_lfe = (st->lfe_stream!=-1); - nb_coupled = st->layout.nb_coupled_streams; - nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe; - nb_normal = 2*nb_coupled + nb_uncoupled; - - /* Give each non-LFE channel enough bits per channel for coding band energy. */ - channel_offset = 40*IMAX(50, Fs/frame_size); + if (st->bitrate_bps > st->layout.nb_channels*40000) + stream_offset = 20000; + else + stream_offset = st->bitrate_bps/st->layout.nb_channels/2; + stream_offset += 60*(Fs/frame_size-50); + /* We start by giving each stream (coupled or uncoupled) the same bitrate. + This models the main saving of coupled channels over uncoupled. */ + /* The LFE stream is an exception to the above and gets fewer bits. */ + lfe_offset = 3500 + 60*(Fs/frame_size-50); + /* Coupled streams get twice the mono rate after the first 20 kb/s. */ + coupled_ratio = 512; + /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */ + lfe_ratio = 32; + + /* Compute bitrate allocation between streams */ if (st->bitrate_bps==OPUS_AUTO) { - bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe; + channel_rate = Fs+60*Fs/frame_size; } else if (st->bitrate_bps==OPUS_BITRATE_MAX) { - bitrate = nb_normal*300000 + nb_lfe*128000; + channel_rate = 300000; } else { - bitrate = st->bitrate_bps; + int nb_lfe; + int nb_uncoupled; + int nb_coupled; + int total; + nb_lfe = (st->lfe_stream!=-1); + nb_coupled = st->layout.nb_coupled_streams; + nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe; + total = (nb_uncoupled<<8) /* mono */ + + coupled_ratio*nb_coupled /* stereo */ + + nb_lfe*lfe_ratio; + channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total; } - - /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the - total rate for the non-energy part to avoid problems at really low rate. */ - lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size); - - /* We give each stream (coupled or uncoupled) a starting bitrate. - This models the main saving of coupled channels over uncoupled. */ - stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2; - stream_offset = IMAX(0, IMIN(20000, stream_offset)); - - /* Coupled streams get twice the mono rate after the offset is allocated. */ - coupled_ratio = 512; - /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */ - lfe_ratio = 32; - - total = (nb_uncoupled<<8) /* mono */ - + coupled_ratio*nb_coupled /* stereo */ - + nb_lfe*lfe_ratio; - channel_rate = 256*(opus_int64)(bitrate - lfe_offset*nb_lfe - stream_offset*(nb_coupled+nb_uncoupled) - channel_offset*nb_normal)/total; +#ifndef FIXED_POINT + if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50) + { + opus_int32 bonus; + bonus = 60*(Fs/frame_size-50); + channel_rate += bonus; + } +#endif for (i=0;i<st->layout.nb_streams;i++) { if (i<st->layout.nb_coupled_streams) - rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8)); + rate[i] = stream_offset+(channel_rate*coupled_ratio>>8); else if (i!=st->lfe_stream) - rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate); + rate[i] = stream_offset+channel_rate; else - rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8)); + rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8); } } +#ifdef ENABLE_EXPERIMENTAL_AMBISONICS static void ambisonics_rate_allocation( OpusMSEncoder *st, opus_int32 *rate, @@ -741,31 +736,50 @@ static void ambisonics_rate_allocation( ) { int i; - opus_int32 total_rate; - opus_int32 per_stream_rate; + int non_mono_rate; + int total_rate; - const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams; + /* The mono channel gets (rate_ratio_num / rate_ratio_den) times as many bits + * as all other channels */ + const int rate_ratio_num = 4; + const int rate_ratio_den = 3; + const int num_channels = st->layout.nb_streams; if (st->bitrate_bps==OPUS_AUTO) { - total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) * - (Fs+60*Fs/frame_size) + st->layout.nb_streams * (opus_int32)15000; + total_rate = num_channels * (20000 + st->layout.nb_streams*(Fs+60*Fs/frame_size)); } else if (st->bitrate_bps==OPUS_BITRATE_MAX) { - total_rate = nb_channels * 320000; - } else - { + total_rate = num_channels * 320000; + } else { total_rate = st->bitrate_bps; } - /* Allocate equal number of bits to Ambisonic (uncoupled) and non-diegetic - * (coupled) streams */ - per_stream_rate = total_rate / st->layout.nb_streams; - for (i = 0; i < st->layout.nb_streams; i++) + /* Let y be the non-mono rate and let p, q be integers such that the mono + * channel rate is (p/q) * y. + * Also let T be the total bitrate to allocate. Then + * (n - 1) y + (p/q) y = T + * y = (T q) / (qn - q + p) + */ + non_mono_rate = + total_rate * rate_ratio_den + / (rate_ratio_den*num_channels + rate_ratio_num - rate_ratio_den); + +#ifndef FIXED_POINT + if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50) { - rate[i] = per_stream_rate; + opus_int32 bonus = 60*(Fs/frame_size-50); + non_mono_rate += bonus; + } +#endif + + rate[0] = total_rate - (num_channels - 1) * non_mono_rate; + for (i=1;i<st->layout.nb_streams;i++) + { + rate[i] = non_mono_rate; } } +#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */ static opus_int32 rate_allocation( OpusMSEncoder *st, @@ -781,9 +795,11 @@ static opus_int32 rate_allocation( ptr = (char*)st + align(sizeof(OpusMSEncoder)); opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); +#ifdef ENABLE_EXPERIMENTAL_AMBISONICS if (st->mapping_type == MAPPING_TYPE_AMBISONICS) { ambisonics_rate_allocation(st, rate, frame_size, Fs); } else +#endif { surround_rate_allocation(st, rate, frame_size, Fs); } @@ -796,9 +812,9 @@ static opus_int32 rate_allocation( return rate_sum; } -/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */ -#define MS_FRAME_TMP (6*1275+12) -int opus_multistream_encode_native +/* Max size in case the encoder decides to return three frames */ +#define MS_FRAME_TMP (3*1275+7) +static int opus_multistream_encode_native ( OpusMSEncoder *st, opus_copy_channel_in_func copy_channel_in, @@ -808,8 +824,7 @@ int opus_multistream_encode_native opus_int32 max_data_bytes, int lsb_depth, downmix_func downmix, - int float_api, - void *user_data + int float_api ) { opus_int32 Fs; @@ -844,8 +859,32 @@ int opus_multistream_encode_native opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr)); opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode)); - frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs); - if (frame_size <= 0) + { + opus_int32 delay_compensation; + int channels; + + channels = st->layout.nb_streams + st->layout.nb_coupled_streams; + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation)); + delay_compensation -= Fs/400; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, channels, Fs, st->bitrate_bps, + delay_compensation, downmix +#ifndef DISABLE_FLOAT_API + , st->subframe_mem +#endif + ); + } + + if (400*frame_size < Fs) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + /* Validate frame_size before using it to allocate stack space. + This mirrors the checks in opus_encode[_float](). */ + if (400*frame_size != Fs && 200*frame_size != Fs && + 100*frame_size != Fs && 50*frame_size != Fs && + 25*frame_size != Fs && 50*frame_size != 3*Fs) { RESTORE_STACK; return OPUS_BAD_ARG; @@ -853,9 +892,6 @@ int opus_multistream_encode_native /* Smallest packet the encoder can produce. */ smallest_packet = st->layout.nb_streams*2-1; - /* 100 ms needs an extra byte per stream for the ToC. */ - if (Fs/frame_size == 10) - smallest_packet += st->layout.nb_streams; if (max_data_bytes < smallest_packet) { RESTORE_STACK; @@ -916,9 +952,11 @@ int opus_multistream_encode_native opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2)); } } +#ifdef ENABLE_EXPERIMENTAL_AMBISONICS else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) { opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY)); } +#endif } ptr = (char*)st + align(sizeof(OpusMSEncoder)); @@ -941,9 +979,9 @@ int opus_multistream_encode_native left = get_left_channel(&st->layout, s, -1); right = get_right_channel(&st->layout, s, -1); (*copy_channel_in)(buf, 2, - pcm, st->layout.nb_channels, left, frame_size, user_data); + pcm, st->layout.nb_channels, left, frame_size); (*copy_channel_in)(buf+1, 2, - pcm, st->layout.nb_channels, right, frame_size, user_data); + pcm, st->layout.nb_channels, right, frame_size); ptr += align(coupled_size); if (st->mapping_type == MAPPING_TYPE_SURROUND) { @@ -959,7 +997,7 @@ int opus_multistream_encode_native int i; int chan = get_mono_channel(&st->layout, s, -1); (*copy_channel_in)(buf, 1, - pcm, st->layout.nb_channels, chan, frame_size, user_data); + pcm, st->layout.nb_channels, chan, frame_size); ptr += align(mono_size); if (st->mapping_type == MAPPING_TYPE_SURROUND) { @@ -975,9 +1013,6 @@ int opus_multistream_encode_native curr_max = max_data_bytes - tot_size; /* Reserve one byte for the last stream and two for the others */ curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1); - /* For 100 ms, reserve an extra byte per stream for the ToC */ - if (Fs/frame_size == 10) - curr_max -= st->layout.nb_streams-s-1; curr_max = IMIN(curr_max,MS_FRAME_TMP); /* Repacketizer will add one or two bytes for self-delimited frames */ if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1; @@ -1018,13 +1053,11 @@ static void opus_copy_channel_in_float( const void *src, int src_stride, int src_channel, - int frame_size, - void *user_data + int frame_size ) { const float *float_src; opus_int32 i; - (void)user_data; float_src = (const float *)src; for (i=0;i<frame_size;i++) #if defined(FIXED_POINT) @@ -1041,13 +1074,11 @@ static void opus_copy_channel_in_short( const void *src, int src_stride, int src_channel, - int frame_size, - void *user_data + int frame_size ) { const opus_int16 *short_src; opus_int32 i; - (void)user_data; short_src = (const opus_int16 *)src; for (i=0;i<frame_size;i++) #if defined(FIXED_POINT) @@ -1068,7 +1099,7 @@ int opus_multistream_encode( ) { return opus_multistream_encode_native(st, opus_copy_channel_in_short, - pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL); + pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0); } #ifndef DISABLE_FLOAT_API @@ -1081,7 +1112,7 @@ int opus_multistream_encode_float( ) { return opus_multistream_encode_native(st, opus_copy_channel_in_float, - pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL); + pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1); } #endif @@ -1097,7 +1128,7 @@ int opus_multistream_encode_float ) { return opus_multistream_encode_native(st, opus_copy_channel_in_float, - pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL); + pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1); } int opus_multistream_encode( @@ -1109,17 +1140,19 @@ int opus_multistream_encode( ) { return opus_multistream_encode_native(st, opus_copy_channel_in_short, - pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL); + pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0); } #endif -int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request, - va_list ap) +int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) { + va_list ap; int coupled_size, mono_size; char *ptr; int ret = OPUS_OK; + va_start(ap, request); + coupled_size = opus_encoder_get_size(2); mono_size = opus_encoder_get_size(1); ptr = (char*)st + align(sizeof(OpusMSEncoder)); @@ -1128,11 +1161,9 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request, case OPUS_SET_BITRATE_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); - if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX) + if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX) { - if (value <= 0) - goto bad_arg; - value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value)); + goto bad_arg; } st->bitrate_bps = value; } @@ -1175,7 +1206,6 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request, case OPUS_GET_INBAND_FEC_REQUEST: case OPUS_GET_FORCE_CHANNELS_REQUEST: case OPUS_GET_PREDICTION_DISABLED_REQUEST: - case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST: { OpusEncoder *enc; /* For int32* GET params, just query the first stream */ @@ -1222,7 +1252,6 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request, case OPUS_SET_FORCE_MODE_REQUEST: case OPUS_SET_FORCE_CHANNELS_REQUEST: case OPUS_SET_PREDICTION_DISABLED_REQUEST: - case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST: { int s; /* This works for int32 params */ @@ -1249,7 +1278,7 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request, OpusEncoder **value; stream_id = va_arg(ap, opus_int32); if (stream_id<0 || stream_id >= st->layout.nb_streams) - goto bad_arg; + ret = OPUS_BAD_ARG; value = va_arg(ap, OpusEncoder**); if (!value) { @@ -1284,6 +1313,7 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request, case OPUS_RESET_STATE: { int s; + st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0; if (st->mapping_type == MAPPING_TYPE_SURROUND) { OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels); @@ -1307,19 +1337,12 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request, ret = OPUS_UNIMPLEMENTED; break; } - return ret; -bad_arg: - return OPUS_BAD_ARG; -} -int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) -{ - int ret; - va_list ap; - va_start(ap, request); - ret = opus_multistream_encoder_ctl_va_list(st, request, ap); va_end(ap); return ret; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; } void opus_multistream_encoder_destroy(OpusMSEncoder *st) |