aboutsummaryrefslogtreecommitdiff
path: root/src/decoder_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/decoder_api.c')
-rw-r--r--src/decoder_api.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/src/decoder_api.c b/src/decoder_api.c
index b8edb8aa..bcab6010 100644
--- a/src/decoder_api.c
+++ b/src/decoder_api.c
@@ -30,6 +30,10 @@
#include <glib.h>
+#include <libavutil/channel_layout.h>
+#include <libavutil/frame.h>
+#include <libavutil/samplefmt.h>
+
#include <assert.h>
#include <stdlib.h>
@@ -347,25 +351,24 @@ static bool update_stream_tag(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,
+ AVFrame *frame,
uint16_t kbit_rate)
{
struct decoder_control *dc = decoder->dc;
- const char *data = _data;
- GError *error = NULL;
- enum decoder_command cmd;
+ enum decoder_command cmd = DECODE_COMMAND_NONE;
+ uint8_t *data;
+ int length;
assert(dc->state == DECODE_STATE_DECODE);
assert(dc->pipe != NULL);
- assert(length % audio_format_frame_size(&dc->in_audio_format) == 0);
decoder_lock(dc);
cmd = decoder_get_virtual_command(decoder);
decoder_unlock(dc);
if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
- length == 0)
- return cmd;
+ !frame->nb_samples)
+ goto finish;
/* send stream tags */
@@ -383,23 +386,27 @@ enum decoder_command decoder_data(struct decoder *decoder,
cmd = do_send_tag(decoder, decoder->stream_tag);
if (cmd != DECODE_COMMAND_NONE)
- return cmd;
+ goto finish;
}
if (!audio_format_equals(&dc->in_audio_format, &dc->out_audio_format)) {
- data = pcm_convert(&decoder->conv_state,
- &dc->in_audio_format, data, length,
- &dc->out_audio_format, &length,
- &error);
- if (data == NULL) {
+ AVFrame *tmp = pcm_convert(&decoder->conv_state,
+ &dc->in_audio_format, &dc->out_audio_format, frame);
+ if (!tmp) {
/* the PCM conversion has failed - stop
playback, since we have no better way to
bail out */
- g_warning("%s", error->message);
- return DECODE_COMMAND_STOP;
+ g_warning("Error converting to output format.\n");
+ cmd = DECODE_COMMAND_STOP;
+ goto finish;
}
+ av_frame_free(&frame);
+ frame = tmp;
}
+ length = frame->nb_samples * av_get_bytes_per_sample(frame->format) *
+ dc->out_audio_format.channels;
+ data = frame->data[0];
while (length > 0) {
struct music_chunk *chunk;
char *dest;
@@ -409,7 +416,8 @@ enum decoder_command decoder_data(struct decoder *decoder,
chunk = decoder_get_chunk(decoder);
if (chunk == NULL) {
assert(dc->command != DECODE_COMMAND_NONE);
- return dc->command;
+ cmd = dc->command;
+ goto finish;
}
dest = music_chunk_write(chunk, &dc->out_audio_format,
@@ -448,12 +456,16 @@ enum decoder_command decoder_data(struct decoder *decoder,
audio_format_time_to_size(&dc->out_audio_format);
if (dc->end_ms > 0 &&
- decoder->timestamp >= dc->end_ms / 1000.0)
+ decoder->timestamp >= dc->end_ms / 1000.0) {
/* the end of this range has been reached:
stop decoding */
- return DECODE_COMMAND_STOP;
+ cmd = DECODE_COMMAND_STOP;
+ break;
+ }
}
+finish:
+ av_frame_free(&frame);
return DECODE_COMMAND_NONE;
}