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.
This commit is contained in:
Max Kellermann 2009-12-25 19:47:33 +01:00
parent 870436a592
commit bad350bc18
22 changed files with 73 additions and 83 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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)

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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) {
mpc_int64_t where = decoder_seek_where(mpd_decoder) *
audio_format.sample_rate;
bool success;
sample_pos = decoder_seek_where(mpd_decoder) *
audio_format.sample_rate;
#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);

View File

@ -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 */

View File

@ -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);

View File

@ -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 =

View File

@ -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);

View File

@ -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
);
}

View File

@ -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) {

View File

@ -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;

View File

@ -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);
/**

View File

@ -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;
/**

View File

@ -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;

View File

@ -96,11 +96,17 @@ decoder_read(G_GNUC_UNUSED struct decoder *decoder,
return input_stream_read(is, buffer, length, NULL);
}
void
decoder_timestamp(G_GNUC_UNUSED struct decoder *decoder,
G_GNUC_UNUSED double t)
{
}
enum decoder_command
decoder_data(G_GNUC_UNUSED struct decoder *decoder,
G_GNUC_UNUSED struct input_stream *is,
const void *data, size_t datalen,
G_GNUC_UNUSED float data_time, G_GNUC_UNUSED uint16_t bit_rate,
G_GNUC_UNUSED uint16_t bit_rate,
G_GNUC_UNUSED struct replay_gain_info *replay_gain_info)
{
write(1, data, datalen);

View File

@ -117,11 +117,17 @@ decoder_read(G_GNUC_UNUSED struct decoder *decoder,
return input_stream_read(is, buffer, length, NULL);
}
void
decoder_timestamp(G_GNUC_UNUSED struct decoder *decoder,
G_GNUC_UNUSED double t)
{
}
enum decoder_command
decoder_data(G_GNUC_UNUSED struct decoder *decoder,
G_GNUC_UNUSED struct input_stream *is,
const void *data, size_t datalen,
G_GNUC_UNUSED float data_time, G_GNUC_UNUSED uint16_t bit_rate,
G_GNUC_UNUSED uint16_t kbit_rate,
G_GNUC_UNUSED struct replay_gain_info *replay_gain_info)
{
write(1, data, datalen);