Skip to content

Commit

Permalink
audiolite/mp3dec: Fix freeze bug
Browse files Browse the repository at this point in the history
Fixed a bug that stopped decoding when a large size ID3v2 TAG
was present.
  • Loading branch information
SPRESENSE committed Jun 26, 2023
1 parent 3f98c8e commit 67e97c9
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 44 deletions.
4 changes: 2 additions & 2 deletions sdk/modules/audiolite/src/components/al_mp3dec.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ int audiolite_mp3dec::handle_mesage(al_comm_msghdr_t hdr,
return 0;
}

if (hdr.opt != AL_WORKER_VERSION_0)
if (hdr.opt != AL_MP3DECWORKER_VERSION)
{
thiz->publish_event(AL_EVENT_MP3DEC_WRONGVER, 0);
thiz->publish_event(AL_EVENT_MP3DEC_WRONGVER, hdr.opt);
return 0;
}

Expand Down
15 changes: 8 additions & 7 deletions sdk/modules/audiolite/worker/mp3dec/minimp3_spresense.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,14 @@
#define SPRMP3_STATE_END (0)
#define SPRMP3_STATE_INIT (1)
#define SPRMP3_STATE_READY (2)
#define SPRMP3_STATE_DECODE (3)
#define SPRMP3_STATE_FILLUP (4)
#define SPRMP3_STATE_FILLUPREMAIN (5)
#define SPRMP3_STATE_WAITIN (6)
#define SPRMP3_STATE_WAITINREMAIN (7)
#define SPRMP3_STATE_ENDING (8)
#define SPRMP3_STATE_ERROR (9)
#define SPRMP3_STATE_WAITSEEK (3)
#define SPRMP3_STATE_DECODE (4)
#define SPRMP3_STATE_FILLUP (5)
#define SPRMP3_STATE_FILLUPREMAIN (6)
#define SPRMP3_STATE_WAITIN (7)
#define SPRMP3_STATE_WAITINREMAIN (8)
#define SPRMP3_STATE_ENDING (9)
#define SPRMP3_STATE_ERROR (10)

#define SPRMP3_SYSSTATE_STOP (0)
#define SPRMP3_SYSSTATE_PAUSE (1)
Expand Down
143 changes: 109 additions & 34 deletions sdk/modules/audiolite/worker/mp3dec/mp3dec_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ struct state_proc_s
static int exec_endstate(sprmp3_t *inst, sprmp3_outmemqueue_t *outq);
static int exec_initstate(sprmp3_t *inst, sprmp3_outmemqueue_t *outq);
static int exec_readystate(sprmp3_t *inst, sprmp3_outmemqueue_t *outq);
static int exec_waitseek(sprmp3_t *inst, sprmp3_outmemqueue_t *outq);
static int exec_decodestate(sprmp3_t *inst, sprmp3_outmemqueue_t *outq);
static int exec_fillupstate(sprmp3_t *inst, sprmp3_outmemqueue_t *outq);
static int exec_fillremstate(sprmp3_t *inst, sprmp3_outmemqueue_t *outq);
Expand All @@ -87,6 +88,7 @@ static struct state_proc_s state_procs[] =
[SPRMP3_STATE_END] = {exec_endstate, 0},
[SPRMP3_STATE_INIT] = {exec_initstate, 0},
[SPRMP3_STATE_READY] = {exec_readystate, 0},
[SPRMP3_STATE_WAITSEEK] = {exec_waitseek, 0},
[SPRMP3_STATE_DECODE] = {exec_decodestate, 1},
[SPRMP3_STATE_FILLUP] = {exec_fillupstate, 1},
[SPRMP3_STATE_FILLUPREMAIN] = {exec_fillremstate, 1},
Expand Down Expand Up @@ -256,22 +258,46 @@ static int fill_tagsize(sprmp3_t *inst)

/*** name: seek_size */

static size_t seek_size(sprmp3_t *inst, int size)
static int seek_size(sprmp3_t *inst, int size)
{
size_t ret = 0;
sprmp3_fmemcont_t *mem =
(sprmp3_fmemcont_t *)sq_peek(&inst->fqueue.queued);
int ret = SPRMP3_STATE_WAITSEEK;
sprmp3_fmemqueue_t *queue = &inst->fqueue;
sprmp3_fmemcont_t *mem = (sprmp3_fmemcont_t *)sq_peek(&queue->queued);

if (mem)
{
/* The size is from top of the stream data */

if (mem->size >= (size_t)size)
{
/* Just skip size bytes */

inst->fqueue.copied_ofst = size;
ret = (size_t)size;

ret = SPRMP3_STATE_DECODE;
}
else
{
/* Keep the remaining size of the data to skip,
* as minus value.
*/

inst->fcache.usedsize = mem->size - size;

/* Release current buffer */

release_framemem(inst->id, queue);
}
}
else
{
/* Keep the remaining size of the data to skip,
* as minus value.
*/

inst->fcache.usedsize = -size;
release_framemem(inst->id, queue);
}

return ret;
}
Expand Down Expand Up @@ -393,6 +419,7 @@ static int refill_framecache(sprmp3_t *inst)

