diff options
Diffstat (limited to '')
-rw-r--r-- | src/decoder/mp4ff_decoder_plugin.c (renamed from src/decoder/mp4ff_plugin.c) | 124 |
1 files changed, 58 insertions, 66 deletions
diff --git a/src/decoder/mp4ff_plugin.c b/src/decoder/mp4ff_decoder_plugin.c index d5afe084b..ce4848409 100644 --- a/src/decoder/mp4ff_plugin.c +++ b/src/decoder/mp4ff_decoder_plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2009 The Music Player Daemon Project + * Copyright (C) 2003-2010 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "../decoder_api.h" #include "config.h" +#include "decoder_api.h" +#include "audio_check.h" #include "tag_table.h" #include <glib.h> @@ -35,7 +36,9 @@ /* all code here is either based on or copied from FAAD2's frontend code */ -struct mp4_context { +struct mp4ff_input_stream { + mp4ff_callback_t callback; + struct decoder *decoder; struct input_stream *input_stream; }; @@ -89,20 +92,38 @@ mp4_get_aac_track(mp4ff_t * infile, faacDecHandle decoder, static uint32_t mp4_read(void *user_data, void *buffer, uint32_t length) { - struct mp4_context *ctx = user_data; + struct mp4ff_input_stream *mis = user_data; - return decoder_read(ctx->decoder, ctx->input_stream, buffer, length); + return decoder_read(mis->decoder, mis->input_stream, buffer, length); } static uint32_t mp4_seek(void *user_data, uint64_t position) { - struct mp4_context *ctx = user_data; + struct mp4ff_input_stream *mis = user_data; - return input_stream_seek(ctx->input_stream, position, SEEK_SET) + return input_stream_seek(mis->input_stream, position, SEEK_SET, NULL) ? 0 : -1; } +static const mp4ff_callback_t mpd_mp4ff_callback = { + .read = mp4_read, + .seek = mp4_seek, +}; + +static mp4ff_t * +mp4ff_input_stream_open(struct mp4ff_input_stream *mis, + struct decoder *decoder, + struct input_stream *input_stream) +{ + mis->callback = mpd_mp4ff_callback; + mis->callback.user_data = mis; + mis->decoder = decoder; + mis->input_stream = input_stream; + + return mp4ff_open_read(&mis->callback); +} + static faacDecHandle mp4_faad_new(mp4ff_t *mp4fh, int *track_r, struct audio_format *audio_format) { @@ -111,6 +132,7 @@ mp4_faad_new(mp4ff_t *mp4fh, int *track_r, struct audio_format *audio_format) int track; uint32_t sample_rate; unsigned char channels; + GError *error = NULL; decoder = faacDecOpen(); @@ -131,37 +153,24 @@ mp4_faad_new(mp4ff_t *mp4fh, int *track_r, struct audio_format *audio_format) return NULL; } - *track_r = track; - *audio_format = (struct audio_format){ - .bits = 16, - .channels = channels, - .sample_rate = sample_rate, - }; - - if (!audio_format_valid(audio_format)) { - g_warning("Invalid audio format: %u:%u:%u\n", - audio_format->sample_rate, - audio_format->bits, - audio_format->channels); + if (!audio_format_init_checked(audio_format, sample_rate, + SAMPLE_FORMAT_S16, channels, + &error)) { + g_warning("%s", error->message); + g_error_free(error); faacDecClose(decoder); return NULL; } + *track_r = track; + return decoder; } static void mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream) { - struct mp4_context ctx = { - .decoder = mpd_decoder, - .input_stream = input_stream, - }; - mp4ff_callback_t callback = { - .read = mp4_read, - .seek = mp4_seek, - .user_data = &ctx, - }; + struct mp4ff_input_stream mis; mp4ff_t *mp4fh; int32_t track; float file_time, total_time; @@ -187,7 +196,7 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream) double seek_where = 0; enum decoder_command cmd = DECODE_COMMAND_NONE; - mp4fh = mp4ff_open_read(&callback); + mp4fh = mp4ff_input_stream_open(&mis, mpd_decoder, input_stream); if (!mp4fh) { g_warning("Input does not appear to be a mp4 stream.\n"); return; @@ -266,7 +275,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) { @@ -332,7 +341,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); } g_free(seek_table); @@ -341,9 +350,9 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream) } static const char *const mp4ff_tag_names[TAG_NUM_OF_ITEM_TYPES] = { - [TAG_ITEM_ALBUM_ARTIST] = "album artist", - [TAG_ITEM_COMPOSER] = "writer", - [TAG_ITEM_PERFORMER] = "band", + [TAG_ALBUM_ARTIST] = "album artist", + [TAG_COMPOSER] = "writer", + [TAG_PERFORMER] = "band", }; static enum tag_type @@ -353,57 +362,41 @@ mp4ff_tag_name_parse(const char *name) if (type == TAG_NUM_OF_ITEM_TYPES) type = tag_name_parse_i(name); + if (g_ascii_strcasecmp(name, "albumartist") == 0 || + g_ascii_strcasecmp(name, "album_artist") == 0) + return TAG_ALBUM_ARTIST; + return type; } static struct tag * -mp4_tag_dup(const char *file) +mp4_stream_tag(struct input_stream *is) { - struct tag *ret = NULL; - struct input_stream input_stream; - struct mp4_context ctx = { - .decoder = NULL, - .input_stream = &input_stream, - }; - mp4ff_callback_t callback = { - .read = mp4_read, - .seek = mp4_seek, - .user_data = &ctx, - }; - mp4ff_t *mp4fh; + struct mp4ff_input_stream mis; int32_t track; int32_t file_time; int32_t scale; int i; - if (!input_stream_open(&input_stream, file)) { - g_warning("Failed to open file: %s", file); + mp4ff_t *mp4fh = mp4ff_input_stream_open(&mis, NULL, is); + if (mp4fh == NULL) return NULL; - } - - mp4fh = mp4ff_open_read(&callback); - if (!mp4fh) { - input_stream_close(&input_stream); - return NULL; - } track = mp4_get_aac_track(mp4fh, NULL, NULL, NULL); if (track < 0) { mp4ff_close(mp4fh); - input_stream_close(&input_stream); return NULL; } - ret = tag_new(); file_time = mp4ff_get_track_duration_use_offsets(mp4fh, track); scale = mp4ff_time_scale(mp4fh, track); if (scale < 0) { mp4ff_close(mp4fh); - input_stream_close(&input_stream); - tag_free(ret); return NULL; } - ret->time = ((float)file_time) / scale + 0.5; + + struct tag *tag = tag_new(); + tag->time = ((float)file_time) / scale + 0.5; for (i = 0; i < mp4ff_meta_get_num_items(mp4fh); i++) { char *item; @@ -413,25 +406,24 @@ mp4_tag_dup(const char *file) enum tag_type type = mp4ff_tag_name_parse(item); if (type != TAG_NUM_OF_ITEM_TYPES) - tag_add_item(ret, type, value); + tag_add_item(tag, type, value); free(item); free(value); } mp4ff_close(mp4fh); - input_stream_close(&input_stream); - return ret; + return tag; } static const char *const mp4_suffixes[] = { "m4a", "mp4", NULL }; static const char *const mp4_mime_types[] = { "audio/mp4", "audio/m4a", NULL }; const struct decoder_plugin mp4ff_decoder_plugin = { - .name = "mp4", + .name = "mp4ff", .stream_decode = mp4_decode, - .tag_dup = mp4_tag_dup, + .stream_tag = mp4_stream_tag, .suffixes = mp4_suffixes, .mime_types = mp4_mime_types, }; |