From bad350bc18ab81661253bf42245b9e3fa175d026 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 25 Dec 2009 19:47:33 +0100 Subject: decoder_api: added function decoder_timestamp() Remove the data_time parameter from decoder_data(). This patch eliminates the timestamp counting in most decoder plugins, because the MPD core will do it automatically by default. --- src/decoder/_flac_common.c | 9 +-------- src/decoder/audiofile_plugin.c | 9 +++------ src/decoder/faad_plugin.c | 8 +------- src/decoder/ffmpeg_plugin.c | 10 ++++------ src/decoder/fluidsynth_plugin.c | 2 +- src/decoder/mad_plugin.c | 1 - src/decoder/mikmod_plugin.c | 5 ----- src/decoder/modplug_plugin.c | 6 ------ src/decoder/mp4ff_plugin.c | 4 ++-- src/decoder/mpcdec_plugin.c | 16 ++++------------ src/decoder/mpg123_decoder_plugin.c | 6 +----- src/decoder/sidplay_plugin.cxx | 8 ++++---- src/decoder/sndfile_decoder_plugin.c | 3 +-- src/decoder/vorbis_plugin.c | 1 - src/decoder/wavpack_plugin.c | 11 ++--------- src/decoder/wildmidi_plugin.c | 2 -- src/decoder_api.c | 22 +++++++++++++++++++--- src/decoder_api.h | 11 ++++++++++- src/decoder_internal.h | 5 +++++ src/decoder_thread.c | 1 + 20 files changed, 59 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/decoder/_flac_common.c b/src/decoder/_flac_common.c index 70b2c0202..4dd2b46ea 100644 --- a/src/decoder/_flac_common.c +++ b/src/decoder/_flac_common.c @@ -161,7 +161,6 @@ flac_common_write(struct flac_data *data, const FLAC__Frame * frame, enum decoder_command cmd; size_t buffer_size = frame->header.blocksize * data->frame_size; void *buffer; - float position; unsigned bit_rate; buffer = pcm_buffer_get(&data->buffer, buffer_size); @@ -170,12 +169,6 @@ flac_common_write(struct flac_data *data, const FLAC__Frame * frame, data->sample_format, buf, 0, frame->header.blocksize); - if (data->next_frame >= data->first_frame) - position = (float)(data->next_frame - data->first_frame) / - frame->header.sample_rate; - else - position = 0; - if (nbytes > 0) bit_rate = nbytes * 8 * frame->header.sample_rate / (1000 * frame->header.blocksize); @@ -184,7 +177,7 @@ flac_common_write(struct flac_data *data, const FLAC__Frame * frame, cmd = decoder_data(data->decoder, data->input_stream, buffer, buffer_size, - position, bit_rate, + bit_rate, data->replay_gain_info); data->next_frame += frame->header.blocksize; switch (cmd) { diff --git a/src/decoder/audiofile_plugin.c b/src/decoder/audiofile_plugin.c index a1fefcb0d..18cfdda5d 100644 --- a/src/decoder/audiofile_plugin.c +++ b/src/decoder/audiofile_plugin.c @@ -160,7 +160,7 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) struct audio_format audio_format; float total_time; uint16_t bit_rate; - int ret, current = 0; + int ret; char chunk[CHUNK_SIZE]; enum decoder_command cmd; @@ -204,17 +204,14 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) if (ret <= 0) break; - current += ret; cmd = decoder_data(decoder, NULL, chunk, ret * fs, - (float)current / - (float)audio_format.sample_rate, bit_rate, NULL); if (cmd == DECODE_COMMAND_SEEK) { - current = decoder_seek_where(decoder) * + AFframecount frame = decoder_seek_where(decoder) * audio_format.sample_rate; - afSeekFrame(af_fp, AF_DEFAULT_TRACK, current); + afSeekFrame(af_fp, AF_DEFAULT_TRACK, frame); decoder_command_finished(decoder); cmd = DECODE_COMMAND_NONE; diff --git a/src/decoder/faad_plugin.c b/src/decoder/faad_plugin.c index c91f8e8f6..2272963b9 100644 --- a/src/decoder/faad_plugin.c +++ b/src/decoder/faad_plugin.c @@ -383,7 +383,6 @@ static void faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is) { GError *error = NULL; - float file_time; float total_time = 0; faacDecHandle decoder; struct audio_format audio_format; @@ -434,8 +433,6 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is) /* the decoder loop */ - file_time = 0.0; - do { size_t frame_size; const void *decoded; @@ -481,15 +478,12 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is) bit_rate = frame_info.bytesconsumed * 8.0 * frame_info.channels * audio_format.sample_rate / frame_info.samples / 1000 + 0.5; - file_time += - (float)(frame_info.samples) / frame_info.channels / - audio_format.sample_rate; } /* send PCM samples to MPD */ cmd = decoder_data(mpd_decoder, is, decoded, - (size_t)frame_info.samples * 2, file_time, + (size_t)frame_info.samples * 2, bit_rate, NULL); } while (cmd != DECODE_COMMAND_STOP); diff --git a/src/decoder/ffmpeg_plugin.c b/src/decoder/ffmpeg_plugin.c index 213621b8c..c702500d7 100644 --- a/src/decoder/ffmpeg_plugin.c +++ b/src/decoder/ffmpeg_plugin.c @@ -232,7 +232,6 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is, const AVRational *time_base) { enum decoder_command cmd = DECODE_COMMAND_NONE; - int position; uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2 + 16]; int16_t *aligned_buffer; size_t buffer_size; @@ -264,14 +263,13 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is, if (audio_size <= 0) continue; - position = packet->pts != (int64_t)AV_NOPTS_VALUE - ? av_rescale_q(packet->pts, *time_base, - (AVRational){1, 1}) - : 0; + if (packet->pts != (int64_t)AV_NOPTS_VALUE) + decoder_timestamp(decoder, + av_rescale_q(packet->pts, *time_base, + (AVRational){1, 1})); cmd = decoder_data(decoder, is, aligned_buffer, audio_size, - position, codec_context->bit_rate / 1000, NULL); } return cmd; diff --git a/src/decoder/fluidsynth_plugin.c b/src/decoder/fluidsynth_plugin.c index 1b1e6a531..2656b5ebd 100644 --- a/src/decoder/fluidsynth_plugin.c +++ b/src/decoder/fluidsynth_plugin.c @@ -204,7 +204,7 @@ fluidsynth_file_decode(struct decoder *decoder, const char *path_fs) break; cmd = decoder_data(decoder, NULL, buffer, sizeof(buffer), - 0, 0, NULL); + 0, NULL); } while (cmd == DECODE_COMMAND_NONE); /* clean up */ diff --git a/src/decoder/mad_plugin.c b/src/decoder/mad_plugin.c index 50c9f62bc..f23ab3c21 100644 --- a/src/decoder/mad_plugin.c +++ b/src/decoder/mad_plugin.c @@ -1025,7 +1025,6 @@ mp3_send_pcm(struct mp3_data *data, unsigned i, unsigned pcm_length, cmd = decoder_data(data->decoder, data->input_stream, data->output_buffer, sizeof(data->output_buffer[0]) * num_samples, - data->elapsed_time, data->bit_rate / 1000, replay_gain_info); if (cmd != DECODE_COMMAND_NONE) diff --git a/src/decoder/mikmod_plugin.c b/src/decoder/mikmod_plugin.c index 2185fe21c..bbb330cb7 100644 --- a/src/decoder/mikmod_plugin.c +++ b/src/decoder/mikmod_plugin.c @@ -147,7 +147,6 @@ mikmod_decoder_file_decode(struct decoder *decoder, const char *path_fs) struct audio_format audio_format; int ret; SBYTE buffer[MIKMOD_FRAME_SIZE]; - unsigned frame_size, current_frame = 0; enum decoder_command cmd = DECODE_COMMAND_NONE; path2 = g_strdup(path_fs); @@ -167,14 +166,10 @@ mikmod_decoder_file_decode(struct decoder *decoder, const char *path_fs) decoder_initialized(decoder, &audio_format, false, 0); - frame_size = audio_format_frame_size(&audio_format); - Player_Start(handle); while (cmd == DECODE_COMMAND_NONE && Player_Active()) { ret = VC_WriteBytes(buffer, sizeof(buffer)); - current_frame += ret / frame_size; cmd = decoder_data(decoder, NULL, buffer, ret, - (float)current_frame / (float)mikmod_sample_rate, 0, NULL); } diff --git a/src/decoder/modplug_plugin.c b/src/decoder/modplug_plugin.c index df4a99f7f..05c9ef2d7 100644 --- a/src/decoder/modplug_plugin.c +++ b/src/decoder/modplug_plugin.c @@ -96,7 +96,6 @@ mod_decode(struct decoder *decoder, struct input_stream *is) struct audio_format audio_format; int ret; char audio_buffer[MODPLUG_FRAME_SIZE]; - unsigned frame_size, current_frame = 0; enum decoder_command cmd = DECODE_COMMAND_NONE; bdatas = mod_loadfile(decoder, is); @@ -128,24 +127,19 @@ mod_decode(struct decoder *decoder, struct input_stream *is) decoder_initialized(decoder, &audio_format, is->seekable, ModPlug_GetLength(f) / 1000.0); - frame_size = audio_format_frame_size(&audio_format); - do { ret = ModPlug_Read(f, audio_buffer, MODPLUG_FRAME_SIZE); if (ret <= 0) break; - current_frame += (unsigned)ret / frame_size; cmd = decoder_data(decoder, NULL, audio_buffer, ret, - (float)current_frame / (float)audio_format.sample_rate, 0, NULL); if (cmd == DECODE_COMMAND_SEEK) { float where = decoder_seek_where(decoder); ModPlug_Seek(f, (int)(where * 1000.0)); - current_frame = (unsigned)(where * audio_format.sample_rate); decoder_command_finished(decoder); } diff --git a/src/decoder/mp4ff_plugin.c b/src/decoder/mp4ff_plugin.c index 9e312d568..325a97291 100644 --- a/src/decoder/mp4ff_plugin.c +++ b/src/decoder/mp4ff_plugin.c @@ -262,7 +262,7 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream) dur -= offset; file_time += ((float)dur) / scale; - if (seeking && file_time > seek_where) + if (seeking && file_time >= seek_where) seek_position_found = true; if (seeking && seek_position_found) { @@ -328,7 +328,7 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream) cmd = decoder_data(mpd_decoder, input_stream, sample_buffer, sample_buffer_length, - file_time, bit_rate, NULL); + bit_rate, NULL); } g_free(seek_table); diff --git a/src/decoder/mpcdec_plugin.c b/src/decoder/mpcdec_plugin.c index bf27ec314..a186bc368 100644 --- a/src/decoder/mpcdec_plugin.c +++ b/src/decoder/mpcdec_plugin.c @@ -152,10 +152,8 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) mpc_uint32_t ret; int32_t chunk[G_N_ELEMENTS(sample_buffer)]; long bit_rate = 0; - unsigned long sample_pos = 0; mpc_uint32_t vbr_update_acc; mpc_uint32_t vbr_update_bits; - float total_time; struct replay_gain_info *replay_gain_info = NULL; enum decoder_command cmd = DECODE_COMMAND_NONE; @@ -219,16 +217,14 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) do { if (cmd == DECODE_COMMAND_SEEK) { - bool success; - - sample_pos = decoder_seek_where(mpd_decoder) * + mpc_int64_t where = decoder_seek_where(mpd_decoder) * audio_format.sample_rate; + bool success; #ifdef MPC_IS_OLD_API - success = mpc_decoder_seek_sample(&decoder, - sample_pos); + success = mpc_decoder_seek_sample(&decoder, where); #else - success = mpc_demux_seek_sample(demux, sample_pos) + success = mpc_demux_seek_sample(demux, where) == MPC_STATUS_OK; #endif if (success) @@ -259,19 +255,15 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) ret = frame.samples; #endif - sample_pos += ret; - ret *= info.channels; mpc_to_mpd_buffer(chunk, sample_buffer, ret); - total_time = ((float)sample_pos) / audio_format.sample_rate; bit_rate = vbr_update_bits * audio_format.sample_rate / 1152 / 1000; cmd = decoder_data(mpd_decoder, is, chunk, ret * sizeof(chunk[0]), - total_time, bit_rate, replay_gain_info); } while (cmd != DECODE_COMMAND_STOP); diff --git a/src/decoder/mpg123_decoder_plugin.c b/src/decoder/mpg123_decoder_plugin.c index 62e6b00b0..0d7cb9e0e 100644 --- a/src/decoder/mpg123_decoder_plugin.c +++ b/src/decoder/mpg123_decoder_plugin.c @@ -103,7 +103,7 @@ mpd_mpg123_file_decode(struct decoder *decoder, const char *path_fs) struct audio_format audio_format; mpg123_handle *handle; int error; - off_t num_samples, position; + off_t num_samples; enum decoder_command cmd; /* open the file */ @@ -134,8 +134,6 @@ mpd_mpg123_file_decode(struct decoder *decoder, const char *path_fs) unsigned char buffer[8192]; size_t nbytes; - position = mpg123_tell(handle); - /* decode */ error = mpg123_read(handle, buffer, sizeof(buffer), &nbytes); @@ -149,8 +147,6 @@ mpd_mpg123_file_decode(struct decoder *decoder, const char *path_fs) /* send to MPD */ cmd = decoder_data(decoder, NULL, buffer, nbytes, - (float)position / - (float)audio_format.sample_rate, 0, NULL); /* seeking not yet implemented */ diff --git a/src/decoder/sidplay_plugin.cxx b/src/decoder/sidplay_plugin.cxx index 63e46a285..9bfe98f3d 100644 --- a/src/decoder/sidplay_plugin.cxx +++ b/src/decoder/sidplay_plugin.cxx @@ -284,7 +284,6 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs) /* .. and play */ - unsigned data_time = 0; const unsigned timebase = player.timebase(); song_len *= timebase; @@ -297,12 +296,13 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs) if (nbytes == 0) break; + decoder_timestamp(decoder, (double)player.time() / timebase); + cmd = decoder_data(decoder, NULL, buffer, nbytes, - (float)data_time / (float)timebase, 0, NULL); - data_time = player.time(); if(cmd==DECODE_COMMAND_SEEK) { + unsigned data_time = player.time(); unsigned target_time = (unsigned) (decoder_seek_where(decoder) * timebase); @@ -323,7 +323,7 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs) decoder_command_finished(decoder); } - if (song_len > 0 && data_time >= song_len) + if (song_len > 0 && player.time() >= song_len) break; } while (cmd != DECODE_COMMAND_STOP); diff --git a/src/decoder/sndfile_decoder_plugin.c b/src/decoder/sndfile_decoder_plugin.c index a5fd4243b..fd51f4a33 100644 --- a/src/decoder/sndfile_decoder_plugin.c +++ b/src/decoder/sndfile_decoder_plugin.c @@ -119,7 +119,7 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is) SF_INFO info; struct audio_format audio_format; size_t frame_size; - sf_count_t read_frames, num_frames, position = 0; + sf_count_t read_frames, num_frames; int buffer[4096]; enum decoder_command cmd; @@ -155,7 +155,6 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is) cmd = decoder_data(decoder, is, buffer, num_frames * frame_size, - frame_to_time(position, &audio_format), 0, NULL); if (cmd == DECODE_COMMAND_SEEK) { sf_count_t c = diff --git a/src/decoder/vorbis_plugin.c b/src/decoder/vorbis_plugin.c index 91a9101f1..f0285de72 100755 --- a/src/decoder/vorbis_plugin.c +++ b/src/decoder/vorbis_plugin.c @@ -377,7 +377,6 @@ vorbis_stream_decode(struct decoder *decoder, cmd = decoder_data(decoder, input_stream, chunk, ret, - ov_pcm_tell(&vf) / audio_format.sample_rate, bitRate, replay_gain_info); } while (cmd != DECODE_COMMAND_STOP); diff --git a/src/decoder/wavpack_plugin.c b/src/decoder/wavpack_plugin.c index da2c8df77..8b80b1476 100644 --- a/src/decoder/wavpack_plugin.c +++ b/src/decoder/wavpack_plugin.c @@ -165,9 +165,8 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, format_samples_t format_samples; char chunk[CHUNK_SIZE]; int samples_requested, samples_got; - float total_time, current_time; + float total_time; int bytes_per_sample, output_sample_size; - int position; is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0; sample_format = @@ -199,8 +198,6 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, decoder_initialized(decoder, &audio_format, can_seek, total_time); - position = 0; - do { if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK) { if (can_seek) { @@ -209,7 +206,6 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, where = decoder_seek_where(decoder); where *= audio_format.sample_rate; if (WavpackSeekSample(wpc, where)) { - position = where; decoder_command_finished(decoder); } else { decoder_seek_error(decoder); @@ -229,9 +225,6 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, if (samples_got > 0) { int bitrate = (int)(WavpackGetInstantBitrate(wpc) / 1000 + 0.5); - position += samples_got; - current_time = position; - current_time /= audio_format.sample_rate; format_samples( bytes_per_sample, chunk, @@ -241,7 +234,7 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, decoder_data( decoder, NULL, chunk, samples_got * output_sample_size, - current_time, bitrate, + bitrate, replay_gain_info ); } diff --git a/src/decoder/wildmidi_plugin.c b/src/decoder/wildmidi_plugin.c index 70b4d5ef9..0392c06b9 100644 --- a/src/decoder/wildmidi_plugin.c +++ b/src/decoder/wildmidi_plugin.c @@ -92,8 +92,6 @@ wildmidi_file_decode(struct decoder *decoder, const char *path_fs) break; cmd = decoder_data(decoder, NULL, buffer, len, - (float)info->current_sample / - (float)WILDMIDI_SAMPLE_RATE, 0, NULL); if (cmd == DECODE_COMMAND_SEEK) { diff --git a/src/decoder_api.c b/src/decoder_api.c index ae2c6687b..dde27727b 100644 --- a/src/decoder_api.c +++ b/src/decoder_api.c @@ -95,7 +95,8 @@ enum decoder_command decoder_get_command(G_GNUC_UNUSED struct decoder * decoder) return dc->command; } -void decoder_command_finished(G_GNUC_UNUSED struct decoder * decoder) +void +decoder_command_finished(struct decoder *decoder) { struct decoder_control *dc = decoder->dc; @@ -115,6 +116,8 @@ void decoder_command_finished(G_GNUC_UNUSED struct decoder * decoder) } music_pipe_clear(dc->pipe, dc->buffer); + + decoder->timestamp = dc->seek_where; } dc->command = DECODE_COMMAND_NONE; @@ -192,6 +195,15 @@ size_t decoder_read(struct decoder *decoder, } } +void +decoder_timestamp(struct decoder *decoder, double t) +{ + assert(decoder != NULL); + assert(t >= 0); + + decoder->timestamp = t; +} + /** * Sends a #tag as-is to the music pipe. Flushes the current chunk * (decoder.chunk) if there is one. @@ -250,7 +262,7 @@ enum decoder_command decoder_data(struct decoder *decoder, struct input_stream *is, const void *_data, size_t length, - float data_time, uint16_t bitRate, + uint16_t kbit_rate, struct replay_gain_info *replay_gain_info) { struct decoder_control *dc = decoder->dc; @@ -316,7 +328,8 @@ decoder_data(struct decoder *decoder, } dest = music_chunk_write(chunk, &dc->out_audio_format, - data_time, bitRate, &nbytes); + decoder->timestamp, kbit_rate, + &nbytes); if (dest == NULL) { /* the chunk is full, flush it */ decoder_flush_chunk(decoder); @@ -350,6 +363,9 @@ decoder_data(struct decoder *decoder, data += nbytes; length -= nbytes; + + decoder->timestamp += (double)nbytes / + audio_format_time_to_size(&dc->in_audio_format); } return DECODE_COMMAND_NONE; diff --git a/src/decoder_api.h b/src/decoder_api.h index 81f75623a..9df6bed19 100644 --- a/src/decoder_api.h +++ b/src/decoder_api.h @@ -114,6 +114,15 @@ size_t decoder_read(struct decoder *decoder, struct input_stream *is, void *buffer, size_t length); +/** + * Sets the time stamp for the next data chunk [seconds]. The MPD + * core automatically counts it up, and a decoder plugin only needs to + * use this function if it thinks that adding to the time stamp based + * on the buffer size won't work. + */ +void +decoder_timestamp(struct decoder *decoder, double t); + /** * This function is called by the decoder plugin when it has * successfully decoded block of input data. @@ -129,7 +138,7 @@ decoder_read(struct decoder *decoder, struct input_stream *is, enum decoder_command decoder_data(struct decoder *decoder, struct input_stream *is, const void *data, size_t length, - float data_time, uint16_t bitRate, + uint16_t kbit_rate, struct replay_gain_info *replay_gain_info); /** diff --git a/src/decoder_internal.h b/src/decoder_internal.h index 9d422d253..df558f4dd 100644 --- a/src/decoder_internal.h +++ b/src/decoder_internal.h @@ -30,6 +30,11 @@ struct decoder { struct pcm_convert_state conv_state; + /** + * The time stamp of the next data chunk, in seconds. + */ + double timestamp; + bool seeking; /** diff --git a/src/decoder_thread.c b/src/decoder_thread.c index 9f297ad0d..9c6f3aab8 100644 --- a/src/decoder_thread.c +++ b/src/decoder_thread.c @@ -303,6 +303,7 @@ decoder_run_song(struct decoder_control *dc, }; int ret; + decoder.timestamp = 0.0; decoder.seeking = false; decoder.song_tag = song->tag != NULL && song_is_file(song) ? tag_dup(song->tag) : NULL; -- cgit v1.2.3