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:
parent
8577d5aea3
commit
82943ea1c7
1 changed files with 33 additions and 28 deletions
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue