1
0
Fork 0
forked from len0rd/rockbox

opus: shrink stack usage by nearly 700 bytes

By moving three structures to the heap.  None are in the hot decode
  loop, instead having to do with file sync / header state.

  Has neglible impact on performance (within measurement noise) on Clip+,
  Rocker, and Xduoo X3.

  On PP5022 (ipodmini2g) performance drops from 138.66% to 138.22% realtime.
  (0.3%)

  Unknown effect on Coldfire which lacks D$.

  Stack savings are pretty significant especially on lowmem devices.

Change-Id: Ic8a1e93062ff5a46230e824134032053c4e1986d
This commit is contained in:
Solomon Peachy 2019-02-01 08:21:07 -05:00
parent 8577d5aea3
commit 82943ea1c7

View file

@ -360,15 +360,15 @@ enum codec_status codec_run(void)
int error = CODEC_ERROR; int error = CODEC_ERROR;
long action; long action;
intptr_t param; intptr_t param;
ogg_sync_state oy; ogg_sync_state *oy;
ogg_stream_state *os;
ogg_page og; ogg_page og;
ogg_packet op; ogg_packet op;
ogg_stream_state os;
int64_t page_granule = 0; int64_t page_granule = 0;
int stream_init = -1; int stream_init = -1;
int sample_rate = 48000; int sample_rate = 48000;
OpusDecoder *st = NULL; OpusDecoder *st = NULL;
OpusHeader header; OpusHeader *header;
int ret; int ret;
unsigned long strtoffset; unsigned long strtoffset;
int skip = 0; int skip = 0;
@ -387,10 +387,15 @@ enum codec_status codec_run(void)
coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
#endif #endif
/* Allocate some stuff off the heap */
header = _ogg_malloc(sizeof(*header));
os = _ogg_malloc(sizeof(*os));
oy = _ogg_malloc(sizeof(*oy));
/* pre-init the ogg_sync_state buffer, so it won't need many reallocs */ /* pre-init the ogg_sync_state buffer, so it won't need many reallocs */
ogg_sync_init(&oy); ogg_sync_init(oy);
oy.storage = 64*1024; oy->storage = 64*1024;
oy.data = _ogg_malloc(oy.storage); oy->data = _ogg_malloc(oy->storage);
/* allocate output buffer */ /* allocate output buffer */
uint16_t *output = (uint16_t*) _ogg_malloc(MAX_FRAME_SIZE*sizeof(uint16_t)); uint16_t *output = (uint16_t*) _ogg_malloc(MAX_FRAME_SIZE*sizeof(uint16_t));
@ -407,13 +412,13 @@ enum codec_status codec_run(void)
if (action == CODEC_ACTION_SEEK_TIME) { if (action == CODEC_ACTION_SEEK_TIME) {
if (st != NULL) { if (st != NULL) {
/* calculate granule to seek to (including seek rewind) */ /* calculate granule to seek to (including seek rewind) */
seek_target = (48LL * param) + header.preskip; seek_target = (48LL * param) + header->preskip;
skip = MIN(seek_target, SEEK_REWIND); skip = MIN(seek_target, SEEK_REWIND);
seek_target -= skip; seek_target -= skip;
LOGF("Opus seek page:%lld,%lld,%ld\n", (long long int)seek_target, LOGF("Opus seek page:%lld,%lld,%ld\n", (long long int)seek_target,
(long long int)page_granule, (long)param); (long long int)page_granule, (long)param);
opus_seek_page_granule(seek_target, page_granule, &oy, &os); opus_seek_page_granule(seek_target, page_granule, oy, os);
/* reset the state to help ensure that subsequent packets won't /* reset the state to help ensure that subsequent packets won't
use state set by unrelated packets processed before seek */ use state set by unrelated packets processed before seek */
opus_decoder_ctl(st, OPUS_RESET_STATE); opus_decoder_ctl(st, OPUS_RESET_STATE);
@ -427,14 +432,14 @@ enum codec_status codec_run(void)
next_page: next_page:
/*Get the ogg buffer for writing*/ /*Get the ogg buffer for writing*/
if (get_more_data(&oy) < 1) { if (get_more_data(oy) < 1) {
goto done; goto done;
} }
/* Loop for all complete pages we got (most likely only one) */ /* Loop for all complete pages we got (most likely only one) */
while (ogg_sync_pageout(&oy, &og) == 1) { while (ogg_sync_pageout(oy, &og) == 1) {
if (stream_init != 0) { if (stream_init != 0) {
stream_init = ogg_stream_init(&os, ogg_page_serialno(&og)); stream_init = ogg_stream_init(os, ogg_page_serialno(&og));
if (stream_init != 0) { if (stream_init != 0) {
LOGF("Stream init failed"); LOGF("Stream init failed");
goto done; goto done;
@ -442,22 +447,22 @@ enum codec_status codec_run(void)
} }
/* Add page to the bitstream */ /* Add page to the bitstream */
ogg_stream_pagein(&os, &og); ogg_stream_pagein(os, &og);
page_granule = ogg_page_granulepos(&og); page_granule = ogg_page_granulepos(&og);
granule_pos = page_granule; granule_pos = page_granule;
while ((ogg_stream_packetout(&os, &op) == 1) && !op.e_o_s) { while ((ogg_stream_packetout(os, &op) == 1) && !op.e_o_s) {
if (op.packetno == 0){ if (op.packetno == 0){
/* identification header */ /* identification header */
if (opus_header_parse(op.packet, op.bytes, &header) == 0) { if (opus_header_parse(op.packet, op.bytes, header) == 0) {
LOGF("Could not parse header"); LOGF("Could not parse header");
goto done; goto done;
} }
skip = header.preskip; skip = header->preskip;
st = opus_decoder_create(sample_rate, header.channels, &ret); st = opus_decoder_create(sample_rate, header->channels, &ret);
if (ret != OPUS_OK) { if (ret != OPUS_OK) {
LOGF("opus_decoder_create failed %d", ret); LOGF("opus_decoder_create failed %d", ret);
goto done; goto done;
@ -466,11 +471,11 @@ enum codec_status codec_run(void)
codec_set_replaygain(ci->id3); codec_set_replaygain(ci->id3);
opus_decoder_ctl(st, OPUS_SET_GAIN(header.gain)); opus_decoder_ctl(st, OPUS_SET_GAIN(header->gain));
ci->configure(DSP_SET_FREQUENCY, sample_rate); ci->configure(DSP_SET_FREQUENCY, sample_rate);
ci->configure(DSP_SET_SAMPLE_DEPTH, 16); ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
ci->configure(DSP_SET_STEREO_MODE, (header.channels == 2) ? ci->configure(DSP_SET_STEREO_MODE, (header->channels == 2) ?
STEREO_INTERLEAVED : STEREO_MONO); STEREO_INTERLEAVED : STEREO_MONO);
if (strtoffset) if (strtoffset)
@ -490,12 +495,12 @@ enum codec_status codec_run(void)
} }
} }
LOGF("sync reset"); LOGF("sync reset");
ogg_sync_reset(&oy); /* next page */ ogg_sync_reset(oy); /* next page */
break; break;
} else { } else {
/* report progress */ /* report progress */
ci->set_offset((size_t) ci->curpos); ci->set_offset((size_t) ci->curpos);
ci->set_elapsed((granule_pos - header.preskip) / 48); ci->set_elapsed((granule_pos - header->preskip) / 48);
/* Decode audio packets */ /* Decode audio packets */
ret = opus_decode(st, op.packet, op.bytes, output, MAX_FRAME_SIZE, 0); ret = opus_decode(st, op.packet, op.bytes, output, MAX_FRAME_SIZE, 0);
@ -503,7 +508,7 @@ enum codec_status codec_run(void)
if (ret > skip) { if (ret > skip) {
/* part of or entire output buffer is played */ /* part of or entire output buffer is played */
ret -= skip; ret -= skip;
ci->pcmbuf_insert(&output[skip * header.channels], NULL, ret); ci->pcmbuf_insert(&output[skip * header->channels], NULL, ret);
skip = 0; skip = 0;
} else { } else {
if (ret < 0) { if (ret < 0) {