From 9845bdde8dc3005185dc43c493380858d717596a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Thu, 5 Jan 2017 22:35:39 +0100 Subject: [PATCH] opus: Update to upstream libopus 1.1.3 --- thirdparty/README.md | 4 +- thirdparty/opus/COPYING | 40 +++-- thirdparty/opus/analysis.c | 13 +- thirdparty/opus/opus.c | 8 +- thirdparty/opus/opus/opus.h | 2 +- thirdparty/opus/opus/opus_defines.h | 2 +- thirdparty/opus/opus/opus_multistream.h | 8 +- thirdparty/opus/opus_encoder.c | 51 +++--- thirdparty/opus/opus_multistream_encoder.c | 183 ++++++++++++++++++--- thirdparty/opus/repacketizer.c | 4 +- 10 files changed, 238 insertions(+), 77 deletions(-) diff --git a/thirdparty/README.md b/thirdparty/README.md index f79a76867b..5b06abf25b 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -141,7 +141,7 @@ changes are marked with `// -- GODOT --` comments. ## openssl - Upstream: https://www.openssl.org -- Version: 1.2.0h +- Version: 1.0.2h - License: OpenSSL license / BSD-like Files extracted from the upstream source: @@ -152,7 +152,7 @@ TODO. ## opus - Upstream: https://opus-codec.org -- Version: 1.1.2 (opus) and 0.7 (opusfile) +- Version: 1.1.3 (opus) and 0.7 (opusfile) - License: BSD-3-Clause Files extracted from upstream source: diff --git a/thirdparty/opus/COPYING b/thirdparty/opus/COPYING index 7b53d665df..9c739c34a3 100644 --- a/thirdparty/opus/COPYING +++ b/thirdparty/opus/COPYING @@ -1,4 +1,7 @@ -Copyright (c) 1994-2013 Xiph.Org Foundation and contributors +Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic, + Jean-Marc Valin, Timothy B. Terriberry, + CSIRO, Gregory Maxwell, Mark Borgerding, + Erik de Castro Lopo Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -11,18 +14,31 @@ notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -- Neither the name of the Xiph.Org Foundation nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific contributors, may be used to endorse or promote +products derived from this software without specific prior written +permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Opus is subject to the royalty-free patent licenses which are +specified at: + +Xiph.Org Foundation: +https://datatracker.ietf.org/ipr/1524/ + +Microsoft Corporation: +https://datatracker.ietf.org/ipr/1914/ + +Broadcom Corporation: +https://datatracker.ietf.org/ipr/1526/ diff --git a/thirdparty/opus/analysis.c b/thirdparty/opus/analysis.c index 360ebcc8dd..663431a436 100644 --- a/thirdparty/opus/analysis.c +++ b/thirdparty/opus/analysis.c @@ -540,17 +540,14 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt /* Instantaneous probability of speech and music, with beta pre-applied. */ float speech0; float music0; + float p, q; /* One transition every 3 minutes of active audio */ tau = .00005f*frame_probs[1]; - beta = .05f; - if (1) { - /* Adapt beta based on how "unexpected" the new prob is */ - float p, q; - p = MAX16(.05f,MIN16(.95f,frame_probs[0])); - q = MAX16(.05f,MIN16(.95f,tonal->music_prob)); - beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p)); - } + /* Adapt beta based on how "unexpected" the new prob is */ + p = MAX16(.05f,MIN16(.95f,frame_probs[0])); + q = MAX16(.05f,MIN16(.95f,tonal->music_prob)); + beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p)); /* p0 and p1 are the probabilities of speech and music at this frame using only information from previous frame and applying the state transition model */ diff --git a/thirdparty/opus/opus.c b/thirdparty/opus/opus.c index e9ce93b308..f76f125cfa 100644 --- a/thirdparty/opus/opus.c +++ b/thirdparty/opus/opus.c @@ -104,6 +104,10 @@ OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem) /* Compute a such that maxval + a*maxval^2 = 1 */ a=(maxval-1)/(maxval*maxval); + /* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math + does not cause output values larger than +/-1, but small enough not + to matter even for 24-bit output. */ + a += a*2.4e-7; if (x[i*C]>0) a = -a; /* Apply soft clipping */ @@ -201,8 +205,10 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, opus_int32 pad = 0; const unsigned char *data0 = data; - if (size==NULL) + if (size==NULL || len<0) return OPUS_BAD_ARG; + if (len==0) + return OPUS_INVALID_PACKET; framesize = opus_packet_get_samples_per_frame(data, 48000); diff --git a/thirdparty/opus/opus/opus.h b/thirdparty/opus/opus/opus.h index b0bdf6f2df..5be73ddf4e 100644 --- a/thirdparty/opus/opus/opus.h +++ b/thirdparty/opus/opus/opus.h @@ -142,7 +142,7 @@ extern "C" { * * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet. * The return value can be negative, which indicates that an error has occurred. If the return value - * is 1 byte, then the packet does not need to be transmitted (DTX). + * is 2 bytes or less, then the packet does not need to be transmitted (DTX). * * Once the encoder state if no longer needed, it can be destroyed with * diff --git a/thirdparty/opus/opus/opus_defines.h b/thirdparty/opus/opus/opus_defines.h index 647ed5d6f2..315412dd1d 100644 --- a/thirdparty/opus/opus/opus_defines.h +++ b/thirdparty/opus/opus/opus_defines.h @@ -65,7 +65,7 @@ extern "C" { #ifndef OPUS_EXPORT # if defined(WIN32) -# ifdef OPUS_BUILD +# if defined(OPUS_BUILD) && defined(DLL_EXPORT) # define OPUS_EXPORT __declspec(dllexport) # else # define OPUS_EXPORT diff --git a/thirdparty/opus/opus/opus_multistream.h b/thirdparty/opus/opus/opus_multistream.h index 47e03900bd..3622e009fb 100644 --- a/thirdparty/opus/opus/opus_multistream.h +++ b/thirdparty/opus/opus/opus_multistream.h @@ -110,10 +110,10 @@ extern "C" { * packets produced by the encoder. Some basic information, such as packet * duration, can be computed without any special negotiation. * - * The format for multistream Opus packets is defined in the - * Ogg - * encapsulation specification and is based on the self-delimited Opus - * framing described in Appendix B of RFC 6716. + * The format for multistream Opus packets is defined in + * RFC 7845 + * and is based on the self-delimited Opus framing described in Appendix B of + * RFC 6716. * Normal Opus packets are just a degenerate case of multistream Opus packets, * and can be encoded or decoded with the multistream API by setting * streams to 1 when initializing the encoder or diff --git a/thirdparty/opus/opus_encoder.c b/thirdparty/opus/opus_encoder.c index a7e19127d6..9a516a884a 100644 --- a/thirdparty/opus/opus_encoder.c +++ b/thirdparty/opus/opus_encoder.c @@ -860,9 +860,6 @@ opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem) { - opus_val16 corr; - opus_val16 ldiff; - opus_val16 width; opus_val32 xx, xy, yy; opus_val16 sqrt_xx, sqrt_yy; opus_val16 qrrt_xx, qrrt_yy; @@ -871,9 +868,12 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3 opus_val16 short_alpha; frame_rate = Fs/frame_size; - short_alpha = Q15ONE - 25*Q15ONE/IMAX(50,frame_rate); + short_alpha = Q15ONE - MULT16_16(25, Q15ONE)/IMAX(50,frame_rate); xx=xy=yy=0; - for (i=0;iYY = MAX32(0, mem->YY); if (MAX32(mem->XX, mem->YY)>QCONST16(8e-4f, 18)) { + opus_val16 corr; + opus_val16 ldiff; + opus_val16 width; sqrt_xx = celt_sqrt(mem->XX); sqrt_yy = celt_sqrt(mem->YY); qrrt_xx = celt_sqrt(sqrt_xx); @@ -920,19 +923,15 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3 mem->XY = MIN32(mem->XY, sqrt_xx*sqrt_yy); corr = SHR32(frac_div32(mem->XY,EPSILON+MULT16_16(sqrt_xx,sqrt_yy)),16); /* Approximate loudness difference */ - ldiff = Q15ONE*ABS16(qrrt_xx-qrrt_yy)/(EPSILON+qrrt_xx+qrrt_yy); + ldiff = MULT16_16(Q15ONE, ABS16(qrrt_xx-qrrt_yy))/(EPSILON+qrrt_xx+qrrt_yy); width = MULT16_16_Q15(celt_sqrt(QCONST32(1.f,30)-MULT16_16(corr,corr)), ldiff); /* Smoothing over one second */ mem->smoothed_width += (width-mem->smoothed_width)/frame_rate; /* Peak follower */ mem->max_follower = MAX16(mem->max_follower-QCONST16(.02f,15)/frame_rate, mem->smoothed_width); - } else { - width = 0; - corr=Q15ONE; - ldiff=0; } /*printf("%f %f %f %f %f ", corr/(float)Q15ONE, ldiff/(float)Q15ONE, width/(float)Q15ONE, mem->smoothed_width/(float)Q15ONE, mem->max_follower/(float)Q15ONE);*/ - return EXTRACT16(MIN32(Q15ONE,20*mem->max_follower)); + return EXTRACT16(MIN32(Q15ONE, MULT16_16(20, mem->max_follower))); } opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size, @@ -1050,6 +1049,16 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes); frame_rate = st->Fs/frame_size; + if (!st->use_vbr) + { + int cbrBytes; + /* Multiply by 3 to make sure the division is exact. */ + int frame_rate3 = 3*st->Fs/frame_size; + /* We need to make sure that "int" values always fit in 16 bits. */ + cbrBytes = IMIN( (3*st->bitrate_bps/8 + frame_rate3/2)/frame_rate3, max_data_bytes); + st->bitrate_bps = cbrBytes*(opus_int32)frame_rate3*8/3; + max_data_bytes = cbrBytes; + } if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8 || (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400))) { @@ -1066,18 +1075,18 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ bw=OPUS_BANDWIDTH_WIDEBAND; else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND) bw=OPUS_BANDWIDTH_NARROWBAND; - else if (bw<=OPUS_BANDWIDTH_SUPERWIDEBAND) + else if (tocmode==MODE_HYBRID&&bw<=OPUS_BANDWIDTH_SUPERWIDEBAND) bw=OPUS_BANDWIDTH_SUPERWIDEBAND; data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels); + ret = 1; + if (!st->use_vbr) + { + ret = opus_packet_pad(data, ret, max_data_bytes); + if (ret == OPUS_OK) + ret = max_data_bytes; + } RESTORE_STACK; - return 1; - } - if (!st->use_vbr) - { - int cbrBytes; - cbrBytes = IMIN( (st->bitrate_bps + 4*frame_rate)/(8*frame_rate) , max_data_bytes); - st->bitrate_bps = cbrBytes * (8*frame_rate); - max_data_bytes = cbrBytes; + return ret; } max_rate = frame_rate*max_data_bytes*8; @@ -1513,7 +1522,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ celt_rate = total_bitRate - st->silk_mode.bitRate; HB_gain_ref = (curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND) ? 3000 : 3600; HB_gain = SHL32((opus_val32)celt_rate, 9) / SHR32((opus_val32)celt_rate + st->stream_channels * HB_gain_ref, 6); - HB_gain = HB_gain < Q15ONE*6/7 ? HB_gain + Q15ONE/7 : Q15ONE; + HB_gain = HB_gain < (opus_val32)Q15ONE*6/7 ? HB_gain + Q15ONE/7 : Q15ONE; } } else { /* SILK gets all bits */ diff --git a/thirdparty/opus/opus_multistream_encoder.c b/thirdparty/opus/opus_multistream_encoder.c index 9e85773573..e722e31ab8 100644 --- a/thirdparty/opus/opus_multistream_encoder.c +++ b/thirdparty/opus/opus_multistream_encoder.c @@ -70,13 +70,22 @@ typedef void (*opus_copy_channel_in_func)( 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; - int surround; + MappingType mapping_type; opus_int32 bitrate_bps; float subframe_mem[3]; /* Encoder states go here */ @@ -242,6 +251,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b upsample = resampling_factor(rate); frame_size = len*upsample; + /* LM = log2(frame_size / 120) */ for (LM=0;LMmaxLM;LM++) if (celt_mode->shortMdctSize<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 (!surround) + if (mapping_type != MAPPING_TYPE_SURROUND) st->lfe_stream = -1; st->bitrate_bps = OPUS_AUTO; st->application = application; @@ -463,12 +478,12 @@ static int opus_multistream_encoder_init_impl( if(ret!=OPUS_OK)return ret; ptr += align(mono_size); } - if (surround) + if (mapping_type == MAPPING_TYPE_SURROUND) { OPUS_CLEAR(ms_get_preemph_mem(st), channels); OPUS_CLEAR(ms_get_window_mem(st), channels*120); } - st->surround = surround; + st->mapping_type = mapping_type; return OPUS_OK; } @@ -482,7 +497,9 @@ int opus_multistream_encoder_init( int application ) { - return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0); + return opus_multistream_encoder_init_impl(st, Fs, channels, streams, + coupled_streams, mapping, + application, MAPPING_TYPE_NONE); } int opus_multistream_surround_encoder_init( @@ -496,6 +513,8 @@ int opus_multistream_surround_encoder_init( int application ) { + MappingType mapping_type; + if ((channels>255) || (channels<1)) return OPUS_BAD_ARG; st->lfe_stream = -1; @@ -530,10 +549,32 @@ int opus_multistream_surround_encoder_init( *coupled_streams=0; for(i=0;i2&&mapping_family==1); + + if (channels>2 && mapping_family==1) { + mapping_type = MAPPING_TYPE_SURROUND; +#ifdef ENABLE_EXPERIMENTAL_AMBISONICS + } else if (mapping_family==254) + { + mapping_type = MAPPING_TYPE_AMBISONICS; +#endif + } else + { + mapping_type = MAPPING_TYPE_NONE; + } + return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, + *coupled_streams, mapping, + application, mapping_type); } OpusMSEncoder *opus_multistream_encoder_create( @@ -618,24 +659,19 @@ OpusMSEncoder *opus_multistream_surround_encoder_create( return st; } -static opus_int32 surround_rate_allocation( +static void surround_rate_allocation( OpusMSEncoder *st, opus_int32 *rate, - int frame_size + int frame_size, + opus_int32 Fs ) { int i; opus_int32 channel_rate; - opus_int32 Fs; - char *ptr; int stream_offset; 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)); if (st->bitrate_bps > st->layout.nb_channels*40000) stream_offset = 20000; @@ -688,6 +724,88 @@ static opus_int32 surround_rate_allocation( rate[i] = stream_offset+channel_rate; else rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8); + } +} + +#ifdef ENABLE_EXPERIMENTAL_AMBISONICS +static void ambisonics_rate_allocation( + OpusMSEncoder *st, + opus_int32 *rate, + int frame_size, + opus_int32 Fs + ) +{ + int i; + int non_mono_rate; + int total_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; + + if (st->bitrate_bps==OPUS_AUTO) + { + total_rate = num_channels * (20000 + st->layout.nb_streams*(Fs+60*Fs/frame_size)); + } 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) + { + 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;ilayout.nb_streams;i++) + { + rate[i] = non_mono_rate; + } +} +#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */ + +static opus_int32 rate_allocation( + OpusMSEncoder *st, + opus_int32 *rate, + int frame_size + ) +{ + int i; + opus_int32 rate_sum=0; + opus_int32 Fs; + char *ptr; + + 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); + } + + for (i=0;ilayout.nb_streams;i++) + { rate[i] = IMAX(rate[i], 500); rate_sum += rate[i]; } @@ -730,7 +848,7 @@ static int opus_multistream_encode_native opus_int32 smallest_packet; ALLOC_STACK; - if (st->surround) + if (st->mapping_type == MAPPING_TYPE_SURROUND) { preemph_mem = ms_get_preemph_mem(st); mem = ms_get_window_mem(st); @@ -784,13 +902,13 @@ static int opus_multistream_encode_native mono_size = opus_encoder_get_size(1); ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16); - if (st->surround) + if (st->mapping_type == MAPPING_TYPE_SURROUND) { surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch); } /* Compute bitrate allocation between streams (this could be a lot better) */ - rate_sum = surround_rate_allocation(st, bitrates, frame_size); + rate_sum = rate_allocation(st, bitrates, frame_size); if (!vbr) { @@ -813,7 +931,7 @@ static int opus_multistream_encode_native else ptr += align(mono_size); opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s])); - if (st->surround) + if (st->mapping_type == MAPPING_TYPE_SURROUND) { opus_int32 equiv_rate; equiv_rate = st->bitrate_bps; @@ -834,6 +952,11 @@ 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)); @@ -845,6 +968,7 @@ static int opus_multistream_encode_native int len; int curr_max; int c1, c2; + int ret; opus_repacketizer_init(&rp); enc = (OpusEncoder*)ptr; @@ -859,7 +983,7 @@ static int opus_multistream_encode_native (*copy_channel_in)(buf+1, 2, pcm, st->layout.nb_channels, right, frame_size); ptr += align(coupled_size); - if (st->surround) + if (st->mapping_type == MAPPING_TYPE_SURROUND) { for (i=0;i<21;i++) { @@ -875,7 +999,7 @@ static int opus_multistream_encode_native (*copy_channel_in)(buf, 1, pcm, st->layout.nb_channels, chan, frame_size); ptr += align(mono_size); - if (st->surround) + if (st->mapping_type == MAPPING_TYPE_SURROUND) { for (i=0;i<21;i++) bandLogE[i] = bandSMR[21*chan+i]; @@ -883,7 +1007,7 @@ static int opus_multistream_encode_native c1 = chan; c2 = -1; } - if (st->surround) + if (st->mapping_type == MAPPING_TYPE_SURROUND) opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE)); /* number of bytes left (+Toc) */ curr_max = max_data_bytes - tot_size; @@ -904,7 +1028,14 @@ static int opus_multistream_encode_native /* We need to use the repacketizer to add the self-delimiting lengths while taking into account the fact that the encoder can now return more than one frame at a time (e.g. 60 ms CELT-only) */ - opus_repacketizer_cat(&rp, tmp_data, len); + ret = opus_repacketizer_cat(&rp, tmp_data, len); + /* If the opus_repacketizer_cat() fails, then something's seriously wrong + with the encoder. */ + if (ret != OPUS_OK) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1); data += len; @@ -1183,7 +1314,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) { int s; st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0; - if (st->surround) + if (st->mapping_type == MAPPING_TYPE_SURROUND) { OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels); OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120); diff --git a/thirdparty/opus/repacketizer.c b/thirdparty/opus/repacketizer.c index f27e9ab958..c80ee7f001 100644 --- a/thirdparty/opus/repacketizer.c +++ b/thirdparty/opus/repacketizer.c @@ -249,7 +249,9 @@ int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len) opus_repacketizer_init(&rp); /* Moving payload to the end of the packet so we can do in-place padding */ OPUS_MOVE(data+new_len-len, data, len); - opus_repacketizer_cat(&rp, data+new_len-len, len); + ret = opus_repacketizer_cat(&rp, data+new_len-len, len); + if (ret != OPUS_OK) + return ret; ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1); if (ret > 0) return OPUS_OK;