aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2010-06-30 20:32:29 +0200
committerMax Kellermann <max@duempel.org>2010-06-30 23:40:31 +0200
commit375a09d6f6d09fc132976e1f82647cc56fb33640 (patch)
tree717eff2e8d5c80665589b52f6efb657cd7697a4c
parent0265c34bed4bdfd45a4ef1b5ff73071c5d5a5e10 (diff)
downloadmpd-375a09d6f6d09fc132976e1f82647cc56fb33640.tar.gz
mpd-375a09d6f6d09fc132976e1f82647cc56fb33640.tar.xz
mpd-375a09d6f6d09fc132976e1f82647cc56fb33640.zip
decoder/ffmpeg: manual format probing
Use the libavformat function av_probe_input_format() to probe the AVInputFormat, instead of letting av_open_input_file() do it implicitly. We will switch to av_open_input_stream() very soon, which does not have the probing code. Loosely based on a patch from Jasper St. Pierre.
-rw-r--r--src/decoder/ffmpeg_plugin.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/src/decoder/ffmpeg_plugin.c b/src/decoder/ffmpeg_plugin.c
index fc402ca04..f7218e238 100644
--- a/src/decoder/ffmpeg_plugin.c
+++ b/src/decoder/ffmpeg_plugin.c
@@ -160,11 +160,53 @@ append_uri_suffix(struct ffmpeg_stream *stream, const char *uri)
g_free(base);
}
+static AVInputFormat *
+ffmpeg_probe(struct decoder *decoder, struct input_stream *is,
+ const char *uri)
+{
+ enum {
+ BUFFER_SIZE = 16384,
+ PADDING = 16,
+ };
+
+ unsigned char *buffer = g_malloc(BUFFER_SIZE);
+ size_t nbytes = decoder_read(decoder, is, buffer, BUFFER_SIZE);
+ if (nbytes <= PADDING || !input_stream_seek(is, 0, SEEK_SET)) {
+ g_free(buffer);
+ return NULL;
+ }
+
+ /* some ffmpeg parsers (e.g. ac3_parser.c) read a few bytes
+ beyond the declared buffer limit, which makes valgrind
+ angry; this workaround removes some padding from the buffer
+ size */
+ nbytes -= PADDING;
+
+ AVProbeData avpd = {
+ .buf = buffer,
+ .buf_size = nbytes,
+ .filename = uri,
+ };
+
+ AVInputFormat *format = av_probe_input_format(&avpd, true);
+ g_free(buffer);
+
+ return format;
+}
+
static bool
-ffmpeg_helper(const char *uri, struct input_stream *input,
+ffmpeg_helper(const char *uri,
+ struct decoder *decoder, struct input_stream *input,
bool (*callback)(struct ffmpeg_context *ctx),
struct ffmpeg_context *ctx)
{
+ AVInputFormat *input_format = ffmpeg_probe(decoder, input, uri);
+ if (input_format == NULL)
+ return false;
+
+ g_debug("detected input format '%s' (%s)",
+ input_format->name, input_format->long_name);
+
AVFormatContext *format_context;
AVCodecContext *codec_context;
AVCodec *codec;
@@ -185,7 +227,8 @@ ffmpeg_helper(const char *uri, struct input_stream *input,
}
//ffmpeg works with ours "fileops" helper
- if (av_open_input_file(&format_context, stream.url, NULL, 0, NULL) != 0) {
+ if (av_open_input_file(&format_context, stream.url, input_format,
+ 0, NULL) != 0) {
g_warning("Open failed\n");
return false;
}
@@ -377,7 +420,7 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
ctx.decoder = decoder;
char *uri = decoder_get_uri(decoder);
- ffmpeg_helper(uri, input,
+ ffmpeg_helper(uri, decoder, input,
ffmpeg_decode_internal, &ctx);
g_free(uri);
}
@@ -465,7 +508,7 @@ static struct tag *ffmpeg_tag(const char *file)
ctx.decoder = NULL;
ctx.tag = tag_new();
- ret = ffmpeg_helper(file, &input, ffmpeg_tag_internal, &ctx);
+ ret = ffmpeg_helper(file, NULL, &input, ffmpeg_tag_internal, &ctx);
if (!ret) {
tag_free(ctx.tag);
ctx.tag = NULL;