| Index: src/opus_multistream_encoder.c
|
| diff --git a/src/opus_multistream_encoder.c b/src/opus_multistream_encoder.c
|
| index 49e27913ee0cd64887df8e3a04eb24885a3806dc..6e87337d93f97d0c55d7ecc1e624f04261c2d5be 100644
|
| --- a/src/opus_multistream_encoder.c
|
| +++ b/src/opus_multistream_encoder.c
|
| @@ -267,7 +267,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
|
| freq[i] = 0;
|
| }
|
|
|
| - compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM);
|
| + 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++)
|
| @@ -408,7 +408,7 @@ static int opus_multistream_encoder_init_impl(
|
| char *ptr;
|
|
|
| if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
|
| - (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
|
| + (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
|
| return OPUS_BAD_ARG;
|
|
|
| st->layout.nb_channels = channels;
|
| @@ -530,7 +530,7 @@ OpusMSEncoder *opus_multistream_encoder_create(
|
| int ret;
|
| OpusMSEncoder *st;
|
| if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
|
| - (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
|
| + (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
|
| {
|
| if (error)
|
| *error = OPUS_BAD_ARG;
|
| @@ -566,6 +566,7 @@ OpusMSEncoder *opus_multistream_surround_encoder_create(
|
| )
|
| {
|
| int ret;
|
| + opus_int32 size;
|
| OpusMSEncoder *st;
|
| if ((channels>255) || (channels<1))
|
| {
|
| @@ -573,7 +574,14 @@ OpusMSEncoder *opus_multistream_surround_encoder_create(
|
| *error = OPUS_BAD_ARG;
|
| return NULL;
|
| }
|
| - st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
|
| + size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
|
| + if (!size)
|
| + {
|
| + if (error)
|
| + *error = OPUS_UNIMPLEMENTED;
|
| + return NULL;
|
| + }
|
| + st = (OpusMSEncoder *)opus_alloc(size);
|
| if (st==NULL)
|
| {
|
| if (error)
|
| @@ -591,7 +599,7 @@ OpusMSEncoder *opus_multistream_surround_encoder_create(
|
| return st;
|
| }
|
|
|
| -static void surround_rate_allocation(
|
| +static opus_int32 surround_rate_allocation(
|
| OpusMSEncoder *st,
|
| opus_int32 *rate,
|
| int frame_size
|
| @@ -605,6 +613,7 @@ static void surround_rate_allocation(
|
| int lfe_offset;
|
| int coupled_ratio; /* Q8 */
|
| int lfe_ratio; /* Q8 */
|
| + opus_int32 rate_sum=0;
|
|
|
| ptr = (char*)st + align(sizeof(OpusMSEncoder));
|
| opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
|
| @@ -660,7 +669,10 @@ static void surround_rate_allocation(
|
| rate[i] = stream_offset+channel_rate;
|
| else
|
| rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
|
| + rate[i] = IMAX(rate[i], 500);
|
| + rate_sum += rate[i];
|
| }
|
| + return rate_sum;
|
| }
|
|
|
| /* Max size in case the encoder decides to return three frames */
|
| @@ -674,7 +686,8 @@ static int opus_multistream_encode_native
|
| unsigned char *data,
|
| opus_int32 max_data_bytes,
|
| int lsb_depth,
|
| - downmix_func downmix
|
| + downmix_func downmix,
|
| + int float_api
|
| )
|
| {
|
| opus_int32 Fs;
|
| @@ -694,6 +707,8 @@ static int opus_multistream_encode_native
|
| opus_val32 *mem = NULL;
|
| opus_val32 *preemph_mem=NULL;
|
| int frame_size;
|
| + opus_int32 rate_sum;
|
| + opus_int32 smallest_packet;
|
| ALLOC_STACK;
|
|
|
| if (st->surround)
|
| @@ -737,6 +752,14 @@ static int opus_multistream_encode_native
|
| RESTORE_STACK;
|
| return OPUS_BAD_ARG;
|
| }
|
| +
|
| + /* Smallest packet the encoder can produce. */
|
| + smallest_packet = st->layout.nb_streams*2-1;
|
| + if (max_data_bytes < smallest_packet)
|
| + {
|
| + RESTORE_STACK;
|
| + return OPUS_BUFFER_TOO_SMALL;
|
| + }
|
| ALLOC(buf, 2*frame_size, opus_val16);
|
| coupled_size = opus_encoder_get_size(2);
|
| mono_size = opus_encoder_get_size(1);
|
| @@ -747,18 +770,20 @@ static int opus_multistream_encode_native
|
| surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in);
|
| }
|
|
|
| - if (max_data_bytes < 4*st->layout.nb_streams-1)
|
| - {
|
| - RESTORE_STACK;
|
| - return OPUS_BUFFER_TOO_SMALL;
|
| - }
|
| -
|
| /* Compute bitrate allocation between streams (this could be a lot better) */
|
| - surround_rate_allocation(st, bitrates, frame_size);
|
| + rate_sum = surround_rate_allocation(st, bitrates, frame_size);
|
|
|
| if (!vbr)
|
| - max_data_bytes = IMIN(max_data_bytes, 3*st->bitrate_bps/(3*8*Fs/frame_size));
|
| -
|
| + {
|
| + if (st->bitrate_bps == OPUS_AUTO)
|
| + {
|
| + max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
|
| + } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
|
| + {
|
| + max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
|
| + 3*st->bitrate_bps/(3*8*Fs/frame_size)));
|
| + }
|
| + }
|
| ptr = (char*)st + align(sizeof(OpusMSEncoder));
|
| for (s=0;s<st->layout.nb_streams;s++)
|
| {
|
| @@ -843,13 +868,15 @@ static int opus_multistream_encode_native
|
| opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
|
| /* number of bytes left (+Toc) */
|
| curr_max = max_data_bytes - tot_size;
|
| - /* Reserve three bytes for the last stream and four for the others */
|
| - curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
|
| + /* Reserve one byte for the last stream and two for the others */
|
| + curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-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;
|
| if (!vbr && s == st->layout.nb_streams-1)
|
| opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
|
| len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
|
| - pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix);
|
| + pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
|
| if (len<0)
|
| {
|
| RESTORE_STACK;
|
| @@ -922,7 +949,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);
|
| + pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
|
| }
|
|
|
| #ifndef DISABLE_FLOAT_API
|
| @@ -935,7 +962,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);
|
| + pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
|
| }
|
| #endif
|
|
|
| @@ -951,7 +978,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);
|
| + pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
|
| }
|
|
|
| int opus_multistream_encode(
|
| @@ -963,7 +990,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);
|
| + pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
|
| }
|
| #endif
|
|
|
|
|