diff options
author | Max Kellermann <max@duempel.org> | 2010-06-30 20:32:29 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2010-06-30 23:40:31 +0200 |
commit | 375a09d6f6d09fc132976e1f82647cc56fb33640 (patch) | |
tree | 717eff2e8d5c80665589b52f6efb657cd7697a4c | |
parent | 0265c34bed4bdfd45a4ef1b5ff73071c5d5a5e10 (diff) | |
download | mpd-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.c | 51 |
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; |