Use dynamic stack allocations in SILK decoder.
This allows the decoder to be compiled with
NONTHREADSAFE_PSEUDOSTACK to move the memory for large buffers off
the stack for devices where it is very limited.
This patch only attempts to do this for the decoder.
The encoder still requires more than 10 kB of stack.
diff --git a/silk/dec_API.c b/silk/dec_API.c
index 60beef6..68403b7 100644
--- a/silk/dec_API.c
+++ b/silk/dec_API.c
@@ -30,6 +30,7 @@
#endif
#include "API.h"
#include "main.h"
+#include "stack_alloc.h"
/************************/
/* Decoder Super Struct */
@@ -85,14 +86,16 @@
{
opus_int i, n, decode_only_middle = 0, ret = SILK_NO_ERROR;
opus_int32 nSamplesOutDec, LBRR_symbol;
- opus_int16 samplesOut1_tmp[ 2 ][ MAX_FS_KHZ * MAX_FRAME_LENGTH_MS + 2 ];
- opus_int16 samplesOut2_tmp[ MAX_API_FS_KHZ * MAX_FRAME_LENGTH_MS ];
+ opus_int16 *samplesOut1_tmp[ 2 ];
+ VARDECL( opus_int16, samplesOut1_tmp_storage );
+ VARDECL( opus_int16, samplesOut2_tmp );
opus_int32 MS_pred_Q13[ 2 ] = { 0 };
opus_int16 *resample_out_ptr;
silk_decoder *psDec = ( silk_decoder * )decState;
silk_decoder_state *channel_state = psDec->channel_state;
opus_int has_side;
opus_int stereo_to_mono;
+ SAVE_STACK;
/**********************************/
/* Test if first frame in payload */
@@ -132,11 +135,13 @@
channel_state[ n ].nb_subfr = 4;
} else {
silk_assert( 0 );
+ RESTORE_STACK;
return SILK_DEC_INVALID_FRAME_SIZE;
}
fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1;
if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) {
silk_assert( 0 );
+ RESTORE_STACK;
return SILK_DEC_INVALID_SAMPLING_FREQUENCY;
}
ret += silk_decoder_set_fs( &channel_state[ n ], fs_kHz_dec, decControl->API_sampleRate );
@@ -153,6 +158,7 @@
if( decControl->API_sampleRate > (opus_int32)MAX_API_FS_KHZ * 1000 || decControl->API_sampleRate < 8000 ) {
ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY;
+ RESTORE_STACK;
return( ret );
}
@@ -240,6 +246,14 @@
psDec->channel_state[ 1 ].first_frame_after_reset = 1;
}
+ ALLOC( samplesOut1_tmp_storage,
+ decControl->nChannelsInternal*(
+ channel_state[ 0 ].frame_length + 2 ),
+ opus_int16 );
+ samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage;
+ samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage
+ + channel_state[ 0 ].frame_length + 2;
+
if( lostFlag == FLAG_DECODE_NORMAL ) {
has_side = !decode_only_middle;
} else {
@@ -285,6 +299,8 @@
*nSamplesOut = silk_DIV32( nSamplesOutDec * decControl->API_sampleRate, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) );
/* Set up pointers to temp buffers */
+ ALLOC( samplesOut2_tmp,
+ decControl->nChannelsAPI == 2 ? *nSamplesOut : 0, opus_int16 );
if( decControl->nChannelsAPI == 2 ) {
resample_out_ptr = samplesOut2_tmp;
} else {
@@ -337,6 +353,7 @@
} else {
psDec->prev_decode_only_middle = decode_only_middle;
}
+ RESTORE_STACK;
return ret;
}