diff options
Diffstat (limited to 'thirdparty/opus/opus_multistream_encoder.c')
-rw-r--r-- | thirdparty/opus/opus_multistream_encoder.c | 351 |
1 files changed, 164 insertions, 187 deletions
diff --git a/thirdparty/opus/opus_multistream_encoder.c b/thirdparty/opus/opus_multistream_encoder.c index 1698223a16..93204a14c1 100644 --- a/thirdparty/opus/opus_multistream_encoder.c +++ b/thirdparty/opus/opus_multistream_encoder.c @@ -61,38 +61,6 @@ 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; @@ -133,6 +101,29 @@ 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; @@ -240,6 +231,7 @@ 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]; @@ -250,6 +242,7 @@ 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++) @@ -258,7 +251,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, frame_size, opus_val32); + ALLOC(freq, freq_size, opus_val32); channel_pos(channels, pos); @@ -268,8 +261,11 @@ 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); + (*copy_channel_in)(x, 1, pcm, channels, c, len, NULL); celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0); #ifndef FIXED_POINT { @@ -284,18 +280,26 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b } } #endif - clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, - overlap, celt_mode->maxLM-LM, 1, arch); - if (upsample != 1) + OPUS_CLEAR(bandE, 21); + for (frame=0;frame<nb_frames;frame++) { - int bound = len; - for (i=0;i<bound;i++) - freq[i] *= upsample; - for (;i<frame_size;i++) - freq[i] = 0; - } + 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, bandE, 21, 1, LM); + 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]); + } 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++) @@ -408,12 +412,10 @@ opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_ { nb_streams=channels; nb_coupled_streams=0; -#ifdef ENABLE_EXPERIMENTAL_AMBISONICS - } else if (mapping_family==254) + } else if (mapping_family==2) { - nb_streams=channels; - nb_coupled_streams=0; -#endif + if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams)) + return 0; } else return 0; size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams); @@ -448,7 +450,6 @@ 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; @@ -456,7 +457,13 @@ 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) || !validate_encoder_layout(&st->layout)) + 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)) return OPUS_BAD_ARG; ptr = (char*)st + align(sizeof(OpusMSEncoder)); coupled_size = opus_encoder_get_size(2); @@ -549,25 +556,23 @@ int opus_multistream_surround_encoder_init( *coupled_streams=0; for(i=0;i<channels;i++) mapping[i] = i; -#ifdef ENABLE_EXPERIMENTAL_AMBISONICS - } else if (mapping_family==254) + } else if (mapping_family==2) { int i; - *streams=channels; - *coupled_streams=0; - for(i=0;i<channels;i++) - mapping[i] = i; -#endif + 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; } else return OPUS_UNIMPLEMENTED; if (channels>2 && mapping_family==1) { mapping_type = MAPPING_TYPE_SURROUND; -#ifdef ENABLE_EXPERIMENTAL_AMBISONICS - } else if (mapping_family==254) + } else if (mapping_family==2) { mapping_type = MAPPING_TYPE_AMBISONICS; -#endif } else { mapping_type = MAPPING_TYPE_NONE; @@ -672,62 +677,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) { - channel_rate = Fs+60*Fs/frame_size; + bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe; } else if (st->bitrate_bps==OPUS_BITRATE_MAX) { - channel_rate = 300000; + bitrate = nb_normal*300000 + nb_lfe*128000; } else { - 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; + bitrate = st->bitrate_bps; } -#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 + + /* 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; for (i=0;i<st->layout.nb_streams;i++) { if (i<st->layout.nb_coupled_streams) - rate[i] = stream_offset+(channel_rate*coupled_ratio>>8); + rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8)); else if (i!=st->lfe_stream) - rate[i] = stream_offset+channel_rate; + rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate); else - rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8); + rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8)); } } -#ifdef ENABLE_EXPERIMENTAL_AMBISONICS static void ambisonics_rate_allocation( OpusMSEncoder *st, opus_int32 *rate, @@ -736,50 +741,31 @@ static void ambisonics_rate_allocation( ) { int i; - int non_mono_rate; - int total_rate; + opus_int32 total_rate; + opus_int32 per_stream_rate; - /* 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; + const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams; if (st->bitrate_bps==OPUS_AUTO) { - total_rate = num_channels * (20000 + st->layout.nb_streams*(Fs+60*Fs/frame_size)); + total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) * + (Fs+60*Fs/frame_size) + st->layout.nb_streams * (opus_int32)15000; } else if (st->bitrate_bps==OPUS_BITRATE_MAX) { - total_rate = num_channels * 320000; - } else { - total_rate = st->bitrate_bps; - } - - /* 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) + total_rate = nb_channels * 320000; + } else { - opus_int32 bonus = 60*(Fs/frame_size-50); - non_mono_rate += bonus; + total_rate = st->bitrate_bps; } -#endif - rate[0] = total_rate - (num_channels - 1) * non_mono_rate; - for (i=1;i<st->layout.nb_streams;i++) + /* 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++) { - rate[i] = non_mono_rate; + rate[i] = per_stream_rate; } } -#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */ static opus_int32 rate_allocation( OpusMSEncoder *st, @@ -795,11 +781,9 @@ 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); } @@ -812,9 +796,9 @@ static opus_int32 rate_allocation( return rate_sum; } -/* Max size in case the encoder decides to return three frames */ -#define MS_FRAME_TMP (3*1275+7) -static int opus_multistream_encode_native +/* 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 ( OpusMSEncoder *st, opus_copy_channel_in_func copy_channel_in, @@ -824,7 +808,8 @@ static int opus_multistream_encode_native opus_int32 max_data_bytes, int lsb_depth, downmix_func downmix, - int float_api + int float_api, + void *user_data ) { opus_int32 Fs; @@ -859,32 +844,8 @@ static int opus_multistream_encode_native opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr)); opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode)); - { - 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) + frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs); + if (frame_size <= 0) { RESTORE_STACK; return OPUS_BAD_ARG; @@ -892,6 +853,9 @@ static 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; @@ -952,11 +916,9 @@ static 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)); @@ -979,9 +941,9 @@ static 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); + pcm, st->layout.nb_channels, left, frame_size, user_data); (*copy_channel_in)(buf+1, 2, - pcm, st->layout.nb_channels, right, frame_size); + pcm, st->layout.nb_channels, right, frame_size, user_data); ptr += align(coupled_size); if (st->mapping_type == MAPPING_TYPE_SURROUND) { @@ -997,7 +959,7 @@ static 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); + pcm, st->layout.nb_channels, chan, frame_size, user_data); ptr += align(mono_size); if (st->mapping_type == MAPPING_TYPE_SURROUND) { @@ -1013,6 +975,9 @@ static 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; @@ -1053,11 +1018,13 @@ static void opus_copy_channel_in_float( const void *src, int src_stride, int src_channel, - int frame_size + int frame_size, + void *user_data ) { 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) @@ -1074,11 +1041,13 @@ static void opus_copy_channel_in_short( const void *src, int src_stride, int src_channel, - int frame_size + int frame_size, + void *user_data ) { 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) @@ -1099,7 +1068,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); + pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL); } #ifndef DISABLE_FLOAT_API @@ -1112,7 +1081,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); + pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL); } #endif @@ -1128,7 +1097,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); + pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL); } int opus_multistream_encode( @@ -1140,19 +1109,17 @@ 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); + pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL); } #endif -int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) +int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request, + va_list ap) { - 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)); @@ -1161,9 +1128,11 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) case OPUS_SET_BITRATE_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); - if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX) + if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX) { - goto bad_arg; + if (value <= 0) + goto bad_arg; + value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value)); } st->bitrate_bps = value; } @@ -1206,6 +1175,7 @@ int opus_multistream_encoder_ctl(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 */ @@ -1252,6 +1222,7 @@ int opus_multistream_encoder_ctl(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 */ @@ -1278,7 +1249,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OpusEncoder **value; stream_id = va_arg(ap, opus_int32); if (stream_id<0 || stream_id >= st->layout.nb_streams) - ret = OPUS_BAD_ARG; + goto bad_arg; value = va_arg(ap, OpusEncoder**); if (!value) { @@ -1313,7 +1284,6 @@ int opus_multistream_encoder_ctl(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); @@ -1337,14 +1307,21 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) ret = OPUS_UNIMPLEMENTED; break; } - - va_end(ap); return ret; bad_arg: - va_end(ap); 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; +} + void opus_multistream_encoder_destroy(OpusMSEncoder *st) { opus_free(st); |