From b2e3c0757b2507db727d5b722b5043d3f98c7ee5 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 30 Jun 2010 20:32:29 +0200 Subject: 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. --- src/decoder/ffmpeg_decoder_plugin.c | 49 +++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'src/decoder/ffmpeg_decoder_plugin.c') diff --git a/src/decoder/ffmpeg_decoder_plugin.c b/src/decoder/ffmpeg_decoder_plugin.c index 68c376211..94b60ecb5 100644 --- a/src/decoder/ffmpeg_decoder_plugin.c +++ b/src/decoder/ffmpeg_decoder_plugin.c @@ -277,9 +277,49 @@ ffmpeg_sample_format(G_GNUC_UNUSED const AVCodecContext *codec_context) #endif } +static AVInputFormat * +ffmpeg_probe(struct decoder *decoder, struct input_stream *is) +{ + 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, NULL)) { + 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 = is->uri, + }; + + AVInputFormat *format = av_probe_input_format(&avpd, true); + g_free(buffer); + + return format; +} + static void ffmpeg_decode(struct decoder *decoder, struct input_stream *input) { + AVInputFormat *input_format = ffmpeg_probe(decoder, input); + if (input_format == NULL) + return; + + g_debug("detected input format '%s' (%s)", + input_format->name, input_format->long_name); + struct ffmpeg_stream stream = { .url = "mpd://X", /* only the mpd:// prefix matters */ .decoder = decoder, @@ -294,7 +334,8 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) append_uri_suffix(&stream, input->uri); //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; } @@ -425,6 +466,10 @@ ffmpeg_copy_metadata(struct tag *tag, AVMetadata *m, static struct tag * ffmpeg_stream_tag(struct input_stream *is) { + AVInputFormat *input_format = ffmpeg_probe(NULL, is); + if (input_format == NULL) + return NULL; + struct ffmpeg_stream stream = { .url = "mpd://X", /* only the mpd:// prefix matters */ .decoder = NULL, @@ -435,7 +480,7 @@ ffmpeg_stream_tag(struct input_stream *is) append_uri_suffix(&stream, is->uri); AVFormatContext *f; - if (av_open_input_file(&f, stream.url, NULL, 0, NULL) != 0) + if (av_open_input_file(&f, stream.url, input_format, 0, NULL) != 0) return NULL; if (av_find_stream_info(f) < 0) { -- cgit v1.2.3