aboutsummaryrefslogtreecommitdiffstats
path: root/src/decoder/mp4ff_decoder_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/decoder/mp4ff_decoder_plugin.c (renamed from src/decoder/mp4ff_plugin.c)120
1 files changed, 54 insertions, 66 deletions
diff --git a/src/decoder/mp4ff_plugin.c b/src/decoder/mp4ff_decoder_plugin.c
index d5afe084b..d72fa02ac 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
@@ -357,53 +366,33 @@ mp4ff_tag_name_parse(const char *name)
}
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);
- return NULL;
- }
-
- mp4fh = mp4ff_open_read(&callback);
- if (!mp4fh) {
- input_stream_close(&input_stream);
+ mp4ff_t *mp4fh = mp4ff_input_stream_open(&mis, NULL, is);
+ if (mp4fh == NULL)
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 +402,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,
};