Remove large multistream stack buffers.
This avoids allocating any buffers on the stack that depend on the total channel count. Such buffers could easily exceed the size of the NONTHREADSAFE_PSEUDOSTACK. It also checks the frame_size argument in both the encoder and decoder to avoid allocating large stack buffers for opus_encode() calls that would fail anyway or opus_decode() calls that would never use all that space anyway.
This commit is contained in:
parent
84dd1cf9b7
commit
a40689e6ef
4 changed files with 230 additions and 80 deletions
|
@ -111,7 +111,8 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** These are the actual Encoder CTL ID numbers.
|
/** These are the actual Encoder CTL ID numbers.
|
||||||
* They should not be used directly by applications. */
|
* They should not be used directly by applications.
|
||||||
|
* In general, SETs should be even and GETs should be odd.*/
|
||||||
#define OPUS_SET_APPLICATION_REQUEST 4000
|
#define OPUS_SET_APPLICATION_REQUEST 4000
|
||||||
#define OPUS_GET_APPLICATION_REQUEST 4001
|
#define OPUS_GET_APPLICATION_REQUEST 4001
|
||||||
#define OPUS_SET_BITRATE_REQUEST 4002
|
#define OPUS_SET_BITRATE_REQUEST 4002
|
||||||
|
@ -138,6 +139,7 @@ extern "C" {
|
||||||
#define OPUS_GET_SIGNAL_REQUEST 4025
|
#define OPUS_GET_SIGNAL_REQUEST 4025
|
||||||
#define OPUS_GET_LOOKAHEAD_REQUEST 4027
|
#define OPUS_GET_LOOKAHEAD_REQUEST 4027
|
||||||
/* #define OPUS_RESET_STATE 4028 */
|
/* #define OPUS_RESET_STATE 4028 */
|
||||||
|
#define OPUS_GET_SAMPLE_RATE_REQUEST 4029
|
||||||
#define OPUS_GET_FINAL_RANGE_REQUEST 4031
|
#define OPUS_GET_FINAL_RANGE_REQUEST 4031
|
||||||
#define OPUS_GET_PITCH_REQUEST 4033
|
#define OPUS_GET_PITCH_REQUEST 4033
|
||||||
#define OPUS_SET_GAIN_REQUEST 4034
|
#define OPUS_SET_GAIN_REQUEST 4034
|
||||||
|
@ -422,6 +424,14 @@ extern "C" {
|
||||||
* @hideinitializer */
|
* @hideinitializer */
|
||||||
#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
|
#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
|
||||||
|
|
||||||
|
/** Gets the sampling rate the encoder or decoder was initialized with.
|
||||||
|
* This simply returns the <code>Fs</code> value passed to opus_encoder_init()
|
||||||
|
* or opus_decoder_init().
|
||||||
|
* @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
|
||||||
|
* @hideinitializer
|
||||||
|
*/
|
||||||
|
#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
|
||||||
|
|
||||||
/** Gets the total samples of delay added by the entire codec.
|
/** Gets the total samples of delay added by the entire codec.
|
||||||
* This can be queried by the encoder and then the provided number of samples can be
|
* This can be queried by the encoder and then the provided number of samples can be
|
||||||
* skipped on from the start of the decoder's output to provide time aligned input
|
* skipped on from the start of the decoder's output to provide time aligned input
|
||||||
|
|
|
@ -228,6 +228,8 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
|
||||||
RESTORE_STACK;
|
RESTORE_STACK;
|
||||||
return OPUS_BUFFER_TOO_SMALL;
|
return OPUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
/* Limit frame_size to avoid excessive stack allocations. */
|
||||||
|
frame_size = IMIN(frame_size, st->Fs/25*3);
|
||||||
/* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
|
/* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
|
||||||
if (len<=1)
|
if (len<=1)
|
||||||
{
|
{
|
||||||
|
@ -856,6 +858,17 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
|
||||||
st->frame_size = st->Fs/400;
|
st->frame_size = st->Fs/400;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OPUS_GET_SAMPLE_RATE_REQUEST:
|
||||||
|
{
|
||||||
|
opus_int32 *value = va_arg(ap, opus_int32*);
|
||||||
|
if (value==NULL)
|
||||||
|
{
|
||||||
|
ret = OPUS_BAD_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*value = st->Fs;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case OPUS_GET_PITCH_REQUEST:
|
case OPUS_GET_PITCH_REQUEST:
|
||||||
{
|
{
|
||||||
opus_int32 *value = va_arg(ap, opus_int32*);
|
opus_int32 *value = va_arg(ap, opus_int32*);
|
||||||
|
|
|
@ -1531,6 +1531,17 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
|
||||||
*value += st->delay_compensation;
|
*value += st->delay_compensation;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OPUS_GET_SAMPLE_RATE_REQUEST:
|
||||||
|
{
|
||||||
|
opus_int32 *value = va_arg(ap, opus_int32*);
|
||||||
|
if (value==NULL)
|
||||||
|
{
|
||||||
|
ret = OPUS_BAD_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*value = st->Fs;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case OPUS_GET_FINAL_RANGE_REQUEST:
|
case OPUS_GET_FINAL_RANGE_REQUEST:
|
||||||
{
|
{
|
||||||
opus_uint32 *value = va_arg(ap, opus_uint32*);
|
opus_uint32 *value = va_arg(ap, opus_uint32*);
|
||||||
|
|
|
@ -55,7 +55,6 @@ struct OpusMSDecoder {
|
||||||
/* Decoder states go here */
|
/* Decoder states go here */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
#define opus_encode_native opus_encode
|
#define opus_encode_native opus_encode
|
||||||
#else
|
#else
|
||||||
|
@ -221,24 +220,31 @@ OpusMSEncoder *opus_multistream_encoder_create(
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
/* Max size in case the encoder decides to return three frames */
|
/* Max size in case the encoder decides to return three frames */
|
||||||
#define MS_FRAME_TMP (3*1275+7)
|
#define MS_FRAME_TMP (3*1275+7)
|
||||||
#ifdef FIXED_POINT
|
static int opus_multistream_encode_native
|
||||||
int opus_multistream_encode
|
|
||||||
#else
|
|
||||||
int opus_multistream_encode_float
|
|
||||||
#endif
|
|
||||||
(
|
(
|
||||||
OpusMSEncoder *st,
|
OpusMSEncoder *st,
|
||||||
const opus_val16 *pcm,
|
opus_copy_channel_in_func copy_channel_in,
|
||||||
|
const void *pcm,
|
||||||
int frame_size,
|
int frame_size,
|
||||||
unsigned char *data,
|
unsigned char *data,
|
||||||
opus_int32 max_data_bytes
|
opus_int32 max_data_bytes
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
opus_int32 Fs;
|
||||||
int coupled_size;
|
int coupled_size;
|
||||||
int mono_size;
|
int mono_size;
|
||||||
int s, i;
|
int s;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int tot_size;
|
int tot_size;
|
||||||
VARDECL(opus_val16, buf);
|
VARDECL(opus_val16, buf);
|
||||||
|
@ -246,8 +252,18 @@ int opus_multistream_encode_float
|
||||||
OpusRepacketizer rp;
|
OpusRepacketizer rp;
|
||||||
ALLOC_STACK;
|
ALLOC_STACK;
|
||||||
|
|
||||||
ALLOC(buf, 2*frame_size, opus_val16);
|
|
||||||
ptr = (char*)st + align(sizeof(OpusMSEncoder));
|
ptr = (char*)st + align(sizeof(OpusMSEncoder));
|
||||||
|
opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
ALLOC(buf, 2*frame_size, opus_val16);
|
||||||
coupled_size = opus_encoder_get_size(2);
|
coupled_size = opus_encoder_get_size(2);
|
||||||
mono_size = opus_encoder_get_size(1);
|
mono_size = opus_encoder_get_size(1);
|
||||||
|
|
||||||
|
@ -271,16 +287,15 @@ int opus_multistream_encode_float
|
||||||
int left, right;
|
int left, right;
|
||||||
left = get_left_channel(&st->layout, s, -1);
|
left = get_left_channel(&st->layout, s, -1);
|
||||||
right = get_right_channel(&st->layout, s, -1);
|
right = get_right_channel(&st->layout, s, -1);
|
||||||
for (i=0;i<frame_size;i++)
|
(*copy_channel_in)(buf, 2,
|
||||||
{
|
pcm, st->layout.nb_channels, left, frame_size);
|
||||||
buf[2*i] = pcm[st->layout.nb_channels*i+left];
|
(*copy_channel_in)(buf+1, 2,
|
||||||
buf[2*i+1] = pcm[st->layout.nb_channels*i+right];
|
pcm, st->layout.nb_channels, right, frame_size);
|
||||||
}
|
|
||||||
ptr += align(coupled_size);
|
ptr += align(coupled_size);
|
||||||
} else {
|
} else {
|
||||||
int chan = get_mono_channel(&st->layout, s, -1);
|
int chan = get_mono_channel(&st->layout, s, -1);
|
||||||
for (i=0;i<frame_size;i++)
|
(*copy_channel_in)(buf, 1,
|
||||||
buf[i] = pcm[st->layout.nb_channels*i+chan];
|
pcm, st->layout.nb_channels, chan, frame_size);
|
||||||
ptr += align(mono_size);
|
ptr += align(mono_size);
|
||||||
}
|
}
|
||||||
/* number of bytes left (+Toc) */
|
/* number of bytes left (+Toc) */
|
||||||
|
@ -307,7 +322,60 @@ int opus_multistream_encode_float
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(DISABLE_FLOAT_API)
|
||||||
|
static void opus_copy_channel_in_float(
|
||||||
|
opus_val16 *dst,
|
||||||
|
int dst_stride,
|
||||||
|
const void *src,
|
||||||
|
int src_stride,
|
||||||
|
int src_channel,
|
||||||
|
int frame_size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const float *float_src;
|
||||||
|
int i;
|
||||||
|
float_src = (const float *)src;
|
||||||
|
for (i=0;i<frame_size;i++)
|
||||||
|
#if defined(FIXED_POINT)
|
||||||
|
dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
|
||||||
|
#else
|
||||||
|
dst[i*dst_stride] = float_src[i*src_stride+src_channel];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void opus_copy_channel_in_short(
|
||||||
|
opus_val16 *dst,
|
||||||
|
int dst_stride,
|
||||||
|
const void *src,
|
||||||
|
int src_stride,
|
||||||
|
int src_channel,
|
||||||
|
int frame_size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const opus_int16 *short_src;
|
||||||
|
int i;
|
||||||
|
short_src = (const opus_int16 *)src;
|
||||||
|
for (i=0;i<frame_size;i++)
|
||||||
|
#if defined(FIXED_POINT)
|
||||||
|
dst[i*dst_stride] = short_src[i*src_stride+src_channel];
|
||||||
|
#else
|
||||||
|
dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
|
int opus_multistream_encode(
|
||||||
|
OpusMSEncoder *st,
|
||||||
|
const opus_val16 *pcm,
|
||||||
|
int frame_size,
|
||||||
|
unsigned char *data,
|
||||||
|
opus_int32 max_data_bytes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return opus_multistream_encode_native(st, opus_copy_channel_in_short,
|
||||||
|
pcm, frame_size, data, max_data_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_FLOAT_API
|
#ifndef DISABLE_FLOAT_API
|
||||||
int opus_multistream_encode_float(
|
int opus_multistream_encode_float(
|
||||||
|
@ -318,22 +386,26 @@ int opus_multistream_encode_float(
|
||||||
opus_int32 max_data_bytes
|
opus_int32 max_data_bytes
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int i, ret;
|
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
|
||||||
VARDECL(opus_int16, in);
|
pcm, frame_size, data, max_data_bytes);
|
||||||
ALLOC_STACK;
|
|
||||||
|
|
||||||
ALLOC(in, frame_size*st->layout.nb_channels, opus_int16);
|
|
||||||
|
|
||||||
for (i=0;i<frame_size*st->layout.nb_channels;i++)
|
|
||||||
in[i] = FLOAT2INT16(pcm[i]);
|
|
||||||
ret = opus_multistream_encode(st, in, frame_size, data, max_data_bytes);
|
|
||||||
RESTORE_STACK;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
int opus_multistream_encode_float
|
||||||
|
(
|
||||||
|
OpusMSEncoder *st,
|
||||||
|
const opus_val16 *pcm,
|
||||||
|
int frame_size,
|
||||||
|
unsigned char *data,
|
||||||
|
opus_int32 max_data_bytes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
|
||||||
|
pcm, frame_size, data, max_data_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
int opus_multistream_encode(
|
int opus_multistream_encode(
|
||||||
OpusMSEncoder *st,
|
OpusMSEncoder *st,
|
||||||
const opus_int16 *pcm,
|
const opus_int16 *pcm,
|
||||||
|
@ -342,19 +414,9 @@ int opus_multistream_encode(
|
||||||
opus_int32 max_data_bytes
|
opus_int32 max_data_bytes
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int i, ret;
|
return opus_multistream_encode_native(st, opus_copy_channel_in_short,
|
||||||
VARDECL(float, in);
|
pcm, frame_size, data, max_data_bytes);
|
||||||
ALLOC_STACK;
|
|
||||||
|
|
||||||
ALLOC(in, frame_size*st->layout.nb_channels, float);
|
|
||||||
|
|
||||||
for (i=0;i<frame_size*st->layout.nb_channels;i++)
|
|
||||||
in[i] = (1.f/32768.f)*pcm[i];
|
|
||||||
ret = opus_multistream_encode_float(st, in, frame_size, data, max_data_bytes);
|
|
||||||
RESTORE_STACK;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
|
int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
|
||||||
|
@ -419,6 +481,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
|
||||||
case OPUS_GET_VBR_CONSTRAINT_REQUEST:
|
case OPUS_GET_VBR_CONSTRAINT_REQUEST:
|
||||||
case OPUS_GET_SIGNAL_REQUEST:
|
case OPUS_GET_SIGNAL_REQUEST:
|
||||||
case OPUS_GET_LOOKAHEAD_REQUEST:
|
case OPUS_GET_LOOKAHEAD_REQUEST:
|
||||||
|
case OPUS_GET_SAMPLE_RATE_REQUEST:
|
||||||
case OPUS_GET_INBAND_FEC_REQUEST:
|
case OPUS_GET_INBAND_FEC_REQUEST:
|
||||||
{
|
{
|
||||||
OpusEncoder *enc;
|
OpusEncoder *enc;
|
||||||
|
@ -604,23 +667,37 @@ OpusMSDecoder *opus_multistream_decoder_create(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (*opus_copy_channel_out_func)(
|
||||||
|
void *dst,
|
||||||
|
int dst_stride,
|
||||||
|
int dst_channel,
|
||||||
|
const opus_val16 *src,
|
||||||
|
int src_stride,
|
||||||
|
int frame_size
|
||||||
|
);
|
||||||
|
|
||||||
static int opus_multistream_decode_native(
|
static int opus_multistream_decode_native(
|
||||||
OpusMSDecoder *st,
|
OpusMSDecoder *st,
|
||||||
const unsigned char *data,
|
const unsigned char *data,
|
||||||
opus_int32 len,
|
opus_int32 len,
|
||||||
opus_val16 *pcm,
|
void *pcm,
|
||||||
|
opus_copy_channel_out_func copy_channel_out,
|
||||||
int frame_size,
|
int frame_size,
|
||||||
int decode_fec
|
int decode_fec
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
opus_int32 Fs;
|
||||||
int coupled_size;
|
int coupled_size;
|
||||||
int mono_size;
|
int mono_size;
|
||||||
int s, i, c;
|
int s, c;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int do_plc=0;
|
int do_plc=0;
|
||||||
VARDECL(opus_val16, buf);
|
VARDECL(opus_val16, buf);
|
||||||
ALLOC_STACK;
|
ALLOC_STACK;
|
||||||
|
|
||||||
|
/* Limit frame_size to avoid excessive stack allocations. */
|
||||||
|
opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
|
||||||
|
frame_size = IMIN(frame_size, Fs/25*3);
|
||||||
ALLOC(buf, 2*frame_size, opus_val16);
|
ALLOC(buf, 2*frame_size, opus_val16);
|
||||||
ptr = (char*)st + align(sizeof(OpusMSDecoder));
|
ptr = (char*)st + align(sizeof(OpusMSDecoder));
|
||||||
coupled_size = opus_decoder_get_size(2);
|
coupled_size = opus_decoder_get_size(2);
|
||||||
|
@ -672,16 +749,16 @@ static int opus_multistream_decode_native(
|
||||||
/* Copy "left" audio to the channel(s) where it belongs */
|
/* Copy "left" audio to the channel(s) where it belongs */
|
||||||
while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
|
while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
|
||||||
{
|
{
|
||||||
for (i=0;i<frame_size;i++)
|
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
|
||||||
pcm[st->layout.nb_channels*i+chan] = buf[2*i];
|
buf, 2, frame_size);
|
||||||
prev = chan;
|
prev = chan;
|
||||||
}
|
}
|
||||||
prev = -1;
|
prev = -1;
|
||||||
/* Copy "right" audio to the channel(s) where it belongs */
|
/* Copy "right" audio to the channel(s) where it belongs */
|
||||||
while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
|
while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
|
||||||
{
|
{
|
||||||
for (i=0;i<frame_size;i++)
|
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
|
||||||
pcm[st->layout.nb_channels*i+chan] = buf[2*i+1];
|
buf+1, 2, frame_size);
|
||||||
prev = chan;
|
prev = chan;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -690,8 +767,8 @@ static int opus_multistream_decode_native(
|
||||||
/* Copy audio to the channel(s) where it belongs */
|
/* Copy audio to the channel(s) where it belongs */
|
||||||
while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
|
while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
|
||||||
{
|
{
|
||||||
for (i=0;i<frame_size;i++)
|
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
|
||||||
pcm[st->layout.nb_channels*i+chan] = buf[i];
|
buf, 1, frame_size);
|
||||||
prev = chan;
|
prev = chan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -701,14 +778,74 @@ static int opus_multistream_decode_native(
|
||||||
{
|
{
|
||||||
if (st->layout.mapping[c] == 255)
|
if (st->layout.mapping[c] == 255)
|
||||||
{
|
{
|
||||||
for (i=0;i<frame_size;i++)
|
(*copy_channel_out)(pcm, st->layout.nb_channels, c,
|
||||||
pcm[st->layout.nb_channels*i+c] = 0;
|
NULL, 0, frame_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RESTORE_STACK;
|
RESTORE_STACK;
|
||||||
return frame_size;
|
return frame_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(DISABLE_FLOAT_API)
|
||||||
|
static void opus_copy_channel_out_float(
|
||||||
|
void *dst,
|
||||||
|
int dst_stride,
|
||||||
|
int dst_channel,
|
||||||
|
const opus_val16 *src,
|
||||||
|
int src_stride,
|
||||||
|
int frame_size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
float *float_dst;
|
||||||
|
int i;
|
||||||
|
float_dst = (float*)dst;
|
||||||
|
if (src != NULL)
|
||||||
|
{
|
||||||
|
for (i=0;i<frame_size;i++)
|
||||||
|
#if defined(FIXED_POINT)
|
||||||
|
float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
|
||||||
|
#else
|
||||||
|
float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i=0;i<frame_size;i++)
|
||||||
|
float_dst[i*dst_stride+dst_channel] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void opus_copy_channel_out_short(
|
||||||
|
void *dst,
|
||||||
|
int dst_stride,
|
||||||
|
int dst_channel,
|
||||||
|
const opus_val16 *src,
|
||||||
|
int src_stride,
|
||||||
|
int frame_size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
opus_int16 *short_dst;
|
||||||
|
int i;
|
||||||
|
short_dst = (opus_int16*)dst;
|
||||||
|
if (src != NULL)
|
||||||
|
{
|
||||||
|
for (i=0;i<frame_size;i++)
|
||||||
|
#if defined(FIXED_POINT)
|
||||||
|
short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
|
||||||
|
#else
|
||||||
|
short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i=0;i<frame_size;i++)
|
||||||
|
short_dst[i*dst_stride+dst_channel] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
int opus_multistream_decode(
|
int opus_multistream_decode(
|
||||||
OpusMSDecoder *st,
|
OpusMSDecoder *st,
|
||||||
|
@ -719,27 +856,16 @@ int opus_multistream_decode(
|
||||||
int decode_fec
|
int decode_fec
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
|
return opus_multistream_decode_native(st, data, len,
|
||||||
|
pcm, opus_copy_channel_out_short, frame_size, decode_fec);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_FLOAT_API
|
#ifndef DISABLE_FLOAT_API
|
||||||
int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
|
int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
|
||||||
opus_int32 len, float *pcm, int frame_size, int decode_fec)
|
opus_int32 len, float *pcm, int frame_size, int decode_fec)
|
||||||
{
|
{
|
||||||
VARDECL(opus_int16, out);
|
return opus_multistream_decode_native(st, data, len,
|
||||||
int ret, i;
|
pcm, opus_copy_channel_out_float, frame_size, decode_fec);
|
||||||
ALLOC_STACK;
|
|
||||||
|
|
||||||
ALLOC(out, frame_size*st->layout.nb_channels, opus_int16);
|
|
||||||
|
|
||||||
ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
for (i=0;i<ret*st->layout.nb_channels;i++)
|
|
||||||
pcm[i] = (1.f/32768.f)*(out[i]);
|
|
||||||
}
|
|
||||||
RESTORE_STACK;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -748,20 +874,8 @@ int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
|
||||||
int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
|
int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
|
||||||
opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
|
opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
|
||||||
{
|
{
|
||||||
VARDECL(float, out);
|
return opus_multistream_decode_native(st, data, len,
|
||||||
int ret, i;
|
pcm, opus_copy_channel_out_short, frame_size, decode_fec);
|
||||||
ALLOC_STACK;
|
|
||||||
|
|
||||||
ALLOC(out, frame_size*st->layout.nb_channels, float);
|
|
||||||
|
|
||||||
ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
for (i=0;i<ret*st->layout.nb_channels;i++)
|
|
||||||
pcm[i] = FLOAT2INT16(out[i]);
|
|
||||||
}
|
|
||||||
RESTORE_STACK;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int opus_multistream_decode_float(
|
int opus_multistream_decode_float(
|
||||||
|
@ -773,7 +887,8 @@ int opus_multistream_decode_float(
|
||||||
int decode_fec
|
int decode_fec
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
|
return opus_multistream_decode_native(st, data, len,
|
||||||
|
pcm, opus_copy_channel_out_float, frame_size, decode_fec);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -792,6 +907,7 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
|
||||||
switch (request)
|
switch (request)
|
||||||
{
|
{
|
||||||
case OPUS_GET_BANDWIDTH_REQUEST:
|
case OPUS_GET_BANDWIDTH_REQUEST:
|
||||||
|
case OPUS_GET_SAMPLE_RATE_REQUEST:
|
||||||
{
|
{
|
||||||
OpusDecoder *dec;
|
OpusDecoder *dec;
|
||||||
/* For int32* GET params, just query the first stream */
|
/* For int32* GET params, just query the first stream */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue