aboutsummaryrefslogtreecommitdiff
path: root/src/opus_decoder.c
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@jmvalin.ca>2012-11-05 10:25:20 -0500
committerJean-Marc Valin <jmvalin@jmvalin.ca>2012-11-05 10:25:20 -0500
commitcc83f6b87597595f5c1ad57e17a53b8636586867 (patch)
treef20d9a7b91bb87f15eb23735237080b85a757a95 /src/opus_decoder.c
parent4ea3ae9af77d23c71a84ae50e0a411afa66a0463 (diff)
downloadlibopus-cc83f6b87597595f5c1ad57e17a53b8636586867.tar.gz
Reduces decoder stack usage
Delays stack allocations as much as possible, and makes some of these allocations conditional.
Diffstat (limited to 'src/opus_decoder.c')
-rw-r--r--src/opus_decoder.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index be6ae401..18262322 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -200,8 +200,14 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
int i, silk_ret=0, celt_ret=0;
ec_dec dec;
opus_int32 silk_frame_size;
+ int pcm_silk_size;
VARDECL(opus_int16, pcm_silk);
- VARDECL(opus_val16, pcm_transition);
+ int pcm_transition_silk_size;
+ VARDECL(opus_val16, pcm_transition_silk);
+ int pcm_transition_celt_size;
+ VARDECL(opus_val16, pcm_transition_celt);
+ opus_val16 *pcm_transition;
+ int redundant_audio_size;
VARDECL(opus_val16, redundant_audio);
int audiosize;
@@ -274,16 +280,26 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
RESTORE_STACK;
return frame_size;
}
- ALLOC(pcm_transition, F5*st->channels, opus_val16);
+ pcm_transition_silk_size = 0;
+ pcm_transition_celt_size = 0;
if (data!=NULL && st->prev_mode > 0 && (
(mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy)
|| (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) )
)
{
transition = 1;
+ /* Decide where to allocate the stack memory for pcm_transition */
if (mode == MODE_CELT_ONLY)
- opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
+ pcm_transition_celt_size = F5*st->channels;
+ else
+ pcm_transition_silk_size = F5*st->channels;
+ }
+ ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16);
+ if (transition && mode == MODE_CELT_ONLY)
+ {
+ pcm_transition = pcm_transition_celt;
+ opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
}
if (audiosize > frame_size)
{
@@ -294,8 +310,9 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
frame_size = audiosize;
}
- ALLOC(pcm_silk, IMAX(F10, frame_size)*st->channels, opus_int16);
- ALLOC(redundant_audio, F5*st->channels, opus_val16);
+ /* Don't allocate any memory when in CELT-only mode */
+ pcm_silk_size = (mode != MODE_CELT_ONLY) ? IMAX(F10, frame_size)*st->channels : 0;
+ ALLOC(pcm_silk, pcm_silk_size, opus_int16);
/* SILK processing */
if (mode != MODE_CELT_ONLY)
@@ -409,10 +426,22 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
}
if (redundancy)
+ {
transition = 0;
+ pcm_transition_silk_size=0;
+ }
+
+ ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16);
if (transition && mode != MODE_CELT_ONLY)
+ {
+ pcm_transition = pcm_transition_silk;
opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
+ }
+
+ /* Only allocation memory for redundancy if/when needed */
+ redundant_audio_size = redundancy ? F5*st->channels : 0;
+ ALLOC(redundant_audio, redundant_audio_size, opus_val16);
/* 5 ms redundant frame for CELT->SILK*/
if (redundancy && celt_to_silk)