Prevents the SILK PLC from being called with an invalid frame size or sampling rate

This commit is contained in:
Jean-Marc Valin 2011-10-04 01:10:32 -04:00
parent 5d5875a93a
commit 0c5085ad2f

View file

@ -47,6 +47,7 @@ struct OpusDecoder {
int silk_dec_offset; int silk_dec_offset;
int channels; int channels;
opus_int32 Fs; /** Sampling rate (at the API level) */ opus_int32 Fs; /** Sampling rate (at the API level) */
silk_DecControlStruct DecControl;
/* Everything beyond this point gets cleared on a reset */ /* Everything beyond this point gets cleared on a reset */
#define OPUS_DECODER_RESET_START stream_channels #define OPUS_DECODER_RESET_START stream_channels
@ -104,6 +105,8 @@ int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels)
st->stream_channels = st->channels = channels; st->stream_channels = st->channels = channels;
st->Fs = Fs; st->Fs = Fs;
st->DecControl.API_sampleRate = st->Fs;
st->DecControl.nChannelsAPI = st->channels;
/* Reset decoder */ /* Reset decoder */
ret = silk_InitDecoder( silk_dec ); ret = silk_InitDecoder( silk_dec );
@ -186,7 +189,6 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
CELTDecoder *celt_dec; CELTDecoder *celt_dec;
int i, silk_ret=0, celt_ret=0; int i, silk_ret=0, celt_ret=0;
ec_dec dec; ec_dec dec;
silk_DecControlStruct DecControl;
opus_int32 silk_frame_size; opus_int32 silk_frame_size;
VARDECL(opus_int16, pcm_silk); VARDECL(opus_int16, pcm_silk);
VARDECL(opus_val16, pcm_transition); VARDECL(opus_val16, pcm_transition);
@ -259,7 +261,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
frame_size = audiosize; frame_size = audiosize;
} }
ALLOC(pcm_silk, frame_size*st->channels, opus_int16); ALLOC(pcm_silk, IMAX(F10, frame_size)*st->channels, opus_int16);
ALLOC(redundant_audio, F5*st->channels, opus_val16); ALLOC(redundant_audio, F5*st->channels, opus_val16);
/* SILK processing */ /* SILK processing */
@ -271,24 +273,27 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
if (st->prev_mode==MODE_CELT_ONLY) if (st->prev_mode==MODE_CELT_ONLY)
silk_InitDecoder( silk_dec ); silk_InitDecoder( silk_dec );
DecControl.API_sampleRate = st->Fs; /* The SILK PLC cannot support produce frames of less than 10 ms */
DecControl.nChannelsAPI = st->channels; st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs);
DecControl.nChannelsInternal = st->stream_channels;
DecControl.payloadSize_ms = 1000 * audiosize / st->Fs; if (data != NULL)
if( mode == MODE_SILK_ONLY ) { {
if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) { st->DecControl.nChannelsInternal = st->stream_channels;
DecControl.internalSampleRate = 8000; if( mode == MODE_SILK_ONLY ) {
} else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) { if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
DecControl.internalSampleRate = 12000; st->DecControl.internalSampleRate = 8000;
} else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) { } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
DecControl.internalSampleRate = 16000; st->DecControl.internalSampleRate = 12000;
} else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
st->DecControl.internalSampleRate = 16000;
} else {
st->DecControl.internalSampleRate = 16000;
silk_assert( 0 );
}
} else { } else {
DecControl.internalSampleRate = 16000; /* Hybrid mode */
silk_assert( 0 ); st->DecControl.internalSampleRate = 16000;
} }
} else {
/* Hybrid mode */
DecControl.internalSampleRate = 16000;
} }
lost_flag = data == NULL ? 1 : 2 * decode_fec; lost_flag = data == NULL ? 1 : 2 * decode_fec;
@ -296,7 +301,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
do { do {
/* Call SILK decoder */ /* Call SILK decoder */
int first_frame = decoded_samples == 0; int first_frame = decoded_samples == 0;
silk_ret = silk_Decode( silk_dec, &DecControl, silk_ret = silk_Decode( silk_dec, &st->DecControl,
lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size ); lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size );
if( silk_ret ) { if( silk_ret ) {
if (lost_flag) { if (lost_flag) {