diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-04-27 03:08:23 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-04-27 03:08:23 +0000 |
commit | c537d5958e8b421ac4f9bef6c8b9e7425a6cf167 (patch) | |
tree | 7ed36518fb6524da7bbd913ba7619b85b5d15d23 /apps/codecs | |
parent | dcf0f8de4a37ff1d2ea510aef75fa67977a8bdcc (diff) | |
download | rockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.tar.gz rockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.zip |
Commit FS#12069 - Playback rework - first stages. Gives as thorough as possible a treatment of codec management, track change and metadata logic as possible while maintaining fairly narrow focus and not rewriting everything all at once. Please see the rockbox-dev mail archive on 2011-04-25 (Playback engine rework) for a more thorough manifest of what was addressed. Plugins and codecs become incompatible.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29785 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs')
39 files changed, 1384 insertions, 1500 deletions
diff --git a/apps/codecs/a52.c b/apps/codecs/a52.c index 00fdeea309..4cd293e37f 100644 --- a/apps/codecs/a52.c +++ b/apps/codecs/a52.c @@ -116,27 +116,31 @@ static void a52_decode_data(uint8_t *start, uint8_t *end) } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); + ci->configure(DSP_SET_SAMPLE_DEPTH, 28); + } + else if (reason == CODEC_UNLOAD) { + if (state) + a52_free(state); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { size_t n; unsigned char *filebuf; int sample_loc; - int retval; + intptr_t param; - /* Generic codec initialisation */ - ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); - ci->configure(DSP_SET_SAMPLE_DEPTH, 28); - -next_track: - retval = CODEC_OK; - - if (codec_init()) { - retval = CODEC_ERROR; - goto exit; - } - - if (codec_wait_taginfo() != 0) - goto request_next_track; + if (codec_init()) + return CODEC_ERROR; ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); codec_set_replaygain(ci->id3); @@ -153,15 +157,18 @@ next_track: } } else { + ci->seek_buffer(ci->id3->first_frame_offset); samplesdone = 0; } while (1) { - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) { - sample_loc = (ci->seek_time - 1)/1000 * ci->id3->frequency; + if (action == CODEC_ACTION_SEEK_TIME) { + sample_loc = param/1000 * ci->id3->frequency; if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) { samplesdone = sample_loc; @@ -179,11 +186,5 @@ next_track: ci->advance_buffer(n); } -request_next_track: - if (ci->request_next_track()) - goto next_track; - -exit: - a52_free(state); - return retval; + return CODEC_OK; } diff --git a/apps/codecs/a52_rm.c b/apps/codecs/a52_rm.c index f5e4923292..c1930aa7b4 100644 --- a/apps/codecs/a52_rm.c +++ b/apps/codecs/a52_rm.c @@ -124,36 +124,44 @@ static void a52_decode_data(uint8_t *start, uint8_t *end) } } - /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); + ci->configure(DSP_SET_SAMPLE_DEPTH, 28); + } + else if (reason == CODEC_UNLOAD) { + if (state) + a52_free(state); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { size_t n; uint8_t *filebuf; - int retval, consumed, packet_offset; + int consumed, packet_offset; int playback_on = -1; size_t resume_offset; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); - ci->configure(DSP_SET_SAMPLE_DEPTH, 28); - -next_track: - retval = CODEC_OK; + intptr_t param; + enum codec_command_action action = CODEC_ACTION_NULL; if (codec_init()) { - retval = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto request_next_track; - resume_offset = ci->id3->offset; ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); codec_set_replaygain(ci->id3); + ci->seek_buffer(ci->id3->first_frame_offset); + /* Intializations */ state = a52_init(0); ci->memset(&rmctx,0,sizeof(RMContext)); @@ -165,26 +173,34 @@ next_track: resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; /* put number of subpackets to skip in resume_offset */ resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); - ci->seek_time = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); + param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); + action = CODEC_ACTION_SEEK_TIME; + } + else { + /* Seek to the first packet */ + ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE ); } - - /* Seek to the first packet */ - ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE ); /* The main decoding loop */ while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + if (action == CODEC_ACTION_NULL) + action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) { - packet_offset = ci->seek_time / ((rmctx.block_align*8*1000)/rmctx.bit_rate); - ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE)); + if (action == CODEC_ACTION_SEEK_TIME) { + packet_offset = param / ((rmctx.block_align*8*1000)/rmctx.bit_rate); + ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + + packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE)); rmctx.audio_pkt_cnt = packet_offset; - samplesdone = (rmctx.sample_rate/1000 * ci->seek_time); + samplesdone = (rmctx.sample_rate/1000 * param); + ci->set_elapsed(samplesdone/(frequency/1000)); ci->seek_complete(); } + action = CODEC_ACTION_NULL; + filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE); consumed = rm_get_packet(&filebuf, &rmctx, &pkt); @@ -195,8 +211,7 @@ next_track: return CODEC_ERROR; } else { - retval = CODEC_OK; - goto exit; + break; } } @@ -205,11 +220,5 @@ next_track: ci->advance_buffer(pkt.length); } -request_next_track: - if (ci->request_next_track()) - goto next_track; - -exit: - a52_free(state); - return retval; + return CODEC_OK; } diff --git a/apps/codecs/aac.c b/apps/codecs/aac.c index 5638dc49a9..90cf0438ce 100644 --- a/apps/codecs/aac.c +++ b/apps/codecs/aac.c @@ -33,7 +33,19 @@ CODEC_HEADER #define FAAD_BYTE_BUFFER_SIZE (2048-12) /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); + ci->configure(DSP_SET_SAMPLE_DEPTH, 29); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { /* Note that when dealing with QuickTime/MPEG4 files, terminology is * a bit confusing. Files with sound are split up in chunks, where @@ -59,25 +71,15 @@ enum codec_status codec_main(void) uint32_t sbr_fac = 1; unsigned char c = 0; void *ret; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); - ci->configure(DSP_SET_SAMPLE_DEPTH, 29); - -next_track: - err = CODEC_OK; + intptr_t param; /* Clean and initialize decoder structures */ memset(&demux_res , 0, sizeof(demux_res)); if (codec_init()) { LOGF("FAAD: Codec init error\n"); - err = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - file_offset = ci->id3->offset; ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); @@ -85,12 +87,13 @@ next_track: stream_create(&input_stream,ci); + ci->seek_buffer(ci->id3->first_frame_offset); + /* if qtmovie_read returns successfully, the stream is up to * the movie data, which can be used directly by the decoder */ if (!qtmovie_read(&input_stream, &demux_res)) { LOGF("FAAD: File init error\n"); - err = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* initialise the sound converter */ @@ -98,8 +101,7 @@ next_track: if (!decoder) { LOGF("FAAD: Decode open error\n"); - err = CODEC_ERROR; - goto done; + return CODEC_ERROR; } NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); @@ -109,8 +111,7 @@ next_track: err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c); if (err) { LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type); - err = CODEC_ERROR; - goto done; + return CODEC_ERROR; } #ifdef SBR_DEC @@ -150,20 +151,19 @@ next_track: /* The main decoding loop */ while (i < demux_res.num_sample_byte_sizes) { - ci->yield(); + enum codec_command_action action = ci->get_command(¶m); - if (ci->stop_codec || ci->new_track) { + if (action == CODEC_ACTION_HALT) break; - } /* Deal with any pending seek requests */ - if (ci->seek_time) { + if (action == CODEC_ACTION_SEEK_TIME) { /* Seek to the desired time position. Important: When seeking in SBR * upsampling files the seek_time must be divided by 2 when calling * m4a_seek and the resulting sound_samples_done must be expanded * by a factor 2. This is done via using sbr_fac. */ if (m4a_seek(&demux_res, &input_stream, - ((ci->seek_time-1)/10/sbr_fac)*(ci->id3->frequency/100), + (param/10/sbr_fac)*(ci->id3->frequency/100), &sound_samples_done, (int*) &i)) { sound_samples_done *= sbr_fac; elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100); @@ -194,8 +194,7 @@ next_track: else if (file_offset == 0) { LOGF("AAC: get_sample_offset error\n"); - err = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* Request the required number of bytes from the input buffer */ @@ -207,8 +206,7 @@ next_track: /* NeAACDecDecode may sometimes return NULL without setting error. */ if (ret == NULL || frame_info.error > 0) { LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error)); - err = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* Advance codec buffer (no need to call set_offset because of this) */ @@ -251,12 +249,6 @@ next_track: i++; } -done: LOGF("AAC: Decoded %lu samples\n", (unsigned long)sound_samples_done); - - if (ci->request_next_track()) - goto next_track; - -exit: - return err; + return CODEC_OK; } diff --git a/apps/codecs/adx.c b/apps/codecs/adx.c index 832b94797b..a1b57fce58 100644 --- a/apps/codecs/adx.c +++ b/apps/codecs/adx.c @@ -45,7 +45,19 @@ static const long cutoff = 500; static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR; /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + /* we only render 16 bits */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 16); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { int channels; int sampleswritten, i; @@ -62,12 +74,8 @@ enum codec_status codec_main(void) off_t chanstart, bufoff; /*long coef1=0x7298L,coef2=-0x3350L;*/ long coef1, coef2; + intptr_t param; - /* Generic codec initialisation */ - /* we only render 16 bits */ - ci->configure(DSP_SET_SAMPLE_DEPTH, 16); - -next_track: DEBUGF("ADX: next_track\n"); if (codec_init()) { return CODEC_ERROR; @@ -77,10 +85,6 @@ next_track: /* init history */ ch1_1=ch1_2=ch2_1=ch2_2=0; - /* wait for track info to load */ - if (codec_wait_taginfo() != 0) - goto request_next_track; - codec_set_replaygain(ci->id3); /* Get header */ @@ -226,10 +230,10 @@ next_track: /* The main decoder loop */ while (!endofstream) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - } /* do we need to loop? */ if (bufoff > end_adr-18*channels && looping) { @@ -254,17 +258,17 @@ next_track: } /* do we need to seek? */ - if (ci->seek_time) { + if (action == CODEC_ACTION_SEEK_TIME) { uint32_t newpos; - DEBUGF("ADX: seek to %ldms\n",ci->seek_time); + DEBUGF("ADX: seek to %ldms\n", (long)param); endofstream = 0; loop_count = 0; fade_count = -1; /* disable fade */ fade_frames = 1; - newpos = (((uint64_t)avgbytespersec*(ci->seek_time - 1)) + newpos = (((uint64_t)avgbytespersec*param) / (1000LL*18*channels))*(18*channels); bufoff = chanstart + newpos; while (bufoff > end_adr-18*channels) { @@ -385,9 +389,5 @@ next_track: 1000LL/avgbytespersec); } -request_next_track: - if (ci->request_next_track()) - goto next_track; - return CODEC_OK; } diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c index d4cf8660dd..3fc137eaeb 100644 --- a/apps/codecs/aiff.c +++ b/apps/codecs/aiff.c @@ -61,9 +61,20 @@ static const struct pcm_codec *get_codec(uint32_t formattag) return NULL; } -enum codec_status codec_main(void) +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { - int status; struct pcm_format format; uint32_t bytesdone, decodedsamples; uint32_t num_sample_frames = 0; @@ -77,38 +88,28 @@ enum codec_status codec_main(void) bool is_aifc = false; const struct pcm_codec *codec; uint32_t size; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); - -next_track: - status = CODEC_OK; + intptr_t param; if (codec_init()) { - status = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - codec_set_replaygain(ci->id3); /* Need to save offset for later use (cleared indirectly by advance_buffer) */ bytesdone = ci->id3->offset; /* assume the AIFF header is less than 1024 bytes */ + ci->seek_buffer(0); buf = ci->request_buffer(&n, 1024); if (n < 54) { - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (memcmp(buf, "FORM", 4) != 0) { DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (memcmp(&buf[8], "AIFF", 4) == 0) is_aifc = false; @@ -117,8 +118,7 @@ next_track: else { DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } buf += 12; @@ -141,8 +141,7 @@ next_track: { DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n", (unsigned long)size, (is_aifc)?22:18); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* num_channels */ format.channels = ((buf[8]<<8)|buf[9]); @@ -154,8 +153,7 @@ next_track: /* sample_rate (don't use last 4 bytes, only integer fs) */ if (buf[16] != 0x40) { DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1; format.samplespersec >>= (16 + 14 - buf[17]); @@ -181,8 +179,7 @@ next_track: } else if (memcmp(buf, "SSND", 4)==0) { if (format.bitspersample == 0) { DEBUGF("CODEC_ERROR: unsupported chunk order\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* offset2snd */ offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; @@ -205,21 +202,18 @@ next_track: buf += size; if (n < size) { DEBUGF("CODEC_ERROR: AIFF header size > 1024\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } n -= size; } /* while 'SSND' */ if (format.channels == 0) { DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.numbytes == 0) { DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } codec = get_codec(format.formattag); @@ -227,14 +221,12 @@ next_track: { DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n", (unsigned int)format.formattag); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (!codec->set_format(&format)) { - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); @@ -245,21 +237,18 @@ next_track: ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); } else { DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.samplesperblock == 0) { DEBUGF("CODEC_ERROR: samplesperblock is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.blockalign == 0) { DEBUGF("CODEC_ERROR: blockalign is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* check chunksize */ @@ -269,8 +258,7 @@ next_track: if (format.chunksize == 0) { DEBUGF("CODEC_ERROR: chunksize is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } firstblockposn = 1024 - n; @@ -283,13 +271,13 @@ next_track: PCM_SEEK_POS, NULL); if (newpos->pos > format.numbytes) - goto done; + return CODEC_OK; + if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } - ci->seek_complete(); } else { /* already where we need to be */ bytesdone = 0; @@ -299,21 +287,29 @@ next_track: endofstream = 0; while (!endofstream) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) { + if (action == CODEC_ACTION_SEEK_TIME) { /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */ - struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); + struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL); if (newpos->pos > format.numbytes) + { + ci->set_elapsed(ci->id3->length); + ci->seek_complete(); break; + } + if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } + + ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); ci->seek_complete(); } aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); @@ -326,11 +322,10 @@ next_track: endofstream = 1; } - status = codec->decode(aifbuf, n, samples, &bufcount); - if (status == CODEC_ERROR) + if (codec->decode(aifbuf, n, samples, &bufcount) == CODEC_ERROR) { DEBUGF("codec error\n"); - goto done; + return CODEC_ERROR; } ci->pcmbuf_insert(samples, NULL, bufcount); @@ -343,13 +338,6 @@ next_track: ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); } - status = CODEC_OK; - -done: - if (ci->request_next_track()) - goto next_track; -exit: - return status; + return CODEC_OK; } - diff --git a/apps/codecs/aiff_enc.c b/apps/codecs/aiff_enc.c index 69496f70ac..fc44196eb0 100644 --- a/apps/codecs/aiff_enc.c +++ b/apps/codecs/aiff_enc.c @@ -359,40 +359,42 @@ static bool init_encoder(void) return true; } /* init_encoder */ -/* main codec entry point */ -enum codec_status codec_main(void) +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) { - if (!init_encoder()) - return CODEC_ERROR; + if (reason == CODEC_LOAD) { + if (!init_encoder()) + return CODEC_ERROR; + } + else if (reason == CODEC_UNLOAD) { + /* reset parameters to initial state */ + ci->enc_set_parameters(NULL); + } + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ /* main encoding loop */ - while(!ci->stop_codec) + while (ci->get_command(NULL) != CODEC_ACTION_HALT) { - uint32_t *src; + uint32_t *src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE); + struct enc_chunk_hdr *chunk; - while ((src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL) - { - struct enc_chunk_hdr *chunk; - - if (ci->stop_codec) - break; + if (src == NULL) + continue; - chunk = ci->enc_get_chunk(); - chunk->enc_size = enc_size; - chunk->num_pcm = PCM_SAMP_PER_CHUNK; - chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); + chunk = ci->enc_get_chunk(); + chunk->enc_size = enc_size; + chunk->num_pcm = PCM_SAMP_PER_CHUNK; + chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); - chunk_to_aiff_format(src, (uint32_t *)chunk->enc_data); - - ci->enc_finish_chunk(); - ci->yield(); - } + chunk_to_aiff_format(src, (uint32_t *)chunk->enc_data); - ci->yield(); + ci->enc_finish_chunk(); } - /* reset parameters to initial state */ - ci->enc_set_parameters(NULL); - return CODEC_OK; -} /* codec_start */ +} diff --git a/apps/codecs/alac.c b/apps/codecs/alac.c index cd9129a278..82bda264c3 100644 --- a/apps/codecs/alac.c +++ b/apps/codecs/alac.c @@ -32,116 +32,114 @@ CODEC_HEADER static int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR; /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) { - size_t n; - demux_res_t demux_res; - stream_t input_stream; - uint32_t samplesdone; - uint32_t elapsedtime; - int samplesdecoded; - unsigned int i; - unsigned char* buffer; - alac_file alac; - int retval; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); - ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1); - - next_track: - retval = CODEC_OK; - - /* Clean and initialize decoder structures */ - memset(&demux_res , 0, sizeof(demux_res)); - if (codec_init()) { - LOGF("ALAC: Error initialising codec\n"); - retval = CODEC_ERROR; - goto exit; - } - - if (codec_wait_taginfo() != 0) - goto done; - - ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); - codec_set_replaygain(ci->id3); + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); + ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1); + } - stream_create(&input_stream,ci); + return CODEC_OK; +} - /* Read from ci->id3->offset before calling qtmovie_read. */ - samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) / - (ci->id3->bitrate*128)); - - /* if qtmovie_read returns successfully, the stream is up to - * the movie data, which can be used directly by the decoder */ - if (!qtmovie_read(&input_stream, &demux_res)) { - LOGF("ALAC: Error initialising file\n"); - retval = CODEC_ERROR; - goto done; - } - - /* initialise the sound converter */ - create_alac(demux_res.sound_sample_size, demux_res.num_channels,&alac); - alac_set_info(&alac, demux_res.codecdata); - - /* Set i for first frame, seek to desired sample position for resuming. */ - i=0; - if (samplesdone > 0) { - if (m4a_seek(&demux_res, &input_stream, samplesdone, - &samplesdone, (int*) &i)) { - elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100); - ci->set_elapsed(elapsedtime); - } else { - samplesdone = 0; +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ + size_t n; + demux_res_t demux_res; + stream_t input_stream; + uint32_t samplesdone; + uint32_t elapsedtime = 0; + int samplesdecoded; + unsigned int i; + unsigned char* buffer; + alac_file alac; + intptr_t param; + + /* Clean and initialize decoder structures */ + memset(&demux_res , 0, sizeof(demux_res)); + if (codec_init()) { + LOGF("ALAC: Error initialising codec\n"); + return CODEC_ERROR; } - } - /* The main decoding loop */ - while (i < demux_res.num_sample_byte_sizes) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { - break; + ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); + codec_set_replaygain(ci->id3); + + ci->seek_buffer(0); + + stream_create(&input_stream,ci); + + /* Read from ci->id3->offset before calling qtmovie_read. */ + samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) / + (ci->id3->bitrate*128)); + + /* if qtmovie_read returns successfully, the stream is up to + * the movie data, which can be used directly by the decoder */ + if (!qtmovie_read(&input_stream, &demux_res)) { + LOGF("ALAC: Error initialising file\n"); + return CODEC_ERROR; } - /* Deal with any pending seek requests */ - if (ci->seek_time) { - if (m4a_seek(&demux_res, &input_stream, - ((ci->seek_time-1)/10) * (ci->id3->frequency/100), - &samplesdone, (int *)&i)) { - elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); - ci->set_elapsed(elapsedtime); - } - ci->seek_complete(); + /* initialise the sound converter */ + create_alac(demux_res.sound_sample_size, demux_res.num_channels,&alac); + alac_set_info(&alac, demux_res.codecdata); + + /* Set i for first frame, seek to desired sample position for resuming. */ + i=0; + if (samplesdone > 0) { + if (m4a_seek(&demux_res, &input_stream, samplesdone, + &samplesdone, (int*) &i)) { + elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100); + ci->set_elapsed(elapsedtime); + } else { + samplesdone = 0; + } } - /* Request the required number of bytes from the input buffer */ - buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); + /* The main decoding loop */ + while (i < demux_res.num_sample_byte_sizes) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) + break; - /* Decode one block - returned samples will be host-endian */ - ci->yield(); - samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield); + /* Request the required number of bytes from the input buffer */ + buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); - /* Advance codec buffer by amount of consumed bytes */ - ci->advance_buffer(alac.bytes_consumed); + /* Deal with any pending seek requests */ + if (action == CODEC_ACTION_SEEK_TIME) { + if (m4a_seek(&demux_res, &input_stream, + (param/10) * (ci->id3->frequency/100), + &samplesdone, (int *)&i)) { + elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); + } + ci->set_elapsed(elapsedtime); + ci->seek_complete(); + } - /* Output the audio */ - ci->yield(); - ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded); + /* Request the required number of bytes from the input buffer */ + buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); - /* Update the elapsed-time indicator */ - samplesdone+=samplesdecoded; - elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); - ci->set_elapsed(elapsedtime); + /* Decode one block - returned samples will be host-endian */ + samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield); + ci->yield(); - i++; - } + /* Advance codec buffer by amount of consumed bytes */ + ci->advance_buffer(alac.bytes_consumed); -done: - LOGF("ALAC: Decoded %lu samples\n",(unsigned long)samplesdone); + /* Output the audio */ + ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded); - if (ci->request_next_track()) - goto next_track; + /* Update the elapsed-time indicator */ + samplesdone+=samplesdecoded; + elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); + ci->set_elapsed(elapsedtime); + + i++; + } -exit: - return retval; + LOGF("ALAC: Decoded %lu samples\n",(unsigned long)samplesdone); + return CODEC_OK; } diff --git a/apps/codecs/ape.c b/apps/codecs/ape.c index 11d973ab26..8f95a01ec7 100644 --- a/apps/codecs/ape.c +++ b/apps/codecs/ape.c @@ -127,13 +127,23 @@ static void ape_resume(struct ape_ctx_t* ape_ctx, size_t resume_offset, } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { struct ape_ctx_t ape_ctx; uint32_t samplesdone; uint32_t elapsedtime; size_t bytesleft; - int retval; uint32_t currentframe; uint32_t newfilepos; @@ -145,33 +155,24 @@ enum codec_status codec_main(void) int res; int firstbyte; size_t resume_offset; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1); - -next_track: - retval = CODEC_OK; + intptr_t param; if (codec_init()) { LOGF("APE: Error initialising codec\n"); - retval = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - /* Remember the resume position - when the codec is opened, the playback engine will reset it. */ resume_offset = ci->id3->offset; + ci->seek_buffer(0); inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); /* Read the file headers to populate the ape_ctx struct */ if (ape_parseheaderbuf(inbuffer,&ape_ctx) < 0) { LOGF("APE: Error reading header\n"); - retval = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } /* Initialise the seektable for this file */ @@ -243,16 +244,16 @@ frame_start: /* Decode the frame a chunk at a time */ while (nblocks > 0) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) goto done; - } /* Deal with any pending seek requests */ - if (ci->seek_time) + if (action == CODEC_ACTION_SEEK_TIME) { if (ape_calc_seekpos(&ape_ctx, - ((ci->seek_time-1)/10) * (ci->id3->frequency/100), + (param/10) * (ci->id3->frequency/100), ¤tframe, &newfilepos, &samplestoskip)) @@ -266,9 +267,12 @@ frame_start: ci->seek_buffer(newfilepos); inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); + elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100); + ci->set_elapsed(elapsedtime); ci->seek_complete(); goto frame_start; /* Sorry... */ } + ci->seek_complete(); } @@ -281,8 +285,7 @@ frame_start: { /* Frame decoding error, abort */ LOGF("APE: Frame %lu, error %d\n",(unsigned long)currentframe,res); - retval = CODEC_ERROR; - goto done; + return CODEC_ERROR; } ci->yield(); @@ -320,10 +323,5 @@ frame_start: done: LOGF("APE: Decoded %lu samples\n",(unsigned long)samplesdone); - - if (ci->request_next_track()) - goto next_track; - -exit: - return retval; + return CODEC_OK; } diff --git a/apps/codecs/asap.c b/apps/codecs/asap.c index 9447c738d2..f12dc6a0c5 100644 --- a/apps/codecs/asap.c +++ b/apps/codecs/asap.c @@ -29,24 +29,21 @@ CODEC_HEADER static byte samples[CHUNK_SIZE] IBSS_ATTR; /* The sample buffer */ static ASAP_State asap; /* asap codec state */ -/* this is the codec entry point */ -enum codec_status codec_main(void) +/* this is called for each file to process */ +enum codec_status codec_run(void) { int n_bytes; int song; int duration; char* module; int bytesPerSample =2; + intptr_t param; -next_track: if (codec_init()) { DEBUGF("codec init failed\n"); return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto request_next_track; - codec_set_replaygain(ci->id3); int bytes_done =0; @@ -97,19 +94,20 @@ next_track: /* The main decoder loop */ while (1) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) { - /* New time is ready in ci->seek_time */ - + if (action == CODEC_ACTION_SEEK_TIME) { + /* New time is ready in param */ + /* seek to pos */ - ASAP_Seek(&asap,ci->seek_time); - /* update elapsed */ - ci->set_elapsed(ci->seek_time); + ASAP_Seek(&asap,param); /* update bytes_done */ - bytes_done = ci->seek_time*44.1*2; + bytes_done = param*44.1*2; + /* update elapsed */ + ci->set_elapsed((bytes_done / 2) / 44.1); /* seek ready */ ci->seek_complete(); } @@ -129,10 +127,6 @@ next_track: if(n_bytes != sizeof(samples)) break; } - -request_next_track: - if (ci->request_next_track()) - goto next_track; return CODEC_OK; } diff --git a/apps/codecs/atrac3_oma.c b/apps/codecs/atrac3_oma.c index 73f3ad29fd..ab24783368 100644 --- a/apps/codecs/atrac3_oma.c +++ b/apps/codecs/atrac3_oma.c @@ -33,24 +33,22 @@ CODEC_HEADER static ATRAC3Context q IBSS_ATTR; -/* this is the codec entry point */ -enum codec_status codec_main(void) -{ +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ static size_t buff_size; int datasize, res, frame_counter, total_frames, seek_frame_offset; uint8_t *bit_buffer; int elapsed = 0; size_t resume_offset; + intptr_t param; + enum codec_command_action action = CODEC_ACTION_NULL; -next_track: if (codec_init()) { DEBUGF("codec init failed\n"); return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - resume_offset = ci->id3->offset; codec_set_replaygain(ci->id3); @@ -60,84 +58,88 @@ next_track: ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */ ci->configure(DSP_SET_STEREO_MODE, ci->id3->channels == 1 ? STEREO_MONO : STEREO_NONINTERLEAVED); - - res =atrac3_decode_init(&q, ci->id3); + + ci->seek_buffer(0); + + res = atrac3_decode_init(&q, ci->id3); if(res < 0) { DEBUGF("failed to initialize OMA atrac decoder\n"); return CODEC_ERROR; } + total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE; + frame_counter = 0; + /* check for a mid-track resume and force a seek time accordingly */ if(resume_offset > ci->id3->first_frame_offset) { resume_offset -= ci->id3->first_frame_offset; /* calculate resume_offset in frames */ resume_offset = (int)resume_offset / FRAMESIZE; - ci->seek_time = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE); + param = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE); + action = CODEC_ACTION_SEEK_TIME; + } + else { + ci->set_elapsed(0); + ci->seek_buffer(ci->id3->first_frame_offset); } - total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE; - frame_counter = 0; - - ci->set_elapsed(0); - ci->seek_buffer(0); - ci->advance_buffer(ci->id3->first_frame_offset); /* The main decoder loop */ -seek_start : while(frame_counter < total_frames) - { + { + if (action == CODEC_ACTION_NULL) + action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) + break; + bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); - ci->yield(); - if (ci->stop_codec || ci->new_track) - goto done; - - if (ci->seek_time) { - ci->set_elapsed(ci->seek_time); - - /* Do not allow seeking beyond the file's length */ - if ((unsigned) ci->seek_time > ci->id3->length) { - ci->seek_complete(); - goto done; - } - - /* Seek to the start of the track */ - if (ci->seek_time == 1) { - ci->set_elapsed(0); - ci->seek_complete(); - ci->seek_buffer(ci->id3->first_frame_offset); - elapsed = 0; - goto seek_start; - } - seek_frame_offset = (ci->seek_time * BITRATE) / (8 * FRAMESIZE); - frame_counter = seek_frame_offset; - ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE); - bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); - elapsed = ci->seek_time; - - ci->set_elapsed(elapsed); - ci->seek_complete(); - } - - res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE); - - if(res != (int)FRAMESIZE) { - DEBUGF("codec error\n"); - return CODEC_ERROR; - } - - if(datasize) - ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, q.samples_per_frame / ci->id3->channels); - - elapsed += (FRAMESIZE * 8) / BITRATE; + if (action == CODEC_ACTION_SEEK_TIME) { + /* Do not allow seeking beyond the file's length */ + if ((unsigned) param > ci->id3->length) { + ci->set_elapsed(ci->id3->length); + ci->seek_complete(); + break; + } + + /* Seek to the start of the track */ + if (param == 0) { + elapsed = 0; + ci->set_elapsed(0); + ci->seek_buffer(ci->id3->first_frame_offset); + ci->seek_complete(); + action = CODEC_ACTION_NULL; + continue; + } + + seek_frame_offset = (param * BITRATE) / (8 * FRAMESIZE); + frame_counter = seek_frame_offset; + ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE); + bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); + elapsed = param; ci->set_elapsed(elapsed); - - ci->advance_buffer(FRAMESIZE); - frame_counter++; - } + ci->seek_complete(); + } + + action = CODEC_ACTION_NULL; - done: - if (ci->request_next_track()) - goto next_track; + res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE); + + if(res != (int)FRAMESIZE) { + DEBUGF("codec error\n"); + return CODEC_ERROR; + } + + if(datasize) + ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, + q.samples_per_frame / ci->id3->channels); + + elapsed += (FRAMESIZE * 8) / BITRATE; + ci->set_elapsed(elapsed); + + ci->advance_buffer(FRAMESIZE); + frame_counter++; + } return CODEC_OK; } diff --git a/apps/codecs/atrac3_rm.c b/apps/codecs/atrac3_rm.c index 6a77d24283..1322e917ed 100644 --- a/apps/codecs/atrac3_rm.c +++ b/apps/codecs/atrac3_rm.c @@ -41,9 +41,9 @@ static void init_rm(RMContext *rmctx) memcpy(ci->id3->id3v2buf, (char*)rmctx->codec_extradata, rmctx->extradata_size*sizeof(char)); } -/* this is the codec entry point */ -enum codec_status codec_main(void) -{ +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ static size_t buff_size; int datasize, res, consumed, i, time_offset; uint8_t *bit_buffer; @@ -52,16 +52,14 @@ enum codec_status codec_main(void) int scrambling_unit_size, num_units, elapsed = 0; int playback_on = -1; size_t resume_offset; + intptr_t param; + enum codec_command_action action = CODEC_ACTION_NULL; -next_track: if (codec_init()) { DEBUGF("codec init failed\n"); return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - resume_offset = ci->id3->offset; codec_set_replaygain(ci->id3); @@ -69,6 +67,7 @@ next_track: ci->memset(&pkt,0,sizeof(RMPacket)); ci->memset(&q,0,sizeof(ATRAC3Context)); + ci->seek_buffer(0); init_rm(&rmctx); ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); @@ -84,22 +83,25 @@ next_track: h = rmctx.sub_packet_h; scrambling_unit_size = h*fs; - res =atrac3_decode_init(&q, ci->id3); + res = atrac3_decode_init(&q, ci->id3); if(res < 0) { DEBUGF("failed to initialize RM atrac decoder\n"); return CODEC_ERROR; } - + /* check for a mid-track resume and force a seek time accordingly */ if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; num_units = (int)resume_offset / scrambling_unit_size; /* put number of subpackets to skip in resume_offset */ resume_offset /= (sps + PACKET_HEADER_SIZE); - ci->seek_time = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); + param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); + action = CODEC_ACTION_SEEK_TIME; } - - ci->set_elapsed(0); + else { + ci->set_elapsed(0); + } + ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); /* The main decoder loop */ @@ -115,22 +117,23 @@ seek_start : return CODEC_ERROR; } else - goto done; + return CODEC_OK; } for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) { - ci->yield(); - if (ci->stop_codec || ci->new_track) - goto done; + if (action == CODEC_ACTION_NULL) + action = ci->get_command(¶m); - if (ci->seek_time) { - ci->set_elapsed(ci->seek_time); + if (action == CODEC_ACTION_HALT) + return CODEC_OK; + if (action == CODEC_ACTION_SEEK_TIME) { /* Do not allow seeking beyond the file's length */ - if ((unsigned) ci->seek_time > ci->id3->length) { + if ((unsigned) param > ci->id3->length) { + ci->set_elapsed(ci->id3->length); ci->seek_complete(); - goto done; + return CODEC_OK; } ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); @@ -139,12 +142,13 @@ seek_start : rmctx.frame_number = 0; /* Seek to the start of the track */ - if (ci->seek_time == 1) { + if (param == 0) { ci->set_elapsed(0); ci->seek_complete(); + action = CODEC_ACTION_NULL; goto seek_start; } - num_units = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); + num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); @@ -155,12 +159,12 @@ seek_start : return CODEC_ERROR; } else - goto done; + return CODEC_OK; } packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; - rmctx.frame_number = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate)); - while(rmctx.audiotimestamp > (unsigned) ci->seek_time) { + rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate)); + while(rmctx.audiotimestamp > (unsigned) param) { rmctx.audio_pkt_cnt = 0; ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); @@ -168,16 +172,19 @@ seek_start : packet_count += rmctx.audio_pkt_cnt; num_units--; } - time_offset = ci->seek_time - rmctx.audiotimestamp; + time_offset = param - rmctx.audiotimestamp; i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i; ci->set_elapsed(elapsed); ci->seek_complete(); } + + action = CODEC_ACTION_NULL; + if(pkt.length) res = atrac3_decode_frame(rmctx.block_align, &q, &datasize, pkt.frames[i], rmctx.block_align); else /* indicates that there are no remaining frames */ - goto done; + return CODEC_OK; if(res != rmctx.block_align) { DEBUGF("codec error\n"); @@ -196,9 +203,5 @@ seek_start : ci->advance_buffer(consumed); } - done : - if (ci->request_next_track()) - goto next_track; - - return CODEC_OK; + return CODEC_OK; } diff --git a/apps/codecs/au.c b/apps/codecs/au.c index 3f9436c9e7..e06f931cf9 100644 --- a/apps/codecs/au.c +++ b/apps/codecs/au.c @@ -106,9 +106,19 @@ static int convert_au_format(unsigned int encoding, struct pcm_format *fmt) } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { - int status; struct pcm_format format; uint32_t bytesdone, decodedsamples; size_t n; @@ -119,22 +129,13 @@ enum codec_status codec_main(void) off_t firstblockposn; /* position of the first block in file */ const struct pcm_codec *codec; int offset = 0; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); - -next_track: - status = CODEC_OK; - + intptr_t param; + if (codec_init()) { DEBUGF("codec_init() error\n"); - status = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - codec_set_replaygain(ci->id3); /* Need to save offset for later use (cleared indirectly by advance_buffer) */ @@ -145,6 +146,7 @@ next_track: format.is_little_endian = false; /* set format */ + ci->seek_buffer(0); buf = ci->request_buffer(&n, 24); if (n < 24 || (memcmp(buf, ".snd", 4) != 0)) { @@ -170,8 +172,7 @@ next_track: if (offset < 24) { DEBUGF("CODEC_ERROR: sun audio offset size is small: %d\n", offset); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* data size */ format.numbytes = get_be32(buf + 8); @@ -182,8 +183,7 @@ next_track: if (format.formattag == AU_FORMAT_UNSUPPORT) { DEBUGF("CODEC_ERROR: sun audio unsupport format: %d\n", get_be32(buf + 12)); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* skip sample rate */ format.channels = get_be32(buf + 20); @@ -202,20 +202,17 @@ next_track: if (!codec) { DEBUGF("CODEC_ERROR: unsupport sun audio format: %x\n", (int)format.formattag); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (!codec->set_format(&format)) { - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.numbytes == 0) { DEBUGF("CODEC_ERROR: data size is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* check chunksize */ @@ -225,8 +222,7 @@ next_track: if (format.chunksize == 0) { DEBUGF("CODEC_ERROR: chunksize is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); @@ -236,8 +232,7 @@ next_track: ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); } else { DEBUGF("CODEC_ERROR: more than 2 channels\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* make sure we're at the correct offset */ @@ -253,7 +248,6 @@ next_track: bytesdone = newpos->pos; decodedsamples = newpos->samples; } - ci->seek_complete(); } else { /* already where we need to be */ bytesdone = 0; @@ -263,22 +257,29 @@ next_track: endofstream = 0; while (!endofstream) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - } - if (ci->seek_time) { + if (action == CODEC_ACTION_SEEK_TIME) { /* 3rd args(read_buffer) is unnecessary in the format which Sun Audio supports. */ - struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); + struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL); if (newpos->pos > format.numbytes) + { + ci->set_elapsed(ci->id3->length); + ci->seek_complete(); break; + } + if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } + + ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); ci->seek_complete(); } @@ -290,11 +291,10 @@ next_track: endofstream = 1; } - status = codec->decode(aubuf, n, samples, &bufcount); - if (status == CODEC_ERROR) + if (codec->decode(aubuf, n, samples, &bufcount) == CODEC_ERROR) { DEBUGF("codec error\n"); - goto done; + return CODEC_ERROR; } ci->pcmbuf_insert(samples, NULL, bufcount); @@ -308,9 +308,5 @@ next_track: } done: - if (ci->request_next_track()) - goto next_track; - -exit: - return status; + return CODEC_OK; } diff --git a/apps/codecs/codec_crt0.c b/apps/codecs/codec_crt0.c index cf14e460ec..33876272c6 100644 --- a/apps/codecs/codec_crt0.c +++ b/apps/codecs/codec_crt0.c @@ -27,39 +27,45 @@ struct codec_api *ci DATA_ATTR; extern unsigned char plugin_bss_start[]; extern unsigned char plugin_end_addr[]; -extern enum codec_status codec_main(void); +extern enum codec_status codec_main(enum codec_entry_call_reason reason); /* stub, the entry point is called via its reference in __header to * avoid warning with certain compilers */ int _start(void) {return 0;} -enum codec_status codec_start(void) +enum codec_status codec_start(enum codec_entry_call_reason reason) { #if (CONFIG_PLATFORM & PLATFORM_NATIVE) -#ifdef USE_IRAM - extern char iramcopy[], iramstart[], iramend[], iedata[], iend[]; - size_t iram_size = iramend - iramstart; - size_t ibss_size = iend - iedata; - if (iram_size > 0 || ibss_size > 0) + if (reason == CODEC_LOAD) { - ci->memcpy(iramstart, iramcopy, iram_size); - ci->memset(iedata, 0, ibss_size); - /* make the icache (if it exists) up to date with the new code */ +#ifdef USE_IRAM + extern char iramcopy[], iramstart[], iramend[], iedata[], iend[]; + size_t iram_size = iramend - iramstart; + size_t ibss_size = iend - iedata; + if (iram_size > 0 || ibss_size > 0) + { + ci->memcpy(iramstart, iramcopy, iram_size); + ci->memset(iedata, 0, ibss_size); + /* make the icache (if it exists) up to date with the new code */ + ci->cpucache_invalidate(); + /* barrier to prevent reordering iram copy and BSS clearing, + * because the BSS segment alias the IRAM copy. + */ + asm volatile ("" ::: "memory"); + } +#endif /* PLUGIN_USE_IRAM */ + ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); + /* Some parts of bss may be used via a no-cache alias (at least + * portalplayer has this). If we don't clear the cache, those aliases + * may read garbage */ ci->cpucache_invalidate(); - /* barrier to prevent reordering iram copy and BSS clearing, - * because the BSS segment alias the IRAM copy. - */ - asm volatile ("" ::: "memory"); } -#endif /* PLUGIN_USE_IRAM */ - ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); - /* Some parts of bss may be used via a no-cache alias (at least - * portalplayer has this). If we don't clear the cache, those aliases - * may read garbage */ - ci->cpucache_invalidate(); -#endif +#endif /* CONFIG_PLATFORM */ - return codec_main(); + /* Note: If for any reason codec_main would not be called with CODEC_LOAD + * because the above code failed then it must not be ever be called with + * any other value and some strategy to avoid doing so must be conceived */ + return codec_main(reason); } #if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE) diff --git a/apps/codecs/cook.c b/apps/codecs/cook.c index 015618986c..a6b4a1153e 100644 --- a/apps/codecs/cook.c +++ b/apps/codecs/cook.c @@ -38,9 +38,9 @@ static void init_rm(RMContext *rmctx) memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext)); } -/* this is the codec entry point */ -enum codec_status codec_main(void) -{ +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ static size_t buff_size; int datasize, res, consumed, i, time_offset; uint8_t *bit_buffer; @@ -48,16 +48,14 @@ enum codec_status codec_main(void) uint32_t packet_count; int scrambling_unit_size, num_units; size_t resume_offset; + intptr_t param = 0; + enum codec_command_action action = CODEC_ACTION_NULL; -next_track: if (codec_init()) { DEBUGF("codec init failed\n"); return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - resume_offset = ci->id3->offset; codec_set_replaygain(ci->id3); @@ -65,6 +63,8 @@ next_track: ci->memset(&pkt,0,sizeof(RMPacket)); ci->memset(&q,0,sizeof(COOKContext)); + ci->seek_buffer(0); + init_rm(&rmctx); ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); @@ -87,20 +87,21 @@ next_track: DEBUGF("failed to initialize cook decoder\n"); return CODEC_ERROR; } - + /* check for a mid-track resume and force a seek time accordingly */ if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; num_units = (int)resume_offset / scrambling_unit_size; /* put number of subpackets to skip in resume_offset */ resume_offset /= (sps + PACKET_HEADER_SIZE); - ci->seek_time = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); + param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); + action = CODEC_ACTION_SEEK_TIME; } ci->set_elapsed(0); ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); - /* The main decoder loop */ + /* The main decoder loop */ seek_start : while(packet_count) { @@ -112,18 +113,19 @@ seek_start : } for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) - { - ci->yield(); - if (ci->stop_codec || ci->new_track) - goto done; + { + if (action == CODEC_ACTION_NULL) + action = ci->get_command(¶m); - if (ci->seek_time) { - ci->set_elapsed(ci->seek_time); + if (action == CODEC_ACTION_HALT) + return CODEC_OK; + if (action == CODEC_ACTION_SEEK_TIME) { /* Do not allow seeking beyond the file's length */ - if ((unsigned) ci->seek_time > ci->id3->length) { + if ((unsigned) param > ci->id3->length) { + ci->set_elapsed(ci->id3->length); ci->seek_complete(); - goto done; + return CODEC_OK; } ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); @@ -132,22 +134,24 @@ seek_start : rmctx.frame_number = 0; /* Seek to the start of the track */ - if (ci->seek_time == 1) { + if (param == 0) { ci->set_elapsed(0); ci->seek_complete(); + action = CODEC_ACTION_NULL; goto seek_start; } - num_units = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); + num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); if(consumed < 0) { DEBUGF("rm_get_packet failed\n"); - return CODEC_ERROR; + ci->seek_complete(); + return CODEC_ERROR; } packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; - rmctx.frame_number = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate)); - while(rmctx.audiotimestamp > (unsigned) ci->seek_time) { + rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate)); + while(rmctx.audiotimestamp > (unsigned) param) { rmctx.audio_pkt_cnt = 0; ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); @@ -155,11 +159,14 @@ seek_start : packet_count += rmctx.audio_pkt_cnt; num_units--; } - time_offset = ci->seek_time - rmctx.audiotimestamp; + time_offset = param - rmctx.audiotimestamp; i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); ci->seek_complete(); - } + } + + action = CODEC_ACTION_NULL; + res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], rmctx.block_align); rmctx.frame_number++; @@ -181,9 +188,5 @@ seek_start : ci->advance_buffer(consumed); } - done : - if (ci->request_next_track()) - goto next_track; - - return CODEC_OK; + return CODEC_OK; } diff --git a/apps/codecs/flac.c b/apps/codecs/flac.c index 89d14b98a7..a5521b584f 100644 --- a/apps/codecs/flac.c +++ b/apps/codecs/flac.c @@ -418,40 +418,40 @@ static bool flac_seek_offset(FLACContext* fc, uint32_t offset) { } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { int8_t *buf; FLACContext fc; - uint32_t samplesdone = 0; + uint32_t samplesdone; uint32_t elapsedtime; size_t bytesleft; int consumed; int res; int frame; - int retval; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1); + intptr_t param; -next_track: - retval = CODEC_OK; - if (codec_init()) { LOGF("FLAC: Error initialising codec\n"); - retval = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - /* Need to save offset for later use (cleared indirectly by flac_init) */ samplesdone = ci->id3->offset; if (!flac_init(&fc,ci->id3->first_frame_offset)) { LOGF("FLAC: Error initialising codec\n"); - retval = CODEC_ERROR; - goto done; + return CODEC_ERROR; } ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); @@ -459,35 +459,34 @@ next_track: STEREO_MONO : STEREO_NONINTERLEAVED); codec_set_replaygain(ci->id3); - if (samplesdone) { - flac_seek_offset(&fc, samplesdone); - samplesdone=0; - } + flac_seek_offset(&fc, samplesdone); + samplesdone=0; /* The main decoding loop */ frame=0; buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); while (bytesleft) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - } /* Deal with any pending seek requests */ - if (ci->seek_time) { - if (flac_seek(&fc,(uint32_t)(((uint64_t)(ci->seek_time-1) + if (action == CODEC_ACTION_SEEK_TIME) { + if (flac_seek(&fc,(uint32_t)(((uint64_t)param *ci->id3->frequency)/1000))) { /* Refill the input buffer */ buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); } + + ci->set_elapsed(param); ci->seek_complete(); } if((res=flac_decode_frame(&fc,decoded0,decoded1,buf, bytesleft,ci->yield)) < 0) { LOGF("FLAC: Frame %d, error %d\n",frame,res); - retval = CODEC_ERROR; - goto done; + return CODEC_ERROR; } consumed=fc.gb.index/8; frame++; @@ -507,14 +506,7 @@ next_track: buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); } - retval = CODEC_OK; -done: LOGF("FLAC: Decoded %lu samples\n",(unsigned long)samplesdone); - - if (ci->request_next_track()) - goto next_track; - -exit: - return retval; + return CODEC_OK; } diff --git a/apps/codecs/lib/codeclib.c b/apps/codecs/lib/codeclib.c index af0894c498..443c0bbdcf 100644 --- a/apps/codecs/lib/codeclib.c +++ b/apps/codecs/lib/codeclib.c @@ -33,6 +33,16 @@ unsigned char* mp3buf; // The actual MP3 buffer from Rockbox unsigned char* mallocbuf; // 512K from the start of MP3 buffer unsigned char* filebuf; // The rest of the MP3 buffer +/* this is the default codec entry point for when nothing needs to be done + on load or unload */ +enum codec_status __attribute__((weak)) +codec_main(enum codec_entry_call_reason reason) +{ + /* Nothing to do */ + return CODEC_OK; + (void)reason; +} + int codec_init(void) { mem_ptr = 0; @@ -41,7 +51,7 @@ int codec_init(void) return 0; } -void codec_set_replaygain(struct mp3entry* id3) +void codec_set_replaygain(const struct mp3entry *id3) { ci->configure(DSP_SET_TRACK_GAIN, id3->track_gain); ci->configure(DSP_SET_ALBUM_GAIN, id3->album_gain); @@ -49,19 +59,6 @@ void codec_set_replaygain(struct mp3entry* id3) ci->configure(DSP_SET_ALBUM_PEAK, id3->album_peak); } -/* Note: codec really needs its own private metdata copy for the current - track being processed in order to be stable. */ -int codec_wait_taginfo(void) -{ - while (!*ci->taginfo_ready && !ci->stop_codec && !ci->new_track) - ci->sleep(0); - if (ci->stop_codec) - return -1; - if (ci->new_track) - return 1; - return 0; -} - /* Various "helper functions" common to all the xxx2wav decoder plugins */ diff --git a/apps/codecs/lib/codeclib.h b/apps/codecs/lib/codeclib.h index 41b466ed1f..30091c5333 100644 --- a/apps/codecs/lib/codeclib.h +++ b/apps/codecs/lib/codeclib.h @@ -156,8 +156,7 @@ static inline unsigned int bs_generic(unsigned int v, int mode) /* Various codec helper functions */ int codec_init(void); -void codec_set_replaygain(struct mp3entry* id3); -int codec_wait_taginfo(void); /* 0 = success */ +void codec_set_replaygain(const struct mp3entry *id3); #ifdef RB_PROFILE void __cyg_profile_func_enter(void *this_fn, void *call_site) diff --git a/apps/codecs/mod.c b/apps/codecs/mod.c index 4ace721a1e..3dfaac663f 100644 --- a/apps/codecs/mod.c +++ b/apps/codecs/mod.c @@ -1218,47 +1218,37 @@ void synthrender(int32_t *renderbuffer, int samplecount) } } +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Make use of 44.1khz */ + ci->configure(DSP_SET_FREQUENCY, 44100); + /* Sample depth is 28 bit host endian */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 28); + /* Stereo output */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); + } + + return CODEC_OK; +} -enum codec_status codec_main(void) +/* this is called for each file to process */ +enum codec_status codec_run(void) { size_t n; unsigned char *modfile; int old_patterntableposition; - int bytesdone; + intptr_t param; -next_track: if (codec_init()) { return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto request_next_track; - codec_set_replaygain(ci->id3); /* Load MOD file */ - /* - * This is the save way - - size_t bytesfree; - unsigned int filesize; - - p = modfile; - bytesfree=sizeof(modfile); - while ((n = ci->read_filebuf(p, bytesfree)) > 0) { - p += n; - bytesfree -= n; - if (bytesfree == 0) - return CODEC_ERROR; - } - filesize = p-modfile; - - if (filesize == 0) - return CODEC_ERROR; - */ - - /* Directly use mod in buffer */ ci->seek_buffer(0); modfile = ci->request_buffer(&n, ci->filesize); if (!modfile || n < (size_t)ci->filesize) { @@ -1268,27 +1258,22 @@ next_track: initmodplayer(); loadmod(modfile); - /* Make use of 44.1khz */ - ci->configure(DSP_SET_FREQUENCY, 44100); - /* Sample depth is 28 bit host endian */ - ci->configure(DSP_SET_SAMPLE_DEPTH, 28); - /* Stereo output */ - ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); - /* The main decoder loop */ ci->set_elapsed(0); bytesdone = 0; old_patterntableposition = 0; while (1) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) { - /* New time is ready in ci->seek_time */ - modplayer.patterntableposition = ci->seek_time/1000; + if (action == CODEC_ACTION_SEEK_TIME) { + /* New time is ready in param */ + modplayer.patterntableposition = param/1000; modplayer.currentline = 0; + ci->set_elapsed(modplayer.patterntableposition*1000+500); ci->seek_complete(); } @@ -1305,9 +1290,5 @@ next_track: } -request_next_track: - if (ci->request_next_track()) - goto next_track; - return CODEC_OK; } diff --git a/apps/codecs/mp3_enc.c b/apps/codecs/mp3_enc.c index e7893fd14a..2f5528f74c 100644 --- a/apps/codecs/mp3_enc.c +++ b/apps/codecs/mp3_enc.c @@ -2584,45 +2584,46 @@ static bool enc_init(void) return true; } /* enc_init */ -enum codec_status codec_main(void) +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) { - /* Generic codec initialisation */ - if (!enc_init()) - return CODEC_ERROR; + if (reason == CODEC_LOAD) { + if (!enc_init()) + return CODEC_ERROR; + } + else if (reason == CODEC_UNLOAD) { + /* reset parameters to initial state */ + ci->enc_set_parameters(NULL); + } + + return CODEC_OK; +} +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ /* main encoding loop */ - while (!ci->stop_codec) + while(ci->get_command(NULL) != CODEC_ACTION_HALT) { - char *buffer; - - while ((buffer = ci->enc_get_pcm_data(pcm_chunk_size)) != NULL) - { - struct enc_chunk_hdr *chunk; - - if (ci->stop_codec) - break; + char *buffer = buffer = ci->enc_get_pcm_data(pcm_chunk_size); + struct enc_chunk_hdr *chunk; - chunk = ci->enc_get_chunk(); - chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); + if(buffer == NULL) + continue; - encode_frame(buffer, chunk); + chunk = ci->enc_get_chunk(); + chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); - if (chunk->num_pcm < samp_per_frame) - { - ci->enc_unget_pcm_data(pcm_chunk_size - chunk->num_pcm*4); - chunk->num_pcm = samp_per_frame; - } + encode_frame(buffer, chunk); - ci->enc_finish_chunk(); - - ci->yield(); + if (chunk->num_pcm < samp_per_frame) + { + ci->enc_unget_pcm_data(pcm_chunk_size - chunk->num_pcm*4); + chunk->num_pcm = samp_per_frame; } - ci->yield(); + ci->enc_finish_chunk(); } - /* reset parameters to initial state */ - ci->enc_set_parameters(NULL); - return CODEC_OK; -} /* codec_start */ +} diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c index 4b49775029..c9e2131450 100644 --- a/apps/codecs/mpa.c +++ b/apps/codecs/mpa.c @@ -268,8 +268,8 @@ static bool mad_synth_thread_create(void) static void mad_synth_thread_quit(void) { - /*mop up COP thread*/ - die=1; + /* mop up COP thread */ + die = 1; ci->semaphore_release(&synth_pending_sem); ci->thread_wait(mad_synth_thread_id); ci->cpucache_invalidate(); @@ -299,9 +299,30 @@ static inline void mad_synth_thread_unwait_pcm(void) #endif /* MPA_SYNTH_ON_COP */ /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Create a decoder instance */ + if (codec_init()) + return CODEC_ERROR; + + ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); + + /* does nothing on 1 processor systems except return true */ + if(!mad_synth_thread_create()) + return CODEC_ERROR; + } + else if (reason == CODEC_UNLOAD) { + /* mop up COP thread - MT only */ + mad_synth_thread_quit(); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { - int status; size_t size; int file_end; int samples_to_skip; /* samples to skip in total for this file (at start) */ @@ -312,27 +333,12 @@ enum codec_status codec_main(void) unsigned long current_frequency = 0; int framelength; int padding = MAD_BUFFER_GUARD; /* to help mad decode the last frame */ - - if (codec_init()) - return CODEC_ERROR; - - /* Create a decoder instance */ - - ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); - - /*does nothing on 1 processor systems except return true*/ - if(!mad_synth_thread_create()) - return CODEC_ERROR; - -next_track: - status = CODEC_OK; + intptr_t param; /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */ init_mad(); file_end = 0; - if (codec_wait_taginfo() != 0) - goto request_next_track; ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); current_frequency = ci->id3->frequency; @@ -379,29 +385,35 @@ next_track: /* This is the decoding loop. */ while (1) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) { + if (action == CODEC_ACTION_SEEK_TIME) { int newpos; /*make sure the synth thread is idle before seeking - MT only*/ mad_synth_thread_wait_pcm(); mad_synth_thread_unwait_pcm(); - samplesdone = ((int64_t)(ci->seek_time-1))*current_frequency/1000; + samplesdone = ((int64_t)param)*current_frequency/1000; - if (ci->seek_time-1 == 0) { + if (param == 0) { newpos = ci->id3->first_frame_offset; samples_to_skip = start_skip; } else { - newpos = get_file_pos(ci->seek_time-1); + newpos = get_file_pos(param); samples_to_skip = 0; } if (!ci->seek_buffer(newpos)) + { + ci->seek_complete(); break; + } + + ci->set_elapsed((samplesdone * 1000) / current_frequency); ci->seek_complete(); init_mad(); framelength = 0; @@ -435,8 +447,7 @@ next_track: continue; } else { /* Some other unrecoverable error */ - status = CODEC_ERROR; - break; + return CODEC_ERROR; } } @@ -504,12 +515,5 @@ next_track: framelength - stop_skip); } -request_next_track: - if (ci->request_next_track()) - goto next_track; - - /*mop up COP thread - MT only*/ - mad_synth_thread_quit(); - - return status; + return CODEC_OK; } diff --git a/apps/codecs/mpc.c b/apps/codecs/mpc.c index 187c37e597..bbe2d9943b 100644 --- a/apps/codecs/mpc.c +++ b/apps/codecs/mpc.c @@ -52,8 +52,20 @@ static mpc_int32_t get_size_impl(mpc_reader *reader) return ci->filesize; } -/* This is the codec entry point. */ -enum codec_status codec_main(void) +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* musepack's sample representation is 18.14 + * DSP_SET_SAMPLE_DEPTH = 14 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 29 */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 29); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { mpc_int64_t samplesdone; uint32_t frequency; /* 0.1 kHz accuracy */ @@ -64,39 +76,27 @@ enum codec_status codec_main(void) mpc_streaminfo info; mpc_frame_info frame; mpc_demux *demux = NULL; - int retval; + intptr_t param; frame.buffer = sample_buffer; - - /* musepack's sample representation is 18.14 - * DSP_SET_SAMPLE_DEPTH = 14 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 29 */ - ci->configure(DSP_SET_SAMPLE_DEPTH, 29); - + /* Create a decoder instance */ reader.read = read_impl; reader.seek = seek_impl; reader.tell = tell_impl; reader.get_size = get_size_impl; -next_track: - retval = CODEC_OK; - if (codec_init()) - { - retval = CODEC_ERROR; - goto exit; - } + return CODEC_ERROR; - if (codec_wait_taginfo() != 0) - goto done; + /* Prep position */ + ci->seek_buffer(0); /* Initialize demux/decoder. */ demux = mpc_demux_init(&reader); if (NULL == demux) - { - retval = CODEC_ERROR; - goto done; - } + return CODEC_ERROR; + /* Read file's streaminfo data. */ mpc_demux_get_info(demux, &info); @@ -117,11 +117,8 @@ next_track: ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); else if (info.channels == 1) ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); - else - { - retval = CODEC_ERROR; - goto done; - } + else + return CODEC_ERROR; codec_set_replaygain(ci->id3); @@ -142,21 +139,24 @@ next_track: /* This is the decoding loop. */ do { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) + return CODEC_OK; + /* Complete seek handler. */ - if (ci->seek_time) + if (action == CODEC_ACTION_SEEK_TIME) { - mpc_int64_t new_offset = ((ci->seek_time - 1)/10)*frequency; + mpc_int64_t new_offset = (param/10)*frequency; if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK) { samplesdone = new_offset; - ci->set_elapsed(ci->seek_time); } + + elapsed_time = (samplesdone*10)/frequency; + ci->set_elapsed(elapsed_time); ci->seek_complete(); } - - /* Stop or skip occured, exit decoding loop. */ - if (ci->stop_codec || ci->new_track) - break; /* Decode one frame. */ status = mpc_demux_decode(demux, &frame); @@ -164,8 +164,7 @@ next_track: if (frame.bits == -1) { /* Decoding error, exit decoding loop. */ - retval = (status == MPC_STATUS_OK) ? CODEC_OK : CODEC_ERROR; - goto done; + return (status == MPC_STATUS_OK) ? CODEC_OK : CODEC_ERROR; } else { @@ -181,11 +180,4 @@ next_track: ci->set_offset( (samplesdone * byterate)/(frequency*100) ); } } while (true); - -done: - if (ci->request_next_track()) - goto next_track; - -exit: - return retval; } diff --git a/apps/codecs/nsf.c b/apps/codecs/nsf.c index 2f37da81d2..72f6974214 100644 --- a/apps/codecs/nsf.c +++ b/apps/codecs/nsf.c @@ -4307,46 +4307,44 @@ static void set_codec_track(int t, int d) { nSilenceTrackMS=5000; SetFadeTime(track,track+fade, fNSFPlaybackSpeed,def); } - ci->id3->elapsed=d*1000; /* d is track no to display */ + ci->set_elapsed(d*1000); /* d is track no to display */ } +/** Operational info **/ +static int track = 0; +static char last_path[MAX_PATH]; +static int dontresettrack = 0; + /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* we only render 16 bits, 44.1KHz, Stereo */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 16); + ci->configure(DSP_SET_FREQUENCY, 44100); + ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); + + RebuildOutputTables(); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { int written; uint8_t *buf; size_t n; int endofstream; /* end of stream flag */ - int track; - int dontresettrack; - char last_path[MAX_PATH]; - int usingplaylist; - - /* we only render 16 bits */ - ci->configure(DSP_SET_SAMPLE_DEPTH, 16); - - ci->configure(DSP_SET_FREQUENCY, 44100); - ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); - - RebuildOutputTables(); - - dontresettrack=0; - last_path[0]='\0'; - track=0; + int usingplaylist = 0; -next_track: - usingplaylist=0; DEBUGF("NSF: next_track\n"); if (codec_init()) { return CODEC_ERROR; } DEBUGF("NSF: after init\n"); - - /* wait for track info to load */ - if (codec_wait_taginfo() != 0) - goto request_next_track; - codec_set_replaygain(ci->id3); /* Read the entire file */ @@ -4408,22 +4406,27 @@ init_nsf: reset_profile_timers(); while (!endofstream) { + intptr_t param; + enum codec_command_action action = ci->get_command(¶m); - ci->yield(); - if (ci->stop_codec || ci->new_track) { + if (action == CODEC_ACTION_HALT) break; - } - if (ci->seek_time >0) { - track=ci->seek_time/1000; - if (usingplaylist) { - if (track>=nPlaylistSize) break; - } else { - if (track>=nTrackCount) break; + if (action == CODEC_ACTION_SEEK_TIME) { + if (param > 0) { + track=param/1000; + if (usingplaylist) { + if (track>=nPlaylistSize) break; + } else { + if (track>=nTrackCount) break; + } + dontresettrack=1; + ci->seek_complete(); + goto init_nsf; + } + else { + ci->seek_complete(); } - ci->seek_complete(); - dontresettrack=1; - goto init_nsf; } ENTER_TIMER(total); @@ -4449,22 +4452,17 @@ init_nsf: print_timers(last_path,track); -request_next_track: - if (ci->request_next_track()) { if (ci->global_settings->repeat_mode==REPEAT_ONE) { /* in repeat one mode just advance to the next track */ track++; if (track>=nTrackCount) track=0; dontresettrack=1; /* at this point we can't tell if another file has been selected */ - goto next_track; } else { /* otherwise do a proper load of the next file */ dontresettrack=0; last_path[0]='\0'; } - goto next_track; /* when we fall through here we'll reload the file */ - } return CODEC_OK; } diff --git a/apps/codecs/raac.c b/apps/codecs/raac.c index b322ae7df3..4b73f41462 100644 --- a/apps/codecs/raac.c +++ b/apps/codecs/raac.c @@ -35,8 +35,21 @@ static void init_rm(RMContext *rmctx) static RMContext rmctx; static RMPacket pkt; + /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); + ci->configure(DSP_SET_SAMPLE_DEPTH, 29); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { static NeAACDecFrameInfo frame_info; NeAACDecHandle decoder; @@ -49,26 +62,21 @@ enum codec_status codec_main(void) unsigned char c = 0; /* channels */ int playback_on = -1; size_t resume_offset; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); - ci->configure(DSP_SET_SAMPLE_DEPTH, 29); - -next_track: - err = CODEC_OK; + intptr_t param; + enum codec_command_action action = CODEC_ACTION_NULL; if (codec_init()) { DEBUGF("FAAD: Codec init error\n"); return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - resume_offset = ci->id3->offset; ci->memset(&rmctx,0,sizeof(RMContext)); ci->memset(&pkt,0,sizeof(RMPacket)); + + ci->seek_buffer(0); + init_rm(&rmctx); ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); codec_set_replaygain(ci->id3); @@ -78,9 +86,9 @@ next_track: if (!decoder) { DEBUGF("FAAD: Decode open error\n"); - err = CODEC_ERROR; - goto done; - } + return CODEC_ERROR; + } + NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); conf->outputFormat = FAAD_FMT_16BIT; /* irrelevant, we don't convert */ NeAACDecSetConfiguration(decoder, conf); @@ -91,8 +99,7 @@ next_track: if (err) { DEBUGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type); - err = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* check for a mid-track resume and force a seek time accordingly */ @@ -100,36 +107,38 @@ next_track: resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; /* put number of subpackets to skip in resume_offset */ resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); - ci->seek_time = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); + param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); + action = CODEC_ACTION_SEEK_TIME; } - - ci->id3->frequency = s; + + ci->id3->frequency = s; /* FIXME: Won't get it to the UI */ ci->set_elapsed(0); ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); /* The main decoding loop */ -seek_start: while (1) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + if (action == CODEC_ACTION_NULL) + action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - } - if (ci->seek_time) { - + if (action == CODEC_ACTION_SEEK_TIME) { /* Do not allow seeking beyond the file's length */ - if ((unsigned) ci->seek_time > ci->id3->length) { + if ((unsigned) param > ci->id3->length) { + ci->set_elapsed(ci->id3->length); ci->seek_complete(); - goto done; + break; } ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); /* Seek to the start of the track */ - if (ci->seek_time == 1) { + if (param == 0) { ci->set_elapsed(0); ci->seek_complete(); - goto seek_start; + action = CODEC_ACTION_NULL; + continue; } skipped = 0; @@ -141,21 +150,30 @@ seek_start: if(playback_on == -1) { /* Error only if packet-parsing failed and playback hadn't started */ DEBUGF("rm_get_packet failed\n"); + ci->seek_complete(); return CODEC_ERROR; } - else - goto done; + else { + ci->seek_complete(); + return CODEC_OK; + } } skipped += pkt.length; - if(pkt.timestamp > (unsigned)ci->seek_time) break; + + if(pkt.timestamp > (unsigned)param) + break; + ci->advance_buffer(pkt.length); } ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE); buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000); NeAACDecPostSeekReset(decoder, decoder->frame); + ci->set_elapsed(pkt.timestamp); ci->seek_complete(); } + action = CODEC_ACTION_NULL; + /* Request the required number of bytes from the input buffer */ buffer=ci->request_buffer(&n,rmctx.audio_framesize + 1000); consumed = rm_get_packet(&buffer, &rmctx, &pkt); @@ -167,20 +185,20 @@ seek_start: return CODEC_ERROR; } else - goto done; + break; } playback_on = 1; if (pkt.timestamp >= ci->id3->length) - goto done; + break; + /* Decode one block - returned samples will be host-endian */ for(i = 0; i < rmctx.sub_packet_cnt; i++) { ret = NeAACDecDecode(decoder, &frame_info, buffer, rmctx.sub_packet_lengths[i]); buffer += rmctx.sub_packet_lengths[i]; if (frame_info.error > 0) { DEBUGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error)); - err = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } ci->pcmbuf_insert(decoder->time_out[0], decoder->time_out[1], @@ -191,11 +209,5 @@ seek_start: ci->advance_buffer(pkt.length); } -done: - if (ci->request_next_track()) - goto next_track; - -exit: - return err; + return CODEC_OK; } - diff --git a/apps/codecs/shorten.c b/apps/codecs/shorten.c index 83a9c34da8..db66991679 100644 --- a/apps/codecs/shorten.c +++ b/apps/codecs/shorten.c @@ -37,7 +37,19 @@ static int32_t offset1[MAX_OFFSET_SIZE] IBSS_ATTR; static int8_t ibuf[MAX_BUFFER_SIZE] IBSS_ATTR; /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); + ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { ShortenContext sc; uint32_t samplesdone; @@ -45,21 +57,14 @@ enum codec_status codec_main(void) int8_t *buf; int consumed, res, nsamples; size_t bytesleft; + intptr_t param; - /* Generic codec initialisation */ - ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); - ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1); - -next_track: /* Codec initialization */ if (codec_init()) { LOGF("Shorten: codec_init error\n"); return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto request_next_track; - codec_set_replaygain(ci->id3); /* Shorten decoder initialization */ @@ -103,14 +108,15 @@ seek_start: samplesdone = 0; buf = ci->request_buffer(&bytesleft, MAX_BUFFER_SIZE); while (bytesleft) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - } /* Seek to start of track */ - if (ci->seek_time == 1) { - if (ci->seek_buffer(sc.header_bits/8 + ci->id3->first_frame_offset)) { + if (action == CODEC_ACTION_SEEK_TIME) { + if (param == 0 && + ci->seek_buffer(sc.header_bits/8 + ci->id3->first_frame_offset)) { sc.bitindex = sc.header_bits - 8*(sc.header_bits/8); ci->set_elapsed(0); ci->seek_complete(); @@ -128,7 +134,7 @@ seek_start: if (res == FN_ERROR) { LOGF("Shorten: shorten_decode_frames error (%lu)\n", (unsigned long)samplesdone); - break; + return CODEC_ERROR; } else { /* Insert decoded samples in pcmbuf */ if (nsamples) { @@ -153,9 +159,5 @@ seek_start: sc.bitindex = sc.gb.index - 8*consumed; } -request_next_track: - if (ci->request_next_track()) - goto next_track; - return CODEC_OK; } diff --git a/apps/codecs/sid.c b/apps/codecs/sid.c index 52c1289fff..0edbabe0b6 100644 --- a/apps/codecs/sid.c +++ b/apps/codecs/sid.c @@ -1203,34 +1203,47 @@ unsigned short LoadSIDFromMemory(void *pSidData, unsigned short *load_addr, return *load_addr; } +static int nSamplesRendered = 0; +static int nSamplesPerCall = 882; /* This is PAL SID single speed (44100/50Hz) */ +static int nSamplesToRender = 0; -enum codec_status codec_main(void) +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) { - unsigned int filesize; + if (reason == CODEC_LOAD) { + /* Make use of 44.1khz */ + ci->configure(DSP_SWITCH_FREQUENCY, 44100); + /* Sample depth is 28 bit host endian */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 28); + /* Mono output */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); + } + + return CODEC_OK; +} +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ + unsigned int filesize; unsigned short load_addr, init_addr, play_addr; unsigned char subSongsMax, subSong, song_speed; + intptr_t param; - int nSamplesRendered = 0; - int nSamplesPerCall = 882; /* This is PAL SID single speed (44100/50Hz) */ - int nSamplesToRender = 0; - -next_track: if (codec_init()) { return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto request_next_track; - codec_set_replaygain(ci->id3); /* Load SID file the read_filebuf callback will return the full requested - * size if at all possible, so there is no need to loop */ + * size if at all possible, so there is no need to loop */ + ci->seek_buffer(0); filesize = ci->read_filebuf(sidfile, sizeof(sidfile)); - if (filesize == 0) + if (filesize == 0) { return CODEC_ERROR; + } c64Init(44100); LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, @@ -1239,37 +1252,30 @@ next_track: cpuJSR(init_addr, subSong); /* Start the song initialize */ - /* Make use of 44.1khz */ - ci->configure(DSP_SWITCH_FREQUENCY, 44100); - /* Sample depth is 28 bit host endian */ - ci->configure(DSP_SET_SAMPLE_DEPTH, 28); - /* Mono output */ - ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); - - /* Set the elapsed time to the current subsong (in seconds) */ ci->set_elapsed(subSong*1000); /* The main decoder loop */ while (1) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) { - /* New time is ready in ci->seek_time */ + if (action == CODEC_ACTION_SEEK_TIME) { + /* New time is ready in param */ /* Start playing from scratch */ c64Init(44100); - LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, &subSongsMax, &subSong, &song_speed, filesize); - sidPoke(24, 15); /* Turn on full volume */ - subSong = ci->seek_time / 1000; /* Now use the current seek time in seconds as subsong */ - cpuJSR(init_addr, subSong); /* Start the song initialize */ - nSamplesToRender = 0; /* Start the rendering from scratch */ - - ci->seek_complete(); + LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, + &subSongsMax, &subSong, &song_speed, filesize); + sidPoke(24, 15); /* Turn on full volume */ + subSong = param / 1000; /* Now use the current seek time in seconds as subsong */ + cpuJSR(init_addr, subSong); /* Start the song initialize */ + nSamplesToRender = 0; /* Start the rendering from scratch */ /* Set the elapsed time to the current subsong (in seconds) */ + ci->seek_complete(); ci->set_elapsed(subSong*1000); } @@ -1306,9 +1312,5 @@ next_track: ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE); } -request_next_track: - if (ci->request_next_track()) - goto next_track; - return CODEC_OK; } diff --git a/apps/codecs/smaf.c b/apps/codecs/smaf.c index 3e8a41387d..9211daa9aa 100644 --- a/apps/codecs/smaf.c +++ b/apps/codecs/smaf.c @@ -332,9 +332,20 @@ static uint8_t *read_buffer(size_t *realsize) return buffer; } -enum codec_status codec_main(void) +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { - int status; uint32_t decodedsamples; size_t n; int bufcount; @@ -342,20 +353,10 @@ enum codec_status codec_main(void) uint8_t *smafbuf; off_t firstblockposn; /* position of the first block in file */ const struct pcm_codec *codec; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); + intptr_t param; -next_track: - status = CODEC_OK; - - if (codec_init()) { - status = CODEC_ERROR; - goto exit; - } - - if (codec_wait_taginfo() != 0) - goto done; + if (codec_init()) + return CODEC_ERROR; codec_set_replaygain(ci->id3); @@ -365,24 +366,22 @@ next_track: decodedsamples = 0; codec = 0; + ci->seek_buffer(0); if (!parse_header(&format, &firstblockposn)) { - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } codec = get_codec(format.formattag); if (codec == 0) { DEBUGF("CODEC_ERROR: unsupport audio format: 0x%x\n", (int)format.formattag); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (!codec->set_format(&format)) { - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* check chunksize */ @@ -392,8 +391,7 @@ next_track: if (format.chunksize == 0) { DEBUGF("CODEC_ERROR: chunksize is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); @@ -404,12 +402,10 @@ next_track: ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); } else { DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } ci->seek_buffer(firstblockposn); - ci->seek_complete(); /* make sure we're at the correct offset */ if (bytesdone > (uint32_t) firstblockposn) @@ -419,13 +415,13 @@ next_track: PCM_SEEK_POS, &read_buffer); if (newpos->pos > format.numbytes) - goto done; + return CODEC_OK; + if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } - ci->seek_complete(); } else { @@ -437,23 +433,32 @@ next_track: endofstream = 0; while (!endofstream) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) { - struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, + if (action == CODEC_ACTION_SEEK_TIME) { + struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, &read_buffer); if (newpos->pos > format.numbytes) + { + ci->set_elapsed(ci->id3->length); + ci->seek_complete(); break; + } + if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } + + ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); ci->seek_complete(); } + smafbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); if (n == 0) @@ -464,11 +469,10 @@ next_track: endofstream = 1; } - status = codec->decode(smafbuf, n, samples, &bufcount); - if (status == CODEC_ERROR) + if (codec->decode(smafbuf, n, samples, &bufcount) == CODEC_ERROR) { DEBUGF("codec error\n"); - goto done; + return CODEC_ERROR; } ci->pcmbuf_insert(samples, NULL, bufcount); @@ -482,11 +486,5 @@ next_track: ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); } -done: - if (ci->request_next_track()) - goto next_track; - -exit: - return status; + return CODEC_OK; } - diff --git a/apps/codecs/spc.c b/apps/codecs/spc.c index 4db2878964..1b49761810 100644 --- a/apps/codecs/spc.c +++ b/apps/codecs/spc.c @@ -260,14 +260,6 @@ static inline void samples_release_rdbuf(void) static inline int32_t * samples_get_rdbuf(void) { ci->semaphore_wait(&sample_queue.emu_sem_head, TIMEOUT_BLOCK); - - if (ci->stop_codec || ci->new_track) - { - /* Told to stop. Buffer must be released. */ - samples_release_rdbuf(); - return NULL; - } - return sample_queue.wav_chunk[sample_queue.head & WAV_CHUNK_MASK].audio; } @@ -390,11 +382,10 @@ static inline void spc_emu_quit(void) } } -static inline bool spc_play_get_samples(int32_t **samples) +static inline int32_t * spc_play_get_samples(void) { /* obtain filled samples buffer */ - *samples = samples_get_rdbuf(); - return *samples != NULL; + return samples_get_rdbuf(); } static inline void spc_play_send_samples(int32_t *samples) @@ -433,15 +424,14 @@ static inline void spc_play_send_samples(int32_t *samples) #define spc_emu_quit() #define samples_release_rdbuf() -static inline bool spc_play_get_samples(int32_t **samples) +static inline int32_t * spc_play_get_samples(void) { ENTER_TIMER(render); /* fill samples buffer */ if ( SPC_play(&spc_emu,WAV_CHUNK_SIZE*2,wav_chunk) ) assert( false ); EXIT_TIMER(render); - *samples = wav_chunk; - return true; + return wav_chunk; } #endif /* SPC_DUAL_CORE */ @@ -454,6 +444,7 @@ static int play_track( void ) unsigned long fadeendsample = (ID666.length+ID666.fade)*(long long) SAMPLE_RATE/1000; int fadedec = 0; int fadevol = 0x7fffffffl; + intptr_t param; if (fadeendsample>fadestartsample) fadedec=0x7fffffffl/(fadeendsample-fadestartsample)+1; @@ -462,25 +453,26 @@ static int play_track( void ) while ( 1 ) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - } - if (ci->seek_time) { + if (action == CODEC_ACTION_SEEK_TIME) { int curtime = sampleswritten*1000LL/SAMPLE_RATE; - DEBUGF("seek to %ld\ncurrently at %d\n",ci->seek_time,curtime); - if (ci->seek_time < curtime) { + DEBUGF("seek to %ld\ncurrently at %d\n", (long)param, curtime); + if (param < curtime) { DEBUGF("seek backwards = reset\n"); + ci->set_elapsed(0); ci->seek_complete(); return 1; } + + ci->set_elapsed(curtime); ci->seek_complete(); } - int32_t *samples; - if (!spc_play_get_samples(&samples)) - break; + int32_t *samples = spc_play_get_samples(); sampleswritten += WAV_CHUNK_SIZE; @@ -532,67 +524,61 @@ static int play_track( void ) } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) { - enum codec_status stat = CODEC_ERROR; - - if (!spc_emu_start()) - goto codec_quit; - - do - { - DEBUGF("SPC: next_track\n"); - if (codec_init()) { - goto codec_quit; - } - DEBUGF("SPC: after init\n"); + if (reason == CODEC_LOAD) { + if (!spc_emu_start()) + return CODEC_ERROR; ci->configure(DSP_SET_SAMPLE_DEPTH, 24); ci->configure(DSP_SET_FREQUENCY, SAMPLE_RATE); ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); + } + else if (reason == CODEC_UNLOAD) { + spc_emu_quit(); + } - /* wait for track info to load */ - if (codec_wait_taginfo() != 0) - continue; - - codec_set_replaygain(ci->id3); + return CODEC_OK; +} - /* Read the entire file */ - DEBUGF("SPC: request initial buffer\n"); - ci->seek_buffer(0); - size_t buffersize; - uint8_t* buffer = ci->request_buffer(&buffersize, ci->filesize); - if (!buffer) { - goto codec_quit; +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ + DEBUGF("SPC: next_track\n"); + if (codec_init()) + return CODEC_ERROR; + DEBUGF("SPC: after init\n"); + + codec_set_replaygain(ci->id3); + + /* Read the entire file */ + DEBUGF("SPC: request initial buffer\n"); + ci->seek_buffer(0); + size_t buffersize; + uint8_t* buffer = ci->request_buffer(&buffersize, ci->filesize); + if (!buffer) + return CODEC_ERROR; + + DEBUGF("SPC: read size = 0x%lx\n",(unsigned long)buffersize); + do + { + if (load_spc_buffer(buffer, buffersize)) { + DEBUGF("SPC load failure\n"); + return CODEC_ERROR; } - DEBUGF("SPC: read size = 0x%lx\n",(unsigned long)buffersize); - do - { - if (load_spc_buffer(buffer, buffersize)) { - DEBUGF("SPC load failure\n"); - goto codec_quit; - } - - LoadID666(buffer+0x2e); + LoadID666(buffer+0x2e); - if (ci->global_settings->repeat_mode!=REPEAT_ONE && ID666.length==0) { - ID666.length=3*60*1000; /* 3 minutes */ - ID666.fade=5*1000; /* 5 seconds */ - } - - reset_profile_timers(); + if (ci->global_settings->repeat_mode!=REPEAT_ONE && ID666.length==0) { + ID666.length=3*60*1000; /* 3 minutes */ + ID666.fade=5*1000; /* 5 seconds */ } - while ( play_track() ); - print_timers(ci->id3->path); + reset_profile_timers(); } - while ( ci->request_next_track() ); + while ( play_track() ); - stat = CODEC_OK; + print_timers(ci->id3->path); -codec_quit: - spc_emu_quit(); - - return stat; + return CODEC_OK; } diff --git a/apps/codecs/speex.c b/apps/codecs/speex.c index 7a1efa9753..e394efc3d5 100644 --- a/apps/codecs/speex.c +++ b/apps/codecs/speex.c @@ -367,11 +367,12 @@ static void *process_header(spx_ogg_packet *op, return st; } -/* this is the codec entry point */ -enum codec_status codec_main(void) +/* this is called for each file to process */ +enum codec_status codec_run(void) { + int error = CODEC_ERROR; + SpeexBits bits; - int error; int eof = 0; spx_ogg_sync_state oy; spx_ogg_page og; @@ -383,7 +384,7 @@ enum codec_status codec_main(void) int eos = 0; SpeexStereoState *stereo; int channels = -1; - int rate = 0, samplerate = 0; + int samplerate = 0; int extra_headers = 0; int stream_init = 0; int page_nb_packets, frame_size, packet_count = 0; @@ -392,26 +393,22 @@ enum codec_status codec_main(void) unsigned long strtoffset = 0; void *st = NULL; int j = 0; + intptr_t param; memset(&bits, 0, sizeof(bits)); memset(&oy, 0, sizeof(oy)); /* Ogg handling still uses mallocs, so reset the malloc buffer per track */ -next_track: - error = CODEC_OK; - if (codec_init()) { - error = CODEC_ERROR; goto exit; } + ci->seek_buffer(0); + stereo = speex_stereo_state_init(); spx_ogg_sync_init(&oy); spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE); - if (codec_wait_taginfo() != 0) - goto done; - strtoffset = ci->id3->offset; samplerate = ci->id3->frequency; @@ -419,30 +416,32 @@ next_track: eof = 0; while (!eof) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; /*seek (seeks to the page before the position) */ - if (ci->seek_time) { + if (action == CODEC_ACTION_SEEK_TIME) { if(samplerate!=0&&packet_count>1){ LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n", - ((spx_int64_t)ci->seek_time/1000) * + ((spx_int64_t)param/1000) * (spx_int64_t)samplerate, - page_granule, ci->seek_time, + page_granule, param, (page_granule/samplerate)*1000, samplerate); - speex_seek_page_granule(((spx_int64_t)ci->seek_time/1000) * + speex_seek_page_granule(((spx_int64_t)param/1000) * (spx_int64_t)samplerate, page_granule, &oy, headerssize); - ci->seek_complete(); } + + ci->set_elapsed(param); + ci->seek_complete(); } next_page: /*Get the ogg buffer for writing*/ if(get_more_data(&oy)<1){/*read error*/ - error=CODEC_ERROR; goto done; } @@ -477,8 +476,7 @@ next_page: nframes=1; if (!st){ - error=CODEC_ERROR; - goto exit; + goto done; } ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); @@ -557,31 +555,18 @@ next_page: } done: - if (ci->request_next_track()) { - - /* Clean things up for the next track */ + /* Clean things up for the next track */ + speex_bits_destroy(&bits); + if (st) if (st) speex_decoder_destroy(st); - if (stream_init == 1) - spx_ogg_stream_reset(&os); - - spx_ogg_sync_reset(&oy); - - cur_granule = stream_init = rate = samplerate = headerssize - = packet_count = eos = 0; - - goto next_track; - } - -exit: - speex_bits_destroy(&bits); - if (stream_init) spx_ogg_stream_destroy(&os); spx_ogg_sync_destroy(&oy); +exit: return error; } diff --git a/apps/codecs/tta.c b/apps/codecs/tta.c index 1d0846ea61..c75f2b0a57 100644 --- a/apps/codecs/tta.c +++ b/apps/codecs/tta.c @@ -34,36 +34,36 @@ CODEC_HEADER static int32_t samples[PCM_BUFFER_LENGTH * 2] IBSS_ATTR; /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { tta_info info; - int status; unsigned int decodedsamples; int endofstream; int new_pos = 0; int sample_count; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1); + intptr_t param; -next_track: - status = CODEC_OK; - if (codec_init()) { DEBUGF("codec_init() error\n"); - status = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; + ci->seek_buffer(0); if (set_tta_info(&info) < 0 || player_init(&info) < 0) - { - status = CODEC_ERROR; - goto exit; - } + return CODEC_ERROR; codec_set_replaygain(ci->id3); @@ -74,8 +74,8 @@ next_track: ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); } else { DEBUGF("CODEC_ERROR: more than 2 channels\n"); - status = CODEC_ERROR; - goto done; + player_stop(); + return CODEC_ERROR; } /* The main decoder loop */ @@ -88,31 +88,31 @@ next_track: new_pos = set_position(ci->id3->offset, TTA_SEEK_POS); if (new_pos >= 0) decodedsamples = new_pos; - ci->seek_complete(); } while (!endofstream) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) + if (action == CODEC_ACTION_SEEK_TIME) { - new_pos = set_position(ci->seek_time / SEEK_STEP, TTA_SEEK_TIME); + new_pos = set_position(param / SEEK_STEP, TTA_SEEK_TIME); if (new_pos >= 0) { decodedsamples = new_pos; - ci->seek_complete(); } + + ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH); + ci->seek_complete(); } sample_count = get_samples(samples); if (sample_count < 0) - { - status = CODEC_ERROR; break; - } + ci->pcmbuf_insert(samples, NULL, sample_count); decodedsamples += sample_count; if (decodedsamples >= info.DATALENGTH) @@ -120,11 +120,6 @@ next_track: ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH); } -done: player_stop(); - if (ci->request_next_track()) - goto next_track; - -exit: - return status; + return CODEC_OK; } diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c index 0a36a37c8b..e02d459262 100644 --- a/apps/codecs/vorbis.c +++ b/apps/codecs/vorbis.c @@ -104,14 +104,25 @@ static bool vorbis_set_codec_parameters(OggVorbis_File *vf) } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + if (codec_init()) + return CODEC_ERROR; + ci->configure(DSP_SET_SAMPLE_DEPTH, 24); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { ov_callbacks callbacks; OggVorbis_File vf; ogg_int32_t **pcm; - bool initialized = false; /* First init done? */ - int error; + int error = CODEC_ERROR; long n; int current_section; int previous_section; @@ -120,36 +131,24 @@ enum codec_status codec_main(void) ogg_int64_t vf_dataoffsets; ogg_uint32_t vf_serialnos; ogg_int64_t vf_pcmlengths[2]; - - ci->configure(DSP_SET_SAMPLE_DEPTH, 24); - - if (codec_init()) { - error = CODEC_ERROR; - goto exit; - } + intptr_t param; #if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS) if (setjmp(rb_jump_buf) != 0) { - /* malloc failed; skip to next track */ - error = CODEC_ERROR; + /* malloc failed; finish with this track */ goto done; } #endif - -next_track: - error = CODEC_OK; - ogg_malloc_init(); - if (codec_wait_taginfo() != 0) - goto done; - /* Create a decoder instance */ callbacks.read_func = read_handler; callbacks.seek_func = initial_seek_handler; callbacks.tell_func = tell_handler; callbacks.close_func = close_handler; + ci->seek_buffer(0); + /* Open a non-seekable stream */ error = ov_open_callbacks(ci, &vf, NULL, 0, callbacks); @@ -186,15 +185,13 @@ next_track: vf.end = ci->id3->filesize; vf.ready_state = OPENED; vf.links = 1; - initialized = true; } else { DEBUGF("Vorbis: ov_open failed: %d\n", error); - error = CODEC_ERROR; goto done; } if (ci->id3->offset) { - ci->advance_buffer(ci->id3->offset); + ci->seek_buffer(ci->id3->offset); ov_raw_seek(&vf, ci->id3->offset); ci->set_elapsed(ov_time_tell(&vf)); ci->set_offset(ov_raw_tell(&vf)); @@ -203,14 +200,17 @@ next_track: previous_section = -1; eof = 0; while (!eof) { - ci->yield(); - if (ci->stop_codec || ci->new_track) + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - if (ci->seek_time) { - if (ov_time_seek(&vf, ci->seek_time - 1)) { + if (action == CODEC_ACTION_SEEK_TIME) { + if (ov_time_seek(&vf, param)) { //ci->logf("ov_time_seek failed"); } + + ci->set_elapsed(ov_time_tell(&vf)); ci->seek_complete(); } @@ -220,7 +220,6 @@ next_track: /* Change DSP and buffer settings for this bitstream */ if (current_section != previous_section) { if (!vorbis_set_codec_parameters(&vf)) { - error = CODEC_ERROR; goto done; } else { previous_section = current_section; @@ -238,6 +237,7 @@ next_track: } } + error = CODEC_OK; done: #if 0 /* defined(SIMULATOR) */ { @@ -249,18 +249,12 @@ done: #endif ogg_malloc_destroy(); - if (ci->request_next_track()) { - if (!initialized) - goto next_track; - /* Clean things up for the next track */ - vf.dataoffsets = NULL; - vf.offsets = NULL; - vf.serialnos = NULL; - vf.pcmlengths = NULL; - ov_clear(&vf); - goto next_track; - } - -exit: + /* Clean things up for the next track */ + vf.dataoffsets = NULL; + vf.offsets = NULL; + vf.serialnos = NULL; + vf.pcmlengths = NULL; + ov_clear(&vf); + return error; } diff --git a/apps/codecs/vox.c b/apps/codecs/vox.c index c7f39342c3..bf274c6917 100644 --- a/apps/codecs/vox.c +++ b/apps/codecs/vox.c @@ -44,9 +44,19 @@ static uint8_t *read_buffer(size_t *realsize) } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { - int status; uint32_t decodedsamples; size_t n; int bufcount; @@ -54,26 +64,18 @@ enum codec_status codec_main(void) uint8_t *voxbuf; off_t firstblockposn = 0; /* position of the first block in file */ const struct pcm_codec *codec; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); - -next_track: - status = CODEC_OK; + intptr_t param; if (codec_init()) { DEBUGF("codec_init() error\n"); - status = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - codec_set_replaygain(ci->id3); /* Need to save offset for later use (cleared indirectly by advance_buffer) */ bytesdone = ci->id3->offset; + ci->seek_buffer(0); ci->memset(&format, 0, sizeof(struct pcm_format)); @@ -96,20 +98,16 @@ next_track: if (!codec) { DEBUGF("CODEC_ERROR: dialogic oki adpcm codec does not load.\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } - if (!codec->set_format(&format)) - { - status = CODEC_ERROR; - goto done; + if (!codec->set_format(&format)) { + return CODEC_ERROR; } if (format.numbytes == 0) { DEBUGF("CODEC_ERROR: data size is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* check chunksize */ @@ -118,8 +116,7 @@ next_track: if (format.chunksize == 0) { DEBUGF("CODEC_ERROR: chunksize is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); @@ -131,14 +128,14 @@ next_track: struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, PCM_SEEK_POS, &read_buffer); - if (newpos->pos > format.numbytes) - goto done; + if (newpos->pos > format.numbytes) { + return CODEC_OK; + } if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } - ci->seek_complete(); } else { /* already where we need to be */ bytesdone = 0; @@ -148,22 +145,29 @@ next_track: endofstream = 0; while (!endofstream) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - } - if (ci->seek_time) { - struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, + if (action == CODEC_ACTION_SEEK_TIME) { + struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, &read_buffer); if (newpos->pos > format.numbytes) + { + ci->set_elapsed(ci->id3->length); + ci->seek_complete(); break; + } + if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } + + ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); ci->seek_complete(); } @@ -175,11 +179,10 @@ next_track: endofstream = 1; } - status = codec->decode(voxbuf, n, samples, &bufcount); - if (status == CODEC_ERROR) + if (codec->decode(voxbuf, n, samples, &bufcount) == CODEC_ERROR) { DEBUGF("codec error\n"); - goto done; + return CODEC_ERROR; } ci->pcmbuf_insert(samples, NULL, bufcount); @@ -192,10 +195,5 @@ next_track: ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); } -done: - if (ci->request_next_track()) - goto next_track; - -exit: - return status; + return CODEC_OK; } diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c index e179470f27..42bcc7081f 100644 --- a/apps/codecs/wav.c +++ b/apps/codecs/wav.c @@ -151,9 +151,19 @@ static uint8_t *read_buffer(size_t *realsize) } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { - int status; uint32_t decodedsamples; size_t n; int bufcount; @@ -163,38 +173,28 @@ enum codec_status codec_main(void) off_t firstblockposn; /* position of the first block in file */ const struct pcm_codec *codec; uint32_t size; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); - -next_track: - status = CODEC_OK; + intptr_t param; if (codec_init()) { DEBUGF("codec_init() error\n"); - status = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - codec_set_replaygain(ci->id3); /* Need to save offset for later use (cleared indirectly by advance_buffer) */ bytesdone = ci->id3->offset; /* get RIFF chunk header */ + ci->seek_buffer(0); buf = ci->request_buffer(&n, 12); if (n < 12) { DEBUGF("request_buffer error\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { DEBUGF("CODEC_ERROR: missing riff header\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* advance to first WAVE chunk */ @@ -215,8 +215,7 @@ next_track: if (n < 8) { DEBUGF("data chunk request_buffer error\n"); /* no more chunks, 'data' chunk must not have been found */ - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* chunkSize */ @@ -225,8 +224,7 @@ next_track: if (size < 16) { DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", (unsigned long)size); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* wFormatTag */ format.formattag=buf[8]|(buf[9]<<8); @@ -256,8 +254,7 @@ next_track: if (format.size < 22) { DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " "missing extension\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* wValidBitsPerSample */ format.bitspersample = buf[26]|(buf[27]<<8); @@ -273,8 +270,7 @@ next_track: { if (!set_msadpcm_coeffs(buf)) { - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } } @@ -284,8 +280,7 @@ next_track: { DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", (unsigned int) format.formattag); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* riff 8bit linear pcm is unsigned */ @@ -295,8 +290,7 @@ next_track: /* set format, parse codec specific tag, check format, and calculate chunk size */ if (!codec->set_format(&format)) { - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } } else if (memcmp(buf, "data", 4) == 0) { format.numbytes = size; @@ -324,31 +318,26 @@ next_track: if (!codec) { DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* common format check */ if (format.channels == 0) { DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.samplesperblock == 0) { DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.blockalign == 0) { DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.numbytes == 0) { DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* check chunksize */ @@ -358,8 +347,7 @@ next_track: if (format.chunksize == 0) { DEBUGF("CODEC_ERROR: chunksize is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); @@ -369,8 +357,7 @@ next_track: ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); } else { DEBUGF("CODEC_ERROR: more than 2 channels\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* make sure we're at the correct offset */ @@ -380,13 +367,12 @@ next_track: PCM_SEEK_POS, &read_buffer); if (newpos->pos > format.numbytes) - goto done; + return CODEC_OK; if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } - ci->seek_complete(); } else { /* already where we need to be */ bytesdone = 0; @@ -396,22 +382,28 @@ next_track: endofstream = 0; while (!endofstream) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - } - if (ci->seek_time) { - struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, + if (action == CODEC_ACTION_SEEK_TIME) { + struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, &read_buffer); - if (newpos->pos > format.numbytes) + { + ci->set_elapsed(ci->id3->length); + ci->seek_complete(); break; + } + if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } + + ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); ci->seek_complete(); } @@ -423,11 +415,10 @@ next_track: endofstream = 1; } - status = codec->decode(wavbuf, n, samples, &bufcount); - if (status == CODEC_ERROR) + if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR) { DEBUGF("codec error\n"); - goto done; + return CODEC_ERROR; } ci->pcmbuf_insert(samples, NULL, bufcount); @@ -440,10 +431,5 @@ next_track: ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); } -done: - if (ci->request_next_track()) - goto next_track; - -exit: - return status; + return CODEC_OK; } diff --git a/apps/codecs/wav64.c b/apps/codecs/wav64.c index 9dbdab8368..c763e6f7f0 100644 --- a/apps/codecs/wav64.c +++ b/apps/codecs/wav64.c @@ -159,9 +159,19 @@ static uint8_t *read_buffer(size_t *realsize) } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { - int status; uint32_t decodedsamples; size_t n; int bufcount; @@ -171,39 +181,29 @@ enum codec_status codec_main(void) off_t firstblockposn; /* position of the first block in file */ const struct pcm_codec *codec; uint64_t size; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); - -next_track: - status = CODEC_OK; + intptr_t param; if (codec_init()) { DEBUGF("codec_init() error\n"); - status = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } - if (codec_wait_taginfo() != 0) - goto done; - codec_set_replaygain(ci->id3); /* Need to save offset for later use (cleared indirectly by advance_buffer) */ bytesdone = ci->id3->offset; /* get RIFF chunk header */ + ci->seek_buffer(0); buf = ci->request_buffer(&n, 40); if (n < 40) { DEBUGF("request_buffer error\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0) || (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0)) { - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* advance to first WAVE chunk */ @@ -224,8 +224,7 @@ next_track: if (n < 8) { DEBUGF("data chunk request_buffer error\n"); /* no more chunks, 'data' chunk must not have been found */ - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* chunkSize */ @@ -233,8 +232,7 @@ next_track: if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) { if (size < 16) { DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* wFormatTag */ format.formattag=buf[24]|(buf[25]<<8); @@ -263,8 +261,7 @@ next_track: if (format.size < 22) { DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " "missing extension\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* wValidBitsPerSample */ format.bitspersample = buf[42]|(buf[43]<<8); @@ -279,10 +276,7 @@ next_track: if (format.formattag == WAVE_FORMAT_ADPCM) { if (!set_msadpcm_coeffs(buf)) - { - status = CODEC_ERROR; - goto done; - } + return CODEC_ERROR; } /* get codec */ @@ -291,8 +285,7 @@ next_track: { DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", (unsigned int) format.formattag); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* riff 8bit linear pcm is unsigned */ @@ -301,10 +294,7 @@ next_track: /* check format, and calculate chunk size */ if (!codec->set_format(&format)) - { - status = CODEC_ERROR; - goto done; - } + return CODEC_ERROR; } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) { format.numbytes = size; /* advance to start of data */ @@ -330,31 +320,26 @@ next_track: if (!codec) { DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* common format check */ if (format.channels == 0) { DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.samplesperblock == 0) { DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.blockalign == 0) { DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } if (format.numbytes == 0) { DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* check chunksize */ @@ -364,8 +349,7 @@ next_track: if (format.chunksize == 0) { DEBUGF("CODEC_ERROR: chunksize is 0\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); @@ -375,8 +359,7 @@ next_track: ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); } else { DEBUGF("CODEC_ERROR: more than 2 channels\n"); - status = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* make sure we're at the correct offset */ @@ -385,14 +368,14 @@ next_track: struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, PCM_SEEK_POS, &read_buffer); - if (newpos->pos > format.numbytes) - goto done; + if (newpos->pos > format.numbytes) { + return CODEC_OK; + } if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } - ci->seek_complete(); } else { /* already where we need to be */ bytesdone = 0; @@ -402,22 +385,29 @@ next_track: endofstream = 0; while (!endofstream) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) break; - } - if (ci->seek_time) { - struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, + if (action == CODEC_ACTION_SEEK_TIME) { + struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, &read_buffer); if (newpos->pos > format.numbytes) + { + ci->set_elapsed(ci->id3->length); + ci->seek_complete(); break; + } + if (ci->seek_buffer(firstblockposn + newpos->pos)) { bytesdone = newpos->pos; decodedsamples = newpos->samples; } + + ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); ci->seek_complete(); } @@ -429,11 +419,10 @@ next_track: endofstream = 1; } - status = codec->decode(wavbuf, n, samples, &bufcount); - if (status == CODEC_ERROR) + if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR) { DEBUGF("codec error\n"); - goto done; + return CODEC_ERROR; } ci->pcmbuf_insert(samples, NULL, bufcount); @@ -445,12 +434,6 @@ next_track: endofstream = 1; ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); } - status = CODEC_OK; - -done: - if (ci->request_next_track()) - goto next_track; -exit: - return status; + return CODEC_OK; } diff --git a/apps/codecs/wav_enc.c b/apps/codecs/wav_enc.c index ef1a88ec23..e4afeaf93c 100644 --- a/apps/codecs/wav_enc.c +++ b/apps/codecs/wav_enc.c @@ -345,40 +345,42 @@ static bool init_encoder(void) return true; } /* init_encoder */ -/* main codec entry point */ -enum codec_status codec_main(void) +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) { - if (!init_encoder()) - return CODEC_ERROR; + if (reason == CODEC_LOAD) { + if (!init_encoder()) + return CODEC_ERROR; + } + else if (reason == CODEC_UNLOAD) { + /* reset parameters to initial state */ + ci->enc_set_parameters(NULL); + } + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ /* main encoding loop */ - while(!ci->stop_codec) + while(ci->get_command(NULL) != CODEC_ACTION_HALT) { - uint32_t *src; + uint32_t *src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE); + struct enc_chunk_hdr *chunk; - while ((src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL) - { - struct enc_chunk_hdr *chunk; - - if (ci->stop_codec) - break; + if(src == NULL) + continue; - chunk = ci->enc_get_chunk(); - chunk->enc_size = enc_size; - chunk->num_pcm = PCM_SAMP_PER_CHUNK; - chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); + chunk = ci->enc_get_chunk(); + chunk->enc_size = enc_size; + chunk->num_pcm = PCM_SAMP_PER_CHUNK; + chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); - chunk_to_wav_format(src, (uint32_t *)chunk->enc_data); + chunk_to_wav_format(src, (uint32_t *)chunk->enc_data); - ci->enc_finish_chunk(); - ci->yield(); - } - - ci->yield(); + ci->enc_finish_chunk(); } - /* reset parameters to initial state */ - ci->enc_set_parameters(NULL); - return CODEC_OK; -} /* codec_start */ +} diff --git a/apps/codecs/wavpack.c b/apps/codecs/wavpack.c index d27a9fb621..ccb9f41190 100644 --- a/apps/codecs/wavpack.c +++ b/apps/codecs/wavpack.c @@ -31,39 +31,39 @@ static int32_t temp_buffer [BUFFER_SIZE] IBSS_ATTR; static int32_t read_callback (void *buffer, int32_t bytes) { int32_t retval = ci->read_filebuf (buffer, bytes); - ci->id3->offset = ci->curpos; + ci->set_offset(ci->curpos); return retval; } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 28); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { WavpackContext *wpc; char error [80]; int bps, nchans, sr_100; - int retval; + intptr_t param; - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, 28); + if (codec_init()) + return CODEC_ERROR; -next_track: - retval = CODEC_OK; + ci->seek_buffer (ci->id3->offset); - if (codec_init()) { - retval = CODEC_ERROR; - goto exit; - } - - if (codec_wait_taginfo() != 0) - goto done; - /* Create a decoder instance */ wpc = WavpackOpenFileInput (read_callback, error); - if (!wpc) { - retval = CODEC_ERROR; - goto done; - } + if (!wpc) + return CODEC_ERROR; ci->configure(DSP_SWITCH_FREQUENCY, WavpackGetSampleRate (wpc)); codec_set_replaygain(ci->id3); @@ -77,56 +77,48 @@ next_track: /* The main decoder loop */ while (1) { - int32_t nsamples; + int32_t nsamples; + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) + break; - if (ci->seek_time && ci->taginfo_ready && ci->id3->length) { - ci->seek_time--; + if (action == CODEC_ACTION_SEEK_TIME) { int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10; int n, d, skip; - if (ci->seek_time > curpos_ms) { - n = ci->seek_time - curpos_ms; + if (param > curpos_ms) { + n = param - curpos_ms; d = ci->id3->length - curpos_ms; skip = (int)((int64_t)(ci->filesize - ci->curpos) * n / d); ci->seek_buffer (ci->curpos + skip); } - else { - n = curpos_ms - ci->seek_time; + else if (curpos_ms != 0) { + n = curpos_ms - param; d = curpos_ms; skip = (int)((int64_t) ci->curpos * n / d); ci->seek_buffer (ci->curpos - skip); } wpc = WavpackOpenFileInput (read_callback, error); - ci->seek_complete(); - if (!wpc) + { + ci->seek_complete(); break; + } ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); - ci->yield (); + ci->seek_complete(); } nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / nchans); - if (!nsamples || ci->stop_codec || ci->new_track) - break; - - ci->yield (); - - if (ci->stop_codec || ci->new_track) + if (!nsamples) break; ci->pcmbuf_insert (temp_buffer, NULL, nsamples); - ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); - ci->yield (); } -done: - if (ci->request_next_track()) - goto next_track; - -exit: - return retval; + return CODEC_OK; } diff --git a/apps/codecs/wavpack_enc.c b/apps/codecs/wavpack_enc.c index d908e284be..730cf0734b 100644 --- a/apps/codecs/wavpack_enc.c +++ b/apps/codecs/wavpack_enc.c @@ -389,77 +389,79 @@ static bool init_encoder(void) return true; } /* init_encoder */ -enum codec_status codec_main(void) +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) { - /* initialize params and config */ - if (!init_encoder()) - return CODEC_ERROR; + if (reason == CODEC_LOAD) { + /* initialize params and config */ + if (!init_encoder()) + return CODEC_ERROR; + } + else if (reason == CODEC_UNLOAD) { + /* reset parameters to initial state */ + ci->enc_set_parameters(NULL); + } + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ /* main encoding loop */ - while(!ci->stop_codec) + while(ci->get_command(NULL) != CODEC_ACTION_HALT) { - uint8_t *src; + uint8_t *src = (uint8_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE); + struct enc_chunk_hdr *chunk; + bool abort_chunk; + uint8_t *dst; + uint8_t *src_end; - while ((src = ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL) - { - struct enc_chunk_hdr *chunk; - bool abort_chunk; - uint8_t *dst; - uint8_t *src_end; - - if(ci->stop_codec) - break; - - abort_chunk = true; + if(src == NULL) + continue; - chunk = ci->enc_get_chunk(); + chunk = ci->enc_get_chunk(); - /* reset counts and pointer */ - chunk->enc_size = 0; - chunk->num_pcm = 0; - chunk->enc_data = NULL; + /* reset counts and pointer */ + chunk->enc_size = 0; + chunk->num_pcm = 0; + chunk->enc_data = NULL; - dst = ENC_CHUNK_SKIP_HDR(dst, chunk); + dst = ENC_CHUNK_SKIP_HDR(dst, chunk); - WavpackStartBlock(wpc, dst, dst + data_size); + WavpackStartBlock(wpc, dst, dst + data_size); - chunk_to_int32((uint32_t*)src); - src = input_buffer; - src_end = src + input_size; + chunk_to_int32((uint32_t*)src); + src = input_buffer; + src_end = src + input_size; - /* encode chunk in four steps yielding between each */ - do + /* encode chunk in four steps yielding between each */ + do + { + abort_chunk = true; + if (WavpackPackSamples(wpc, (int32_t *)src, + PCM_SAMP_PER_CHUNK/4)) { - if (WavpackPackSamples(wpc, (int32_t *)src, - PCM_SAMP_PER_CHUNK/4)) - { - chunk->num_pcm += PCM_SAMP_PER_CHUNK/4; - ci->yield(); - /* could've been stopped in some way */ - abort_chunk = ci->stop_codec || - (chunk->flags & CHUNKF_ABORT); - } - - src += input_step; + chunk->num_pcm += PCM_SAMP_PER_CHUNK/4; + ci->yield(); + /* could've been stopped in some way */ + abort_chunk = chunk->flags & CHUNKF_ABORT; } - while (!abort_chunk && src < src_end); - if (!abort_chunk) - { - chunk->enc_data = dst; - if (chunk->num_pcm < PCM_SAMP_PER_CHUNK) - ci->enc_unget_pcm_data(PCM_CHUNK_SIZE - chunk->num_pcm*4); - /* finish the chunk and store chunk size info */ - chunk->enc_size = WavpackFinishBlock(wpc); - ci->enc_finish_chunk(); - } + src += input_step; } + while (!abort_chunk && src < src_end); - ci->yield(); + if (!abort_chunk) + { + chunk->enc_data = dst; + if (chunk->num_pcm < PCM_SAMP_PER_CHUNK) + ci->enc_unget_pcm_data(PCM_CHUNK_SIZE - chunk->num_pcm*4); + /* finish the chunk and store chunk size info */ + chunk->enc_size = WavpackFinishBlock(wpc); + ci->enc_finish_chunk(); + } } - /* reset parameters to initial state */ - ci->enc_set_parameters(NULL); - return CODEC_OK; -} /* codec_start */ +} diff --git a/apps/codecs/wma.c b/apps/codecs/wma.c index 1b46813444..c327fafb5a 100644 --- a/apps/codecs/wma.c +++ b/apps/codecs/wma.c @@ -29,53 +29,52 @@ CODEC_HEADER static WMADecodeContext wmadec; /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 29); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { uint32_t elapsedtime; - int retval; asf_waveformatex_t wfx; size_t resume_offset; int i; - int wmares, res; + int wmares; + int res = 0; uint8_t* audiobuf; int audiobufsize; int packetlength = 0; int errcount = 0; - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, 29); - -next_track: - retval = CODEC_OK; + intptr_t param; /* Proper reset of the decoder context. */ memset(&wmadec, 0, sizeof(wmadec)); - /* Wait for the metadata to be read */ - if (codec_wait_taginfo() != 0) - goto done; - /* Remember the resume position - when the codec is opened, the playback engine will reset it. */ resume_offset = ci->id3->offset; restart_track: - retval = CODEC_OK; - if (codec_init()) { LOGF("WMA: Error initialising codec\n"); - retval = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } /* Copy the format metadata we've stored in the id3 TOC field. This saves us from parsing it again here. */ memcpy(&wfx, ci->id3->toc, sizeof(wfx)); + ci->seek_buffer(ci->id3->first_frame_offset); if (wma_decode_init(&wmadec,&wfx) < 0) { LOGF("WMA: Unsupported or corrupt file\n"); - retval = CODEC_ERROR; - goto exit; + return CODEC_ERROR; } if (resume_offset > ci->id3->first_frame_offset) @@ -101,34 +100,35 @@ restart_track: codec_set_replaygain(ci->id3); /* The main decoding loop */ - - res = 1; while (res >= 0) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { - goto done; - } + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) + break; /* Deal with any pending seek requests */ - if (ci->seek_time){ + if (action == CODEC_ACTION_SEEK_TIME) { - if (ci->seek_time == 1) { + if (param == 0) { + ci->set_elapsed(0); ci->seek_complete(); goto restart_track; /* Pretend you never saw this... */ } - elapsedtime = asf_seek(ci->seek_time, &wfx); + elapsedtime = asf_seek(param, &wfx); if (elapsedtime < 1){ + ci->set_elapsed(0); ci->seek_complete(); - goto next_track; + break; } /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/ - ci->set_elapsed(elapsedtime); /*flush the wma decoder state*/ wmadec.last_superframe_len = 0; wmadec.last_bitoffset = 0; + + ci->set_elapsed(elapsedtime); ci->seek_complete(); } errcount = 0; @@ -140,10 +140,15 @@ new_packet: * times. If we succeed, the error counter will be reset. */ + if (res == ASF_ERROR_EOF) { + /* File ended - not an error */ + break; + } + errcount++; DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount); if (errcount > 5) { - goto done; + return CODEC_ERROR; } else { ci->advance_buffer(packetlength); goto new_packet; @@ -163,7 +168,7 @@ new_packet: errcount++; DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount); if (errcount > 5) { - goto done; + return CODEC_ERROR; } else { ci->advance_buffer(packetlength); goto new_packet; @@ -173,18 +178,12 @@ new_packet: elapsedtime += (wmares*10)/(wfx.rate/100); ci->set_elapsed(elapsedtime); } - ci->yield(); } } ci->advance_buffer(packetlength); } -done: /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/ - - if (ci->request_next_track()) - goto next_track; -exit: - return retval; + return CODEC_OK; } diff --git a/apps/codecs/wmapro.c b/apps/codecs/wmapro.c index c02dddeeb3..b6a8e47f25 100644 --- a/apps/codecs/wmapro.c +++ b/apps/codecs/wmapro.c @@ -27,11 +27,22 @@ CODEC_HEADER int32_t *dec[2]; /* pointers to the output buffers in WMAProDecodeCtx in wmaprodec.c */ + /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, WMAPRO_DSP_SAMPLE_DEPTH); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { uint32_t elapsedtime; - int retval; asf_waveformatex_t wfx; /* Holds the stream properties */ size_t resume_offset; int res; /* Return values from asf_read_packet() and decode_packet() */ @@ -42,28 +53,15 @@ enum codec_status codec_main(void) int pktcnt = 0; /* Count of the packets played */ uint8_t *data; /* Pointer to decoder input buffer */ int size; /* Size of the input frame to the decoder */ - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, WMAPRO_DSP_SAMPLE_DEPTH); - - -next_track: - retval = CODEC_OK; - - /* Wait for the metadata to be read */ - if (codec_wait_taginfo() != 0) - goto done; + intptr_t param; /* Remember the resume position */ resume_offset = ci->id3->offset; restart_track: - retval = CODEC_OK; - if (codec_init()) { LOGF("(WMA PRO) Error: Error initialising codec\n"); - retval = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* Copy the format metadata we've stored in the id3 TOC field. This @@ -77,8 +75,7 @@ restart_track: if (decode_init(&wfx) < 0) { LOGF("(WMA PRO) Error: Unsupported or corrupt file\n"); - retval = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* Now advance the file position to the first frame */ @@ -91,23 +88,24 @@ restart_track: while (pktcnt < wfx.numpackets) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { - goto done; - } - - /* Deal with any pending seek requests */ - if (ci->seek_time){ + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) + break; - if (ci->seek_time == 1) { + /* Deal with any pending seek requests */ + if (action == CODEC_ACTION_SEEK_TIME) { + if (param == 0) { + ci->set_elapsed(0); ci->seek_complete(); goto restart_track; /* Pretend you never saw this... */ } - elapsedtime = asf_seek(ci->seek_time, &wfx); + elapsedtime = asf_seek(param, &wfx); if (elapsedtime < 1){ + ci->set_elapsed(0); ci->seek_complete(); - goto next_track; + break; } ci->set_elapsed(elapsedtime); @@ -117,8 +115,8 @@ restart_track: res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx); if (res < 0) { - LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res); - goto done; + LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res); + return CODEC_ERROR; } else { data = audiobuf; size = audiobufsize; @@ -132,7 +130,7 @@ restart_track: res = decode_packet(&wfx, dec, &outlen, data, size); if(res < 0) { LOGF("(WMA PRO) Error: decode_packet returned %d", res); - goto done; + return CODEC_ERROR; } data += res; size -= res; @@ -152,10 +150,6 @@ restart_track: ci->advance_buffer(packetlength); } -done: - if (ci->request_next_track()) - goto next_track; - - return retval; + return CODEC_OK; } diff --git a/apps/codecs/wmavoice.c b/apps/codecs/wmavoice.c index ddf66828f1..64c8cd1692 100644 --- a/apps/codecs/wmavoice.c +++ b/apps/codecs/wmavoice.c @@ -52,10 +52,20 @@ static void init_codec_ctx(AVCodecContext *avctx, asf_waveformatex_t *wfx) } /* this is the codec entry point */ -enum codec_status codec_main(void) +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 31); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) { uint32_t elapsedtime; - int retval; asf_waveformatex_t wfx; /* Holds the stream properties */ size_t resume_offset; int res; /* Return values from asf_read_packet() and decode_packet() */ @@ -64,27 +74,14 @@ enum codec_status codec_main(void) int packetlength = 0; /* Logical packet size (minus the header size) */ int outlen = 0; /* Number of bytes written to the output buffer */ int pktcnt = 0; /* Count of the packets played */ - - /* Generic codec initialisation */ - ci->configure(DSP_SET_SAMPLE_DEPTH, 31); - - -next_track: - retval = CODEC_OK; - - /* Wait for the metadata to be read */ - if (codec_wait_taginfo() != 0) - goto done; + intptr_t param; /* Remember the resume position */ resume_offset = ci->id3->offset; restart_track: - retval = CODEC_OK; - if (codec_init()) { LOGF("(WMA Voice) Error: Error initialising codec\n"); - retval = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* Copy the format metadata we've stored in the id3 TOC field. This @@ -97,14 +94,15 @@ restart_track: ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ? STEREO_MONO : STEREO_INTERLEAVED); codec_set_replaygain(ci->id3); + + ci->seek_buffer(0); /* Initialise the AVCodecContext */ init_codec_ctx(&avctx, &wfx); if (wmavoice_decode_init(&avctx) < 0) { LOGF("(WMA Voice) Error: Unsupported or corrupt file\n"); - retval = CODEC_ERROR; - goto done; + return CODEC_ERROR; } /* Now advance the file position to the first frame */ @@ -117,21 +115,24 @@ restart_track: while (pktcnt < wfx.numpackets) { - ci->yield(); - if (ci->stop_codec || ci->new_track) { - goto done; - } - + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) + break; + /* Deal with any pending seek requests */ - if (ci->seek_time){ + if (action == CODEC_ACTION_SEEK_TIME) { + ci->set_elapsed(param); - if (ci->seek_time == 1) { + if (param == 0) { + ci->set_elapsed(0); ci->seek_complete(); goto restart_track; /* Pretend you never saw this... */ } - elapsedtime = asf_seek(ci->seek_time, &wfx); + elapsedtime = asf_seek(param, &wfx); if (elapsedtime < 1){ + ci->set_elapsed(0); ci->seek_complete(); goto next_track; } @@ -145,7 +146,7 @@ new_packet: if (res < 0) { LOGF("(WMA Voice) read_packet error %d\n",res); - goto done; + return CODEC_ERROR; } else { avpkt.data = audiobuf; avpkt.size = audiobufsize; @@ -165,8 +166,9 @@ new_packet: ci->advance_buffer(packetlength); goto new_packet; } - else - goto done; + else { + return CODEC_ERROR; + } } avpkt.data += res; avpkt.size -= res; @@ -186,10 +188,6 @@ new_packet: ci->advance_buffer(packetlength); } -done: - if (ci->request_next_track()) - goto next_track; - - return retval; + return CODEC_OK; } |