static int initialize_framecache(sprmp3_t *inst)
{
int ret;
size_t id3v2size;

mp3dec_init(&inst->core);
Expand All @@ -404,68 +431,98 @@ static int initialize_framecache(sprmp3_t *inst)

if (fill_tagsize(inst) == 0)
{
return ERROR;
#ifdef SPRMP3_DEBUG
sprmp3_dprintf("fill_tagsize() error\n");
#endif
return SPRMP3_STATE_ERROR;
}

memset(&inst->frame_info, 0, sizeof(inst->frame_info));

if (inst->fcache.fillsize > MINIMP3_ID3_DETECT_SIZE)
{
return ERROR;
}

if (MINIMP3_ID3_DETECT_SIZE != inst->fcache.fillsize)
if (inst->fcache.fillsize != MINIMP3_ID3_DETECT_SIZE)
{
return ERROR;
#ifdef SPRMP3_DEBUG
sprmp3_dprintf("fillsize is not equal ID3 SIZE : %d\n",
inst->fcache.fillsize);
#endif
return SPRMP3_STATE_ERROR;
}

id3v2size = mp3dec_skip_id3v2(inst->fcache.addr,
inst->fcache.fillsize);

if (id3v2size)
{
/* Avoid read data and fill again */

inst->fcache.fillsize = 0;

/* If tag header exists */

if (seek_size(inst, id3v2size) != id3v2size)
ret = seek_size(inst, id3v2size);
if (ret != SPRMP3_STATE_DECODE)
{
return ERROR;
return ret;
}

/* Avoid read data and fill again */

inst->fcache.fillsize = 0;
}

/* Fill empty space on No tag header case */

refill_framecache(inst);

if (inst->fcache.eof)
{
/* If the stream is very short and it is the end */

mp3dec_skip_id3v1(&inst->fcache.addr[0],
(size_t *)&inst->fcache.fillsize);
}

return OK;
return SPRMP3_STATE_DECODE;
}

/*** name: exec_readystate */

static int exec_readystate(sprmp3_t *inst, sprmp3_outmemqueue_t *outq)
{
int ret;
(void)outq;

if (initialize_framecache(inst) == OK)
ret = initialize_framecache(inst);

if (ret == SPRMP3_STATE_ERROR)
{
return SPRMP3_STATE_DECODE;
send_errormsg(inst->id, AL_COMM_MSGCODEERR_TOOSHORT);
}

return ret;
}

/*** name: exec_waitseek */

static int exec_waitseek(sprmp3_t *inst, sprmp3_outmemqueue_t *outq)
{
int sz;
int next_state = SPRMP3_STATE_WAITSEEK;
sprmp3_fmemqueue_t *queue = &inst->fqueue;
sprmp3_fmemcont_t *mem = (sprmp3_fmemcont_t *)sq_peek(&queue->queued);

if (inst->fcache.usedsize < 0)
{
if (mem)
{
sz = -inst->fcache.usedsize;
if (mem->size >= (size_t)sz)
{
inst->fqueue.copied_ofst = sz;
inst->fcache.usedsize = 0;
next_state = refill_framecache(inst);
}
else
{
inst->fcache.usedsize = mem->size - sz;
release_framemem(inst->id, queue);
}
}
}
else
{
send_errormsg(inst->id, AL_COMM_MSGCODEERR_TOOSHORT);
return SPRMP3_STATE_ERROR;
next_state = refill_framecache(inst);
}

return next_state;
}

/*** name: mix_data */
Expand Down Expand Up @@ -790,8 +847,26 @@ static int exec_decodestate(sprmp3_t *inst, sprmp3_outmemqueue_t *outq)
}
else if (!frame_size)
{
send_errormsg(inst->id, AL_COMM_MSGCODEERR_ILLIGALFRAME);
return SPRMP3_STATE_ERROR;
if (inst->fcache.eof)
{
/* In case of no frame is found in the last data,
* End the decoding.
*/

inst->fcache.usedsize = inst->fcache.fillsize;
inst->tgtcache.decsize = inst->tgtcache.remofst;
outq->done |= SPRMP3_OUTDONE(inst);
inst->omem_wofst = 0;
#ifdef SPRMP3_DEBUG
sprmp3_dprintf("Force the decode finish.\n");
#endif
return SPRMP3_STATE_ENDING;
}
else
{
send_errormsg(inst->id, AL_COMM_MSGCODEERR_ILLIGALFRAME);
return SPRMP3_STATE_ERROR;
}
}

/* Update frame information */
Expand Down
2 changes: 1 addition & 1 deletion sdk/modules/audiolite/worker/mp3dec/sprmp3_sendback.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ int send_bootmsg(void)
hdr.grp = AL_COMM_MESSAGE_SYS;
hdr.type = AL_COMM_MSGTYPE_ASYNC;
hdr.code = AL_COMM_MSGCODESYS_BOOT;
hdr.opt = AL_WORKER_VERSION_0;
hdr.opt = AL_MP3DECWORKER_VERSION;

#ifdef SPRMP3_DEBUG
sprmp3_dprintf("[MSG] BootUp\n");
Expand Down
3 changes: 3 additions & 0 deletions sdk/modules/include/audiolite/alworker_comm.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@
#define AL_WORKER_TYPE_MP3DEC (1)

#define AL_WORKER_VERSION_0 (0)
#define AL_WORKER_VERSION_1 (1)

#define AL_MP3DECWORKER_VERSION AL_WORKER_VERSION_1

#define AL_COMM_NO_MSG (0xffffffff)

Expand Down

0 comments on commit 67e97c9

Please sign in to comment.