diff options
Diffstat (limited to 'lib')
36 files changed, 487 insertions, 192 deletions
diff --git a/lib/rbcodec/codecs/a52.c b/lib/rbcodec/codecs/a52.c index 77caaf87c1..da670308b8 100644 --- a/lib/rbcodec/codecs/a52.c +++ b/lib/rbcodec/codecs/a52.c @@ -150,19 +150,28 @@ enum codec_status codec_run(void) samplesdone = 0; - /* The main decoding loop */ if (ci->id3->offset) { - if (ci->seek_buffer(ci->id3->offset)) { - samplesdone = (ci->id3->offset / ci->id3->bytesperframe) * - A52_SAMPLESPERFRAME; - ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000)); - } + sample_loc = (ci->id3->offset / ci->id3->bytesperframe) * + A52_SAMPLESPERFRAME; + param = ci->id3->offset; + } + else if (ci->id3->elapsed) { + sample_loc = ci->id3->elapsed/1000 * ci->id3->frequency; + param = sample_loc/A52_SAMPLESPERFRAME*ci->id3->bytesperframe; } else { - ci->seek_buffer(ci->id3->first_frame_offset); - ci->set_elapsed(0); + sample_loc = 0; + param = ci->id3->first_frame_offset; + } + + if (ci->seek_buffer(param)) { + samplesdone = sample_loc; } + ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); + + /* The main decoding loop */ + while (1) { enum codec_command_action action = ci->get_command(¶m); @@ -172,7 +181,8 @@ enum codec_status codec_run(void) if (action == CODEC_ACTION_SEEK_TIME) { sample_loc = param/1000 * ci->id3->frequency; - if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) { + if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)* + ci->id3->bytesperframe)) { samplesdone = sample_loc; ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); } diff --git a/lib/rbcodec/codecs/a52_rm.c b/lib/rbcodec/codecs/a52_rm.c index 42868437d8..3f07a43ce9 100644 --- a/lib/rbcodec/codecs/a52_rm.c +++ b/lib/rbcodec/codecs/a52_rm.c @@ -148,13 +148,15 @@ enum codec_status codec_run(void) int consumed, packet_offset; int playback_on = -1; size_t resume_offset; + enum codec_command_action action; intptr_t param; - enum codec_command_action action = CODEC_ACTION_NULL; if (codec_init()) { return CODEC_ERROR; } + action = CODEC_ACTION_NULL; + param = ci->id3->elapsed; resume_offset = ci->id3->offset; ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); @@ -171,11 +173,14 @@ enum codec_status codec_run(void) samplesdone = 0; /* 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; + if (resume_offset) { + resume_offset -= MIN(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); param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); + } + + if (param > 0) { action = CODEC_ACTION_SEEK_TIME; } else { diff --git a/lib/rbcodec/codecs/aac.c b/lib/rbcodec/codecs/aac.c index c9cf737b48..015e332be2 100644 --- a/lib/rbcodec/codecs/aac.c +++ b/lib/rbcodec/codecs/aac.c @@ -72,6 +72,7 @@ enum codec_status codec_run(void) uint32_t sbr_fac = 1; unsigned char c = 0; void *ret; + enum codec_command_action action; intptr_t param; bool empty_first_frame = false; @@ -82,6 +83,8 @@ enum codec_status codec_run(void) return CODEC_ERROR; } + action = CODEC_ACTION_NULL; + param = ci->id3->elapsed; file_offset = ci->id3->offset; ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); @@ -138,11 +141,16 @@ enum codec_status codec_run(void) sound_samples_done = 0; } NeAACDecPostSeekReset(decoder, i); + elapsed_time = (sound_samples_done * 10) / + (ci->id3->frequency / 100); + } else if (param) { + elapsed_time = param; + action = CODEC_ACTION_SEEK_TIME; } else { + elapsed_time = 0; sound_samples_done = 0; } - elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100); ci->set_elapsed(elapsed_time); if (i == 0) @@ -152,7 +160,8 @@ enum codec_status codec_run(void) /* 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_NULL) + action = ci->get_command(¶m); if (action == CODEC_ACTION_HALT) break; @@ -180,6 +189,8 @@ enum codec_status codec_run(void) ci->seek_complete(); } + action = CODEC_ACTION_NULL; + /* There can be gaps between chunks, so skip ahead if needed. It * doesn't seem to happen much, but it probably means that a * "proper" file can have chunks out of order. Why one would want diff --git a/lib/rbcodec/codecs/aiff.c b/lib/rbcodec/codecs/aiff.c index 3bedfa5760..9fee781c03 100644 --- a/lib/rbcodec/codecs/aiff.c +++ b/lib/rbcodec/codecs/aiff.c @@ -99,6 +99,7 @@ enum codec_status codec_run(void) codec_set_replaygain(ci->id3); /* Need to save offset for later use (cleared indirectly by advance_buffer) */ + param = ci->id3->elapsed; bytesdone = ci->id3->offset; /* assume the AIFF header is less than 1024 bytes */ @@ -270,10 +271,20 @@ enum codec_status codec_run(void) ci->advance_buffer(firstblockposn); /* make sure we're at the correct offset */ - if (bytesdone > (uint32_t) firstblockposn) { + if (bytesdone > (uint32_t) firstblockposn || param) { + uint32_t seek_val; + int seek_mode; + + if (bytesdone) { + seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone); + seek_mode = PCM_SEEK_POS; + } else { + seek_val = param; + seek_mode = PCM_SEEK_TIME; + } + /* Round down to previous block */ - struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, - PCM_SEEK_POS, NULL); + struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, NULL); if (newpos->pos > format.numbytes) return CODEC_OK; diff --git a/lib/rbcodec/codecs/alac.c b/lib/rbcodec/codecs/alac.c index 5eb6e001f7..a3a5ad43b8 100644 --- a/lib/rbcodec/codecs/alac.c +++ b/lib/rbcodec/codecs/alac.c @@ -50,7 +50,7 @@ enum codec_status codec_run(void) demux_res_t demux_res; stream_t input_stream; uint32_t samplesdone; - uint32_t elapsedtime = 0; + uint32_t elapsedtime; int samplesdecoded; unsigned int i; unsigned char* buffer; @@ -71,9 +71,9 @@ enum codec_status codec_run(void) 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)); + /* Read resume info before calling qtmovie_read. */ + elapsedtime = ci->id3->elapsed; + samplesdone = ci->id3->offset; /* if qtmovie_read returns successfully, the stream is up to * the movie data, which can be used directly by the decoder */ @@ -87,16 +87,24 @@ enum codec_status codec_run(void) /* 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, + + if (elapsedtime || samplesdone) { + if (samplesdone) { + samplesdone = + (uint32_t)((uint64_t)samplesdone*ci->id3->frequency / + (ci->id3->bitrate*128)); + } + else { + samplesdone = (elapsedtime/10) * (ci->id3->frequency/100); + } + + 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; } } + elapsedtime = (samplesdone*10)/(ci->id3->frequency/100); ci->set_elapsed(elapsedtime); /* The main decoding loop */ @@ -106,9 +114,6 @@ enum codec_status codec_run(void) if (action == CODEC_ACTION_HALT) break; - /* Request the required number of bytes from the input buffer */ - buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); - /* Deal with any pending seek requests */ if (action == CODEC_ACTION_SEEK_TIME) { if (m4a_seek(&demux_res, &input_stream, diff --git a/lib/rbcodec/codecs/ape.c b/lib/rbcodec/codecs/ape.c index 577e7b65e2..a6c5254d45 100644 --- a/lib/rbcodec/codecs/ape.c +++ b/lib/rbcodec/codecs/ape.c @@ -155,6 +155,7 @@ enum codec_status codec_run(void) int res; int firstbyte; size_t resume_offset; + enum codec_command_action action; intptr_t param; if (codec_init()) { @@ -162,8 +163,12 @@ enum codec_status codec_run(void) return CODEC_ERROR; } + action = CODEC_ACTION_NULL; + param = 0; + /* Remember the resume position - when the codec is opened, the playback engine will reset it. */ + elapsedtime = ci->id3->elapsed; resume_offset = ci->id3->offset; ci->seek_buffer(0); @@ -213,14 +218,21 @@ enum codec_status codec_run(void) ape_resume(&ape_ctx, resume_offset, ¤tframe, &samplesdone, &samplestoskip, &firstbyte); - } else { + elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100); + } + else { currentframe = 0; samplesdone = 0; samplestoskip = 0; firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */ + + if (elapsedtime) { + /* Resume by simulated seeking */ + param = elapsedtime; + action = CODEC_ACTION_SEEK_TIME; + } } - elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100); ci->set_elapsed(elapsedtime); /* Initialise the buffer */ @@ -247,36 +259,44 @@ frame_start: /* Decode the frame a chunk at a time */ while (nblocks > 0) { - enum codec_command_action action = ci->get_command(¶m); + if (action == CODEC_ACTION_NULL) + action = ci->get_command(¶m); - if (action == CODEC_ACTION_HALT) - goto done; + if (action != CODEC_ACTION_NULL) { + if (action == CODEC_ACTION_HALT) + goto done; - /* Deal with any pending seek requests */ - if (action == CODEC_ACTION_SEEK_TIME) - { - if (ape_calc_seekpos(&ape_ctx, - (param/10) * (ci->id3->frequency/100), - ¤tframe, - &newfilepos, - &samplestoskip)) + /* Deal with any pending seek requests */ + if (action == CODEC_ACTION_SEEK_TIME) { - samplesdone = currentframe * ape_ctx.blocksperframe; - - /* APE's bytestream is weird... */ - firstbyte = 3 - (newfilepos & 3); - newfilepos &= ~3; - - ci->seek_buffer(newfilepos); - inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); + if (ape_calc_seekpos(&ape_ctx, + (param/10) * (ci->id3->frequency/100), + ¤tframe, + &newfilepos, + &samplestoskip)) + { + samplesdone = currentframe * ape_ctx.blocksperframe; + + /* APE's bytestream is weird... */ + firstbyte = 3 - (newfilepos & 3); + newfilepos &= ~3; + + 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(); + action = CODEC_ACTION_NULL; + goto frame_start; /* Sorry... */ + } - elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100); - ci->set_elapsed(elapsedtime); ci->seek_complete(); - goto frame_start; /* Sorry... */ } - ci->seek_complete(); + action = CODEC_ACTION_NULL; } blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks); diff --git a/lib/rbcodec/codecs/asap.c b/lib/rbcodec/codecs/asap.c index 19b39a44c4..2c350ba450 100644 --- a/lib/rbcodec/codecs/asap.c +++ b/lib/rbcodec/codecs/asap.c @@ -52,6 +52,8 @@ enum codec_status codec_run(void) return CODEC_ERROR; } + param = ci->id3->elapsed; + codec_set_replaygain(ci->id3); int bytes_done =0; @@ -86,8 +88,6 @@ enum codec_status codec_run(void) ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); bytesPerSample = 4; } - /* reset eleapsed */ - ci->set_elapsed(0); song = asap.module_info->default_song; duration = asap.module_info->durations[song]; @@ -100,6 +100,11 @@ enum codec_status codec_run(void) ASAP_PlaySong(&asap, song, duration); ASAP_MutePokeyChannels(&asap, 0); + if (param) + goto resume_start; + + ci->set_elapsed(0); + /* The main decoder loop */ while (1) { enum codec_command_action action = ci->get_command(¶m); @@ -108,6 +113,7 @@ enum codec_status codec_run(void) break; if (action == CODEC_ACTION_SEEK_TIME) { + resume_start: /* New time is ready in param */ /* seek to pos */ diff --git a/lib/rbcodec/codecs/atrac3_oma.c b/lib/rbcodec/codecs/atrac3_oma.c index 50f7c8f163..65d9ed8b38 100644 --- a/lib/rbcodec/codecs/atrac3_oma.c +++ b/lib/rbcodec/codecs/atrac3_oma.c @@ -50,13 +50,15 @@ enum codec_status codec_run(void) int elapsed = 0; size_t resume_offset; intptr_t param; - enum codec_command_action action = CODEC_ACTION_NULL; + enum codec_command_action action; if (codec_init()) { DEBUGF("codec init failed\n"); return CODEC_ERROR; } + action = CODEC_ACTION_NULL; + param = ci->id3->elapsed; resume_offset = ci->id3->offset; codec_set_replaygain(ci->id3); @@ -79,11 +81,13 @@ enum codec_status codec_run(void) 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; + if (resume_offset) { + resume_offset -= MIN(resume_offset, ci->id3->first_frame_offset); /* calculate resume_offset in frames */ - resume_offset = (int)resume_offset / FRAMESIZE; - param = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE); + param = (resume_offset/FRAMESIZE) * ((FRAMESIZE * 8)/BITRATE); + } + + if ((unsigned long)param) { action = CODEC_ACTION_SEEK_TIME; } else { @@ -100,11 +104,9 @@ enum codec_status codec_run(void) if (action == CODEC_ACTION_HALT) break; - bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); - if (action == CODEC_ACTION_SEEK_TIME) { /* Do not allow seeking beyond the file's length */ - if ((unsigned) param > ci->id3->length) { + if ((unsigned long) param > ci->id3->length) { ci->set_elapsed(ci->id3->length); ci->seek_complete(); break; @@ -123,7 +125,6 @@ enum codec_status codec_run(void) 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->seek_complete(); @@ -131,6 +132,8 @@ enum codec_status codec_run(void) action = CODEC_ACTION_NULL; + bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); + res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE); if(res != (int)FRAMESIZE) { diff --git a/lib/rbcodec/codecs/atrac3_rm.c b/lib/rbcodec/codecs/atrac3_rm.c index 997507425e..4b528c0a8d 100644 --- a/lib/rbcodec/codecs/atrac3_rm.c +++ b/lib/rbcodec/codecs/atrac3_rm.c @@ -57,17 +57,19 @@ enum codec_status codec_run(void) uint8_t *bit_buffer; uint16_t fs,sps,h; uint32_t packet_count; - int scrambling_unit_size, num_units, elapsed = 0; + int scrambling_unit_size, num_units, elapsed; int playback_on = -1; size_t resume_offset; intptr_t param; - enum codec_command_action action = CODEC_ACTION_NULL; + enum codec_command_action action; if (codec_init()) { DEBUGF("codec init failed\n"); return CODEC_ERROR; } + action = CODEC_ACTION_NULL; + elapsed = ci->id3->elapsed; resume_offset = ci->id3->offset; codec_set_replaygain(ci->id3); @@ -98,15 +100,20 @@ enum codec_status codec_run(void) } /* 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; + if(resume_offset) { + resume_offset -= MIN(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); - param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); + elapsed = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); + } + + if (elapsed > 0) { + param = elapsed; action = CODEC_ACTION_SEEK_TIME; } else { + elapsed = 0; ci->set_elapsed(0); } @@ -151,6 +158,7 @@ seek_start : /* Seek to the start of the track */ if (param == 0) { + elapsed = 0; ci->set_elapsed(0); ci->seek_complete(); action = CODEC_ACTION_NULL; diff --git a/lib/rbcodec/codecs/au.c b/lib/rbcodec/codecs/au.c index 7ae7fe3e94..18d4296125 100644 --- a/lib/rbcodec/codecs/au.c +++ b/lib/rbcodec/codecs/au.c @@ -139,6 +139,7 @@ enum codec_status codec_run(void) codec_set_replaygain(ci->id3); /* Need to save offset for later use (cleared indirectly by advance_buffer) */ + param = ci->id3->elapsed; bytesdone = ci->id3->offset; ci->memset(&format, 0, sizeof(struct pcm_format)); @@ -236,10 +237,20 @@ enum codec_status codec_run(void) } /* make sure we're at the correct offset */ - if (bytesdone > (uint32_t) firstblockposn) { + if (bytesdone > (uint32_t) firstblockposn || param) { + uint32_t seek_val; + int seek_mode; + + if (bytesdone) { + seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone); + seek_mode = PCM_SEEK_POS; + } else { + seek_val = param; + seek_mode = PCM_SEEK_TIME; + } + /* Round down to previous block */ - struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, - PCM_SEEK_POS, NULL); + struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, NULL); if (newpos->pos > format.numbytes) goto done; diff --git a/lib/rbcodec/codecs/ay.c b/lib/rbcodec/codecs/ay.c index b11ad84294..88936df131 100644 --- a/lib/rbcodec/codecs/ay.c +++ b/lib/rbcodec/codecs/ay.c @@ -56,6 +56,7 @@ enum codec_status codec_run(void) /* reset values */ track = is_multitrack = 0; elapsed_time = 0; + param = ci->id3->elapsed; DEBUGF("AY: next_track\n"); if (codec_init()) { @@ -87,6 +88,10 @@ enum codec_status codec_run(void) is_multitrack = 1; } + if (param) { + goto resume_start; + } + next_track: set_codec_track(track, is_multitrack); @@ -98,6 +103,7 @@ next_track: break; if (action == CODEC_ACTION_SEEK_TIME) { + resume_start: if (is_multitrack) { track = param/1000; ci->seek_complete(); diff --git a/lib/rbcodec/codecs/cook.c b/lib/rbcodec/codecs/cook.c index 55188aad36..402d1d3fa6 100644 --- a/lib/rbcodec/codecs/cook.c +++ b/lib/rbcodec/codecs/cook.c @@ -56,14 +56,16 @@ enum codec_status codec_run(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; + intptr_t param; + enum codec_command_action action; if (codec_init()) { DEBUGF("codec init failed\n"); return CODEC_ERROR; } + action = CODEC_ACTION_NULL; + param = ci->id3->elapsed; resume_offset = ci->id3->offset; codec_set_replaygain(ci->id3); @@ -97,12 +99,15 @@ enum codec_status codec_run(void) } /* 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; + if(resume_offset) { + resume_offset -= MIN(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); param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); + } + + if (param) { action = CODEC_ACTION_SEEK_TIME; } else { diff --git a/lib/rbcodec/codecs/flac.c b/lib/rbcodec/codecs/flac.c index 3390c24a2c..eab6e7c2bc 100644 --- a/lib/rbcodec/codecs/flac.c +++ b/lib/rbcodec/codecs/flac.c @@ -468,7 +468,8 @@ enum codec_status codec_run(void) return CODEC_ERROR; } - /* Need to save offset for later use (cleared indirectly by flac_init) */ + /* Need to save resume for later use (cleared indirectly by flac_init) */ + elapsedtime = ci->id3->elapsed; samplesdone = ci->id3->offset; if (!flac_init(&fc,ci->id3->first_frame_offset)) { @@ -481,9 +482,16 @@ enum codec_status codec_run(void) STEREO_MONO : STEREO_NONINTERLEAVED); codec_set_replaygain(ci->id3); - flac_seek_offset(&fc, samplesdone); - samplesdone=fc.samplenumber+fc.blocksize; - elapsedtime=((uint64_t)samplesdone*1000)/(ci->id3->frequency); + if (samplesdone || !elapsedtime) { + flac_seek_offset(&fc, samplesdone); + samplesdone=fc.samplenumber+fc.blocksize; + elapsedtime=((uint64_t)samplesdone*1000)/(ci->id3->frequency); + } + else if (!flac_seek(&fc,(uint32_t)((uint64_t)elapsedtime + *ci->id3->frequency/1000))) { + elapsedtime = 0; + } + ci->set_elapsed(elapsedtime); /* The main decoding loop */ diff --git a/lib/rbcodec/codecs/gbs.c b/lib/rbcodec/codecs/gbs.c index def05ed351..717f56c82f 100644 --- a/lib/rbcodec/codecs/gbs.c +++ b/lib/rbcodec/codecs/gbs.c @@ -76,6 +76,11 @@ enum codec_status codec_run(void) if (gbs_emu.m3u.size > 0) gbs_emu.track_count = gbs_emu.m3u.size; + if (ci->id3->elapsed) { + track = ci->id3->elapsed/1000; + if (track >= gbs_emu.track_count) return CODEC_OK; + } + next_track: set_codec_track(track); diff --git a/lib/rbcodec/codecs/hes.c b/lib/rbcodec/codecs/hes.c index 849fd88f12..56f49621c6 100644 --- a/lib/rbcodec/codecs/hes.c +++ b/lib/rbcodec/codecs/hes.c @@ -76,6 +76,11 @@ enum codec_status codec_run(void) if (hes_emu.m3u.size > 0) hes_emu.track_count = hes_emu.m3u.size; + if (ci->id3->elapsed) { + track = ci->id3->elapsed/1000; + if (track >= hes_emu.track_count) return CODEC_OK; + } + next_track: set_codec_track(track); diff --git a/lib/rbcodec/codecs/kss.c b/lib/rbcodec/codecs/kss.c index 92efcd4e5f..e6cf866cdd 100644 --- a/lib/rbcodec/codecs/kss.c +++ b/lib/rbcodec/codecs/kss.c @@ -79,6 +79,11 @@ enum codec_status codec_run(void) if (kss_emu.m3u.size > 0) kss_emu.track_count = kss_emu.m3u.size; + if (ci->id3->elapsed) { + track = ci->id3->elapsed/1000; + if (track >= kss_emu.track_count) return CODEC_OK; + } + next_track: set_codec_track(track); diff --git a/lib/rbcodec/codecs/mod.c b/lib/rbcodec/codecs/mod.c index 8bb2dc5163..4dd0cde6e5 100644 --- a/lib/rbcodec/codecs/mod.c +++ b/lib/rbcodec/codecs/mod.c @@ -1319,7 +1319,16 @@ enum codec_status codec_run(void) loadmod(modfile); /* The main decoder loop */ - ci->set_elapsed(0); +#if 0 + /* Needs to be a bit more elaborate or critical stuff is missed */ + if (ci->id3->elapsed) { + modplayer.patterntableposition = ci->id3->elapsed/1000; + modplayer.currentline = 0; + } +#endif + + ci->set_elapsed(modplayer.patterntableposition*1000); + bytesdone = 0; old_patterntableposition = 0; diff --git a/lib/rbcodec/codecs/mpa.c b/lib/rbcodec/codecs/mpa.c index 07db248099..ca12087e87 100644 --- a/lib/rbcodec/codecs/mpa.c +++ b/lib/rbcodec/codecs/mpa.c @@ -346,6 +346,11 @@ enum codec_status codec_run(void) current_frequency = ci->id3->frequency; codec_set_replaygain(ci->id3); + if (!ci->id3->offset && ci->id3->elapsed) { + /* Have elapsed time but not offset */ + ci->id3->offset = get_file_pos(ci->id3->elapsed); + } + if (ci->id3->offset) { ci->seek_buffer(ci->id3->offset); set_elapsed(ci->id3); diff --git a/lib/rbcodec/codecs/mpc.c b/lib/rbcodec/codecs/mpc.c index 9db40242dc..79f2aa22db 100644 --- a/lib/rbcodec/codecs/mpc.c +++ b/lib/rbcodec/codecs/mpc.c @@ -108,6 +108,7 @@ enum codec_status codec_run(void) * sample seek position from the file offset, the sampling frequency and * the bitrate. As the saved position is exactly calculated the reverse way * there is no loss of information except rounding. */ + elapsed_time = ci->id3->elapsed; samplesdone = 100 * (((mpc_uint64_t)ci->id3->offset * frequency) / byterate); /* Set up digital signal processing for correct number of channels */ @@ -122,19 +123,24 @@ enum codec_status codec_run(void) codec_set_replaygain(ci->id3); - /* Resume to saved sample offset. */ - elapsed_time = 0; - - if (samplesdone > 0) + if (samplesdone > 0 || elapsed_time) { - if (mpc_demux_seek_sample(demux, samplesdone) == MPC_STATUS_OK) + mpc_int64_t new_offset = samplesdone; + + if (new_offset <= 0) + new_offset = (elapsed_time/10)*frequency; /* by time */ + + /* Resume to sample offset. */ + if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK) { - elapsed_time = (samplesdone*10)/frequency; + samplesdone = new_offset; } else { samplesdone = 0; } + + elapsed_time = (samplesdone*10)/frequency; } ci->set_elapsed(elapsed_time); diff --git a/lib/rbcodec/codecs/nsf.c b/lib/rbcodec/codecs/nsf.c index 4c5b37c3fa..cbdf8e3ec5 100644 --- a/lib/rbcodec/codecs/nsf.c +++ b/lib/rbcodec/codecs/nsf.c @@ -57,6 +57,7 @@ enum codec_status codec_run(void) track = is_multitrack = 0; elapsed_time = 0; + param = ci->id3->elapsed; DEBUGF("NSF: next_track\n"); if (codec_init()) { @@ -85,6 +86,10 @@ enum codec_status codec_run(void) if (nsf_emu.track_count > 1) is_multitrack = 1; + if (param) { + goto resume_start; + } + next_track: set_codec_track(track, is_multitrack); @@ -96,6 +101,7 @@ next_track: break; if (action == CODEC_ACTION_SEEK_TIME) { + resume_start: if (is_multitrack) { track = param/1000; ci->seek_complete(); diff --git a/lib/rbcodec/codecs/opus.c b/lib/rbcodec/codecs/opus.c index 15d96ff6fe..2c495aa8d0 100644 --- a/lib/rbcodec/codecs/opus.c +++ b/lib/rbcodec/codecs/opus.c @@ -314,6 +314,7 @@ enum codec_status codec_main(enum codec_entry_call_reason reason) enum codec_status codec_run(void) { int error = CODEC_ERROR; + enum codec_command_action action; intptr_t param; ogg_sync_state oy; ogg_page og; @@ -325,13 +326,17 @@ enum codec_status codec_run(void) OpusDecoder *st = NULL; OpusHeader header; int ret; - unsigned long strtoffset = ci->id3->offset; + unsigned long strtoffset; int skip = 0; int64_t seek_target; uint64_t granule_pos; ogg_malloc_init(); + action = CODEC_ACTION_NULL; + param = ci->id3->elapsed; + strtoffset = ci->id3->offset; + global_stack = 0; #if defined(CPU_COLDFIRE) @@ -351,28 +356,40 @@ enum codec_status codec_run(void) ci->seek_buffer(0); ci->set_elapsed(0); + if (!strtoffset && param) { + action = CODEC_ACTION_SEEK_TIME; + } + + goto next_page; + while (1) { - enum codec_command_action action = ci->get_command(¶m); + if (action == CODEC_ACTION_NULL) + action = ci->get_command(¶m); - if (action == CODEC_ACTION_HALT) - break; + if (action != CODEC_ACTION_NULL) { + if (action == CODEC_ACTION_HALT) + break; + + if (action == CODEC_ACTION_SEEK_TIME) { + if (st != NULL) { + /* calculate granule to seek to (including seek rewind) */ + seek_target = (48LL * param) + header.preskip; + skip = MIN(seek_target, SEEK_REWIND); + seek_target -= skip; - if (action == CODEC_ACTION_SEEK_TIME) { - if (st != NULL) { - /* calculate granule to seek to (including seek rewind) */ - seek_target = (48LL * param) + header.preskip; - skip = MIN(seek_target, SEEK_REWIND); - seek_target -= skip; + LOGF("Opus seek page:%lld,%lld,%ld\n", + seek_target, page_granule, (long)param); + speex_seek_page_granule(seek_target, page_granule, &oy, &os); + } - LOGF("Opus seek page:%lld,%lld,%ld\n", - seek_target, page_granule, (long)param); - speex_seek_page_granule(seek_target, page_granule, &oy, &os); + ci->set_elapsed(param); + ci->seek_complete(); } - ci->set_elapsed(param); - ci->seek_complete(); + action = CODEC_ACTION_NULL; } + next_page: /*Get the ogg buffer for writing*/ if (get_more_data(&oy) < 1) { goto done; diff --git a/lib/rbcodec/codecs/raac.c b/lib/rbcodec/codecs/raac.c index 523560b63e..d2d3531028 100644 --- a/lib/rbcodec/codecs/raac.c +++ b/lib/rbcodec/codecs/raac.c @@ -63,14 +63,16 @@ enum codec_status codec_run(void) unsigned char c = 0; /* channels */ int playback_on = -1; size_t resume_offset; + enum codec_command_action action; intptr_t param; - enum codec_command_action action = CODEC_ACTION_NULL; if (codec_init()) { DEBUGF("FAAD: Codec init error\n"); return CODEC_ERROR; } + action = CODEC_ACTION_NULL; + param = ci->id3->elapsed; resume_offset = ci->id3->offset; ci->memset(&rmctx,0,sizeof(RMContext)); @@ -104,15 +106,21 @@ enum codec_status codec_run(void) } /* 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; + if (resume_offset) { + resume_offset -= MIN(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); param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); + } + + if (param > 0) { action = CODEC_ACTION_SEEK_TIME; } - ci->set_elapsed(0); - ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); + else { + /* Seek to the first packet */ + ci->set_elapsed(0); + ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); + } /* The main decoding loop */ while (1) { @@ -124,7 +132,7 @@ enum codec_status codec_run(void) if (action == CODEC_ACTION_SEEK_TIME) { /* Do not allow seeking beyond the file's length */ - if ((unsigned) param > ci->id3->length) { + if ((unsigned long)param > ci->id3->length) { ci->set_elapsed(ci->id3->length); ci->seek_complete(); break; @@ -164,6 +172,7 @@ enum codec_status codec_run(void) 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); diff --git a/lib/rbcodec/codecs/sgc.c b/lib/rbcodec/codecs/sgc.c index 348a54a2d3..eb260975c5 100644 --- a/lib/rbcodec/codecs/sgc.c +++ b/lib/rbcodec/codecs/sgc.c @@ -91,6 +91,11 @@ enum codec_status codec_run(void) if (sgc_emu.m3u.size > 0) sgc_emu.track_count = sgc_emu.m3u.size; + if (ci->id3->elapsed) { + track = ci->id3->elapsed/1000; + if (track >= sgc_emu.track_count) return CODEC_OK; + } + next_track: set_codec_track(track); diff --git a/lib/rbcodec/codecs/sid.c b/lib/rbcodec/codecs/sid.c index 1a6d04155d..6e39d3f759 100644 --- a/lib/rbcodec/codecs/sid.c +++ b/lib/rbcodec/codecs/sid.c @@ -1253,6 +1253,7 @@ enum codec_status codec_run(void) unsigned char subSongsMax, subSong, song_speed; unsigned char *sidfile = NULL; intptr_t param; + bool resume; if (codec_init()) { return CODEC_ERROR; @@ -1269,15 +1270,10 @@ enum codec_status codec_run(void) return CODEC_ERROR; } - c64Init(SAMPLE_RATE); - LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, - &subSongsMax, &subSong, &song_speed, (unsigned short)filesize); - sidPoke(24, 15); /* Turn on full volume */ - cpuJSR(init_addr, subSong); /* Start the song initialize */ + param = ci->id3->elapsed; + resume = param != 0; - - /* Set the elapsed time to the current subsong (in seconds) */ - ci->set_elapsed(subSong*1000); + goto sid_start; /* The main decoder loop */ while (1) { @@ -1287,20 +1283,26 @@ enum codec_status codec_run(void) break; if (action == CODEC_ACTION_SEEK_TIME) { + sid_start: /* New time is ready in param */ /* Start playing from scratch */ c64Init(SAMPLE_RATE); LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, - &subSongsMax, &subSong, &song_speed, (unsigned short)filesize); + &subSongsMax, &subSong, &song_speed, + (unsigned short)filesize); sidPoke(24, 15); /* Turn on full volume */ - subSong = param / 1000; /* Now use the current seek time in seconds as subsong */ + if (!resume || (resume && param)) + 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->set_elapsed(subSong*1000); ci->seek_complete(); + + resume = false; } nSamplesRendered = 0; diff --git a/lib/rbcodec/codecs/smaf.c b/lib/rbcodec/codecs/smaf.c index d56aa0a860..e4ec6342b2 100644 --- a/lib/rbcodec/codecs/smaf.c +++ b/lib/rbcodec/codecs/smaf.c @@ -360,7 +360,8 @@ enum codec_status codec_run(void) codec_set_replaygain(ci->id3); - /* Need to save offset for later use (cleared indirectly by advance_buffer) */ + /* Need to save resume for later use (cleared indirectly by advance_buffer) */ + param = ci->id3->elapsed; bytesdone = ci->id3->offset; decodedsamples = 0; @@ -408,11 +409,21 @@ enum codec_status codec_run(void) ci->seek_buffer(firstblockposn); /* make sure we're at the correct offset */ - if (bytesdone > (uint32_t) firstblockposn) - { + if (bytesdone > (uint32_t) firstblockposn || param) { + uint32_t seek_val; + int seek_mode; + + if (bytesdone) { + seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone); + seek_mode = PCM_SEEK_POS; + } else { + seek_val = param; + seek_mode = PCM_SEEK_TIME; + } + /* Round down to previous block */ - struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, - PCM_SEEK_POS, &read_buffer); + struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, + &read_buffer); if (newpos->pos > format.numbytes) return CODEC_OK; diff --git a/lib/rbcodec/codecs/speex.c b/lib/rbcodec/codecs/speex.c index ac3bc963b1..a073151ee2 100644 --- a/lib/rbcodec/codecs/speex.c +++ b/lib/rbcodec/codecs/speex.c @@ -381,7 +381,6 @@ enum codec_status codec_run(void) int error = CODEC_ERROR; SpeexBits bits; - int eof = 0; spx_ogg_sync_state oy; spx_ogg_page og; spx_ogg_packet op; @@ -403,9 +402,10 @@ enum codec_status codec_run(void) int packet_count = 0; int lookahead; int headerssize = 0; - unsigned long strtoffset = ci->id3->offset; + unsigned long strtoffset; void *st = NULL; int j = 0; + enum codec_command_action action; intptr_t param; memset(&bits, 0, sizeof(bits)); @@ -416,6 +416,10 @@ enum codec_status codec_run(void) goto exit; } + action = CODEC_ACTION_NULL; + param = ci->id3->elapsed; + strtoffset = ci->id3->offset; + ci->seek_buffer(0); ci->set_elapsed(0); @@ -425,29 +429,39 @@ enum codec_status codec_run(void) codec_set_replaygain(ci->id3); - eof = 0; - while (!eof) { - enum codec_command_action action = ci->get_command(¶m); - - if (action == CODEC_ACTION_HALT) - break; - - /*seek (seeks to the page before the position) */ - 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)param/1000) * - (spx_int64_t)samplerate, - page_granule, (long)param, - (page_granule/samplerate)*1000, samplerate); - - speex_seek_page_granule(((spx_int64_t)param/1000) * - (spx_int64_t)samplerate, - page_granule, &oy, headerssize); + if (!strtoffset && param) { + action = CODEC_ACTION_SEEK_TIME; + } + + goto next_page; + + while (1) { + if (action == CODEC_ACTION_NULL) + action = ci->get_command(¶m); + + if (action != CODEC_ACTION_NULL) { + if (action == CODEC_ACTION_HALT) + break; + + /*seek (seeks to the page before the position) */ + 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)param/1000) * + (spx_int64_t)samplerate, + page_granule, (long)param, + (page_granule/samplerate)*1000, samplerate); + + speex_seek_page_granule(((spx_int64_t)param/1000) * + (spx_int64_t)samplerate, + page_granule, &oy, headerssize); + } + + ci->set_elapsed(param); + ci->seek_complete(); } - ci->set_elapsed(param); - ci->seek_complete(); + action = CODEC_ACTION_NULL; } next_page: diff --git a/lib/rbcodec/codecs/tta.c b/lib/rbcodec/codecs/tta.c index 564496a14e..b7660a920f 100644 --- a/lib/rbcodec/codecs/tta.c +++ b/lib/rbcodec/codecs/tta.c @@ -82,10 +82,20 @@ enum codec_status codec_run(void) decodedsamples = 0; endofstream = 0; - if (ci->id3->offset > 0) + if (ci->id3->offset || ci->id3->elapsed) { - /* Need to save offset for later use (cleared indirectly by advance_buffer) */ - new_pos = set_position(ci->id3->offset, TTA_SEEK_POS); + /* Need to save offset for later use (cleared indirectly by + advance_buffer) */ + unsigned int pos = ci->id3->offset; + enum tta_seek_type type = TTA_SEEK_POS; + + if (!pos) { + pos = ci->id3->elapsed / SEEK_STEP; + type = TTA_SEEK_TIME; + } + + new_pos = set_position(pos, type); + if (new_pos >= 0) decodedsamples = new_pos; } diff --git a/lib/rbcodec/codecs/vgm.c b/lib/rbcodec/codecs/vgm.c index 9f2f1b9c5e..126305944f 100644 --- a/lib/rbcodec/codecs/vgm.c +++ b/lib/rbcodec/codecs/vgm.c @@ -127,7 +127,10 @@ enum codec_status codec_run(void) Vgm_start_track(&vgm_emu); - ci->set_elapsed(0); + if (ci->id3->elapsed != 0) + Track_seek(&vgm_emu, ci->id3->elapsed); + + codec_update_elapsed(); codec_update_fade(); /* The main decoder loop */ diff --git a/lib/rbcodec/codecs/vorbis.c b/lib/rbcodec/codecs/vorbis.c index c09d2cea6d..ca9db9b802 100644 --- a/lib/rbcodec/codecs/vorbis.c +++ b/lib/rbcodec/codecs/vorbis.c @@ -126,7 +126,6 @@ enum codec_status codec_run(void) long n; int current_section; int previous_section; - int eof; ogg_int64_t vf_offsets[2]; ogg_int64_t vf_dataoffsets; ogg_uint32_t vf_serialnos; @@ -193,16 +192,17 @@ enum codec_status codec_run(void) if (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)); } - else { - ci->set_elapsed(0); + else if (ci->id3->elapsed) { + ov_time_seek(&vf, ci->id3->elapsed); } + ci->set_elapsed(ov_time_tell(&vf)); + previous_section = -1; - eof = 0; - while (!eof) { + + while (1) { enum codec_command_action action = ci->get_command(¶m); if (action == CODEC_ACTION_HALT) @@ -230,7 +230,7 @@ enum codec_status codec_run(void) } if (n == 0) { - eof = 1; + break; } else if (n < 0) { DEBUGF("Vorbis: Error decoding frame\n"); } else { diff --git a/lib/rbcodec/codecs/vox.c b/lib/rbcodec/codecs/vox.c index 66979e2911..d84af24cfc 100644 --- a/lib/rbcodec/codecs/vox.c +++ b/lib/rbcodec/codecs/vox.c @@ -73,7 +73,8 @@ enum codec_status codec_run(void) codec_set_replaygain(ci->id3); - /* Need to save offset for later use (cleared indirectly by advance_buffer) */ + /* Need to save resume for later use (cleared indirectly by advance_buffer) */ + param = ci->id3->elapsed; bytesdone = ci->id3->offset; ci->seek_buffer(0); @@ -123,10 +124,21 @@ enum codec_status codec_run(void) ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); /* make sure we're at the correct offset */ - if (bytesdone > (uint32_t) firstblockposn) { + if (bytesdone > (uint32_t) firstblockposn || param) { + uint32_t seek_val; + int seek_mode; + + if (bytesdone) { + seek_val = bytesdone - MIN((uint32_t )firstblockposn, bytesdone); + seek_mode = PCM_SEEK_POS; + } else { + seek_val = param; + seek_mode = PCM_SEEK_TIME; + } + /* Round down to previous block */ - struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, - PCM_SEEK_POS, &read_buffer); + struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, + &read_buffer); if (newpos->pos > format.numbytes) { return CODEC_OK; diff --git a/lib/rbcodec/codecs/wav.c b/lib/rbcodec/codecs/wav.c index cc65ab83b2..3208e2b5b8 100644 --- a/lib/rbcodec/codecs/wav.c +++ b/lib/rbcodec/codecs/wav.c @@ -182,7 +182,8 @@ enum codec_status codec_run(void) codec_set_replaygain(ci->id3); - /* Need to save offset for later use (cleared indirectly by advance_buffer) */ + /* Need to save resume for later use (cleared indirectly by advance_buffer) */ + param = ci->id3->elapsed; bytesdone = ci->id3->offset; /* get RIFF chunk header */ @@ -361,10 +362,21 @@ enum codec_status codec_run(void) } /* make sure we're at the correct offset */ - if (bytesdone > (uint32_t) firstblockposn) { + if (bytesdone > (uint32_t) firstblockposn || param) { + uint32_t seek_val; + int seek_mode; + + if (bytesdone) { + seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone); + seek_mode = PCM_SEEK_POS; + } else { + seek_val = param; + seek_mode = PCM_SEEK_TIME; + } + /* Round down to previous block */ - struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, - PCM_SEEK_POS, &read_buffer); + struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, + &read_buffer); if (newpos->pos > format.numbytes) return CODEC_OK; diff --git a/lib/rbcodec/codecs/wav64.c b/lib/rbcodec/codecs/wav64.c index 9b3b2d38e4..96e605faad 100644 --- a/lib/rbcodec/codecs/wav64.c +++ b/lib/rbcodec/codecs/wav64.c @@ -191,6 +191,7 @@ enum codec_status codec_run(void) codec_set_replaygain(ci->id3); /* Need to save offset for later use (cleared indirectly by advance_buffer) */ + param = ci->id3->elapsed; bytesdone = ci->id3->offset; /* get RIFF chunk header */ @@ -363,10 +364,22 @@ enum codec_status codec_run(void) } /* make sure we're at the correct offset */ - if (bytesdone > (uint32_t) firstblockposn) { + if (bytesdone > (uint32_t) firstblockposn || param) { + uint32_t seek_val; + int seek_mode; + + /* we prefer offset resume */ + if (bytesdone > (uint32_t) firstblockposn) { + seek_val = bytesdone - firstblockposn; + seek_mode = PCM_SEEK_POS; + } else { + seek_val = param; + seek_mode = PCM_SEEK_TIME; + } + /* Round down to previous block */ - struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, - PCM_SEEK_POS, &read_buffer); + struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, + &read_buffer); if (newpos->pos > format.numbytes) { return CODEC_OK; diff --git a/lib/rbcodec/codecs/wavpack.c b/lib/rbcodec/codecs/wavpack.c index c0cdafabac..d9c294397c 100644 --- a/lib/rbcodec/codecs/wavpack.c +++ b/lib/rbcodec/codecs/wavpack.c @@ -55,12 +55,16 @@ enum codec_status codec_run(void) int bps; */ int nchans, sr_100; + unsigned long offset; intptr_t param; if (codec_init()) return CODEC_ERROR; - ci->seek_buffer (ci->id3->offset); + param = ci->id3->elapsed; + offset = ci->id3->offset; + + ci->seek_buffer (offset); /* Create a decoder instance */ wpc = WavpackOpenFileInput (read_callback, error); @@ -75,7 +79,12 @@ enum codec_status codec_run(void) ci->configure(DSP_SET_STEREO_MODE, nchans == 2 ? STEREO_INTERLEAVED : STEREO_MONO); sr_100 = ci->id3->frequency / 100; - ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); + if (!offset && param) { + goto resume_start; /* resume by elapsed */ + } + else { + ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); + } /* The main decoder loop */ @@ -87,6 +96,7 @@ enum codec_status codec_run(void) break; if (action == CODEC_ACTION_SEEK_TIME) { + resume_start:; int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10; int n, d, skip; diff --git a/lib/rbcodec/codecs/wma.c b/lib/rbcodec/codecs/wma.c index 9039f81429..9a5e0c71fa 100755 --- a/lib/rbcodec/codecs/wma.c +++ b/lib/rbcodec/codecs/wma.c @@ -52,13 +52,16 @@ enum codec_status codec_run(void) int audiobufsize; int packetlength = 0; int errcount = 0; + enum codec_command_action action; intptr_t param; /* Remember the resume position - when the codec is opened, the playback engine will reset it. */ + elapsedtime = ci->id3->elapsed; resume_offset = ci->id3->offset; restart_track: + action = CODEC_ACTION_NULL; /* Proper reset of the decoder context. */ memset(&wmadec, 0, sizeof(wmadec)); @@ -78,13 +81,20 @@ restart_track: return CODEC_ERROR; } - if (resume_offset > ci->id3->first_frame_offset) + if (resume_offset > ci->id3->first_frame_offset || elapsedtime) { - /* Get start of current packet */ - int packet_offset = (resume_offset - ci->id3->first_frame_offset) - % wfx.packet_size; - ci->seek_buffer(resume_offset - packet_offset); - elapsedtime = asf_get_timestamp(&i); + if (resume_offset) { + /* Get start of current packet */ + int packet_offset = (resume_offset - + MIN(resume_offset, ci->id3->first_frame_offset)) + % wfx.packet_size; + ci->seek_buffer(resume_offset - packet_offset); + elapsedtime = asf_get_timestamp(&i); + } + else { + param = elapsedtime; + action = CODEC_ACTION_SEEK_TIME; + } } else { @@ -104,7 +114,8 @@ restart_track: /* The main decoding loop */ while (res >= 0) { - enum codec_command_action action = ci->get_command(¶m); + if (action == CODEC_ACTION_NULL) + action = ci->get_command(¶m); if (action != CODEC_ACTION_NULL) { @@ -126,6 +137,7 @@ restart_track: if (param == 0) { ci->set_elapsed(0); ci->seek_complete(); + elapsedtime = 0; goto restart_track; /* Pretend you never saw this... */ } @@ -140,6 +152,8 @@ restart_track: ci->set_elapsed(elapsedtime); ci->seek_complete(); } + + action = CODEC_ACTION_NULL; } errcount = 0; diff --git a/lib/rbcodec/codecs/wmapro.c b/lib/rbcodec/codecs/wmapro.c index d99ca1aa9e..f15f36813d 100644 --- a/lib/rbcodec/codecs/wmapro.c +++ b/lib/rbcodec/codecs/wmapro.c @@ -55,6 +55,8 @@ enum codec_status codec_run(void) int size; /* Size of the input frame to the decoder */ intptr_t param; + elapsedtime = ci->id3->elapsed; + restart_track: if (codec_init()) { LOGF("(WMA PRO) Error: Error initialising codec\n"); @@ -75,11 +77,17 @@ restart_track: return CODEC_ERROR; } - /* Now advance the file position to the first frame */ - ci->seek_buffer(ci->id3->first_frame_offset); + if (elapsedtime) { + elapsedtime = asf_seek(elapsedtime, &wfx); + if (elapsedtime < 1) + return CODEC_OK; + } + else { + /* Now advance the file position to the first frame */ + ci->seek_buffer(ci->id3->first_frame_offset); + } - elapsedtime = 0; - ci->set_elapsed(0); + ci->set_elapsed(elapsedtime); /* The main decoding loop */ @@ -95,6 +103,7 @@ restart_track: if (param == 0) { ci->set_elapsed(0); ci->seek_complete(); + elapsedtime = 0; goto restart_track; /* Pretend you never saw this... */ } diff --git a/lib/rbcodec/codecs/wmavoice.c b/lib/rbcodec/codecs/wmavoice.c index 214e0737e7..4c89c6dc96 100644 --- a/lib/rbcodec/codecs/wmavoice.c +++ b/lib/rbcodec/codecs/wmavoice.c @@ -67,7 +67,6 @@ enum codec_status codec_run(void) { uint32_t elapsedtime; asf_waveformatex_t wfx; /* Holds the stream properties */ - size_t resume_offset; int res; /* Return values from asf_read_packet() and decode_packet() */ uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */ int audiobufsize; /* Payload size */ @@ -76,8 +75,8 @@ enum codec_status codec_run(void) int pktcnt = 0; /* Count of the packets played */ intptr_t param; - /* Remember the resume position */ - resume_offset = ci->id3->offset; + elapsedtime = ci->id3->elapsed; + restart_track: if (codec_init()) { LOGF("(WMA Voice) Error: Error initialising codec\n"); @@ -105,13 +104,17 @@ restart_track: return CODEC_ERROR; } - /* Now advance the file position to the first frame */ - ci->seek_buffer(ci->id3->first_frame_offset); - - elapsedtime = 0; - ci->set_elapsed(0); + if (elapsedtime) { + elapsedtime = asf_seek(elapsedtime, &wfx); + if (elapsedtime < 1) + return CODEC_OK; + } + else { + /* Now advance the file position to the first frame */ + ci->seek_buffer(ci->id3->first_frame_offset); + } - resume_offset = 0; + ci->set_elapsed(elapsedtime); /* The main decoding loop */ @@ -129,6 +132,7 @@ restart_track: if (param == 0) { ci->set_elapsed(0); ci->seek_complete(); + elapsedtime = 0; goto restart_track; /* Pretend you never saw this... */ } @@ -136,7 +140,7 @@ restart_track: if (elapsedtime < 1){ ci->set_elapsed(0); ci->seek_complete(); - goto next_track; + break; } ci->set_elapsed(elapsedtime); |