1
0
Fork 0
forked from len0rd/rockbox

opus optimize playback function

knocks off about .5 second from decode time not a big change but might help a bit on
devices that barely achieve realtime

Change-Id: If6e822b7273613c9449c102ce7dd3543bf975d37
This commit is contained in:
William Wilgus 2019-01-12 12:56:26 -06:00
parent c70e40f050
commit 00943537e6

View file

@ -59,7 +59,7 @@ static int get_more_data(ogg_sync_state *oy)
} }
/* seek to ogg page after given file position */ /* seek to ogg page after given file position */
static int seek_ogg_page(int64_t filepos) static int seek_ogg_page(uint64_t filepos)
{ {
const char synccode[] = "OggS\0"; /* Note: there are two nulls here */ const char synccode[] = "OggS\0"; /* Note: there are two nulls here */
char buf[sizeof(synccode)]; char buf[sizeof(synccode)];
@ -208,7 +208,7 @@ static int64_t seek_backwards(ogg_sync_state *oy, ogg_page *og,
return -1; return -1;
} }
static int speex_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,
@ -326,8 +326,7 @@ static int speex_seek_page_granule(int64_t pos, int64_t curpos,
/* this is the codec entry point */ /* this is the codec entry point */
enum codec_status codec_main(enum codec_entry_call_reason reason) enum codec_status codec_main(enum codec_entry_call_reason reason)
{ {
(void)reason; (void)reason; /* CODEC_LOAD, CODEC_UNLOAD */
return CODEC_OK; return CODEC_OK;
} }
@ -342,7 +341,7 @@ enum codec_status codec_run(void)
ogg_packet op; ogg_packet op;
ogg_stream_state os; ogg_stream_state os;
int64_t page_granule = 0; int64_t page_granule = 0;
int stream_init = 0; int stream_init = -1;
int sample_rate = 48000; int sample_rate = 48000;
OpusDecoder *st = NULL; OpusDecoder *st = NULL;
OpusHeader header; OpusHeader header;
@ -375,38 +374,29 @@ enum codec_status codec_run(void)
ci->seek_buffer(0); ci->seek_buffer(0);
ci->set_elapsed(0); ci->set_elapsed(0);
if (!strtoffset && param) { goto next_page; /* need to decode header before we do anything else */
action = CODEC_ACTION_SEEK_TIME;
}
goto next_page;
while (1) { while (1) {
if (action == CODEC_ACTION_NULL) action = ci->get_command(&param);
action = ci->get_command(&param);
if (action != CODEC_ACTION_NULL) { process_action:
if (action == CODEC_ACTION_HALT) if (action == CODEC_ACTION_SEEK_TIME) {
break; if (st != NULL) {
/* calculate granule to seek to (including seek rewind) */
seek_target = (48LL * param) + header.preskip;
skip = MIN(seek_target, SEEK_REWIND);
seek_target -= skip;
if (action == CODEC_ACTION_SEEK_TIME) { LOGF("Opus seek page:%lld,%lld,%ld\n",
if (st != NULL) { seek_target, page_granule, (long)param);
/* calculate granule to seek to (including seek rewind) */ opus_seek_page_granule(seek_target, page_granule, &oy, &os);
seek_target = (48LL * param) + header.preskip;
skip = MIN(seek_target, SEEK_REWIND);
seek_target -= skip;
LOGF("Opus seek page:%lld,%lld,%ld\n",
seek_target, page_granule, (long)param);
speex_seek_page_granule(seek_target, page_granule, &oy, &os);
}
ci->set_elapsed(param);
ci->seek_complete();
} }
action = CODEC_ACTION_NULL; ci->set_elapsed(param);
} ci->seek_complete();
param = 0;
} else if (action == CODEC_ACTION_HALT)
break;
next_page: next_page:
/*Get the ogg buffer for writing*/ /*Get the ogg buffer for writing*/
@ -416,9 +406,12 @@ enum codec_status codec_run(void)
/* 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) {
ogg_stream_init(&os, ogg_page_serialno(&og)); stream_init = ogg_stream_init(&os, ogg_page_serialno(&og));
stream_init = 1; if (stream_init != 0) {
LOGF("Stream init failed");
goto done;
}
} }
/* Add page to the bitstream */ /* Add page to the bitstream */
@ -427,16 +420,6 @@ enum codec_status codec_run(void)
page_granule = ogg_page_granulepos(&og); page_granule = ogg_page_granulepos(&og);
granule_pos = page_granule; granule_pos = page_granule;
/* Do this to avoid allocating space for huge comment packets
(embedded Album Art) */
if (os.packetno == 1 && ogg_stream_packetpeek(&os, NULL) == 0){
LOGF("sync reset");
/* seek buffer directly to the first audio packet */
seek_ogg_page(ci->curpos - oy.returned);
ogg_sync_reset(&oy);
break;
}
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 */
@ -463,16 +446,21 @@ enum codec_status codec_run(void)
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);
} else if (op.packetno == 1) { if (strtoffset)
/* Comment header */ seek_ogg_page(strtoffset);
} else { else if (param) {
if (strtoffset) { action = CODEC_ACTION_SEEK_TIME;
ci->seek_buffer(strtoffset); goto process_action;
ogg_sync_reset(&oy); } else {
strtoffset = 0; /* seek buffer directly to the first audio packet to avoid
break;//next page allocating space for huge comment packets
(embedded Album Art) */
seek_ogg_page(ci->curpos - oy.returned);
} }
LOGF("sync reset");
ogg_sync_reset(&oy); /* next page */
break;
} 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);
@ -480,29 +468,22 @@ enum codec_status codec_run(void)
/* 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);
if (ret > 0) { if (ret > skip) {
if (skip > 0) { /* part of or entire output buffer is played */
if (ret <= skip) { ret -= skip;
/* entire output buffer is skipped */ ci->pcmbuf_insert(&output[skip * header.channels], NULL, ret);
skip -= ret; skip = 0;
ret = 0;
} else {
/* part of output buffer is played */
ret -= skip;
ci->pcmbuf_insert(&output[skip * header.channels], NULL, ret);
skip = 0;
}
} else {
/* entire buffer is played */
ci->pcmbuf_insert(output, NULL, ret);
}
granule_pos += ret;
} else { } else {
if (ret < 0) { if (ret < 0) {
LOGF("opus_decode failed %d", ret); LOGF("opus_decode failed %d", ret);
goto done; goto done;
} else if (ret == 0)
break;
else {
/* entire output buffer is skipped */
skip -= ret;
ret = 0;
} }
break;
} }
} }
} }
@ -514,4 +495,3 @@ done:
ogg_malloc_destroy(); ogg_malloc_destroy();
return error; return error;
} }