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

@ -216,7 +216,7 @@ static int64_t seek_backwards(ogg_sync_state *oy, ogg_page *og,
offset = ret; offset = ret;
continue; continue;
} }
} else if (ret == -3) } else if (ret == -3)
return(-3); return(-3);
else if (ret<=0) else if (ret<=0)
break; break;
@ -235,8 +235,8 @@ static int64_t seek_backwards(ogg_sync_state *oy, ogg_page *og,
static int opus_seek_page_granule(int64_t pos, int64_t curpos, static int opus_seek_page_granule(int64_t pos, int64_t curpos,
ogg_sync_state *oy, ogg_stream_state *os) ogg_sync_state *oy, ogg_stream_state *os)
{ {
/* TODO: Someone may want to try to implement seek to packet, /* TODO: Someone may want to try to implement seek to packet,
instead of just to page (should be more accurate, not be any instead of just to page (should be more accurate, not be any
faster) */ faster) */
int64_t crofs; int64_t crofs;
@ -253,7 +253,7 @@ static int opus_seek_page_granule(int64_t pos, int64_t curpos,
/* if seeking for more that 10sec, /* if seeking for more that 10sec,
headersize is known & more than 10kb is played, headersize is known & more than 10kb is played,
try to guess a place to seek from the number of try to guess a place to seek from the number of
bytes playe for this position, this works best when bytes playe for this position, this works best when
the bitrate is relativly constant. the bitrate is relativly constant.
*/ */
@ -324,7 +324,7 @@ static int opus_seek_page_granule(int64_t pos, int64_t curpos,
lastgranule = ogg_page_granulepos(&og); lastgranule = ogg_page_granulepos(&og);
if ( ((lastgranule - (avgpagelen/4)) < pos && ( lastgranule + if ( ((lastgranule - (avgpagelen/4)) < pos && ( lastgranule +
avgpagelen + (avgpagelen / 4)) > pos) || avgpagelen + (avgpagelen / 4)) > pos) ||
lastgranule > pos) { lastgranule > pos) {
@ -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)
@ -479,7 +484,7 @@ enum codec_status codec_run(void)
action = CODEC_ACTION_SEEK_TIME; action = CODEC_ACTION_SEEK_TIME;
goto process_action; goto process_action;
} else { } else {
/* seek buffer directly to the first audio packet to avoid /* seek buffer directly to the first audio packet to avoid
allocating space for huge comment packets allocating space for huge comment packets
(embedded Album Art) */ (embedded Album Art) */
if (seek_opus_tags()) if (seek_opus_tags())
@ -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) {