diff options
author | Max Kellermann <max@duempel.org> | 2010-06-30 20:32:29 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2010-07-19 22:59:59 +0200 |
commit | b2e3c0757b2507db727d5b722b5043d3f98c7ee5 (patch) | |
tree | 6c6b2b52587b227ed91c26ec82f7b372889f585b /src/decoder | |
parent | 0fc0196dba684e1aac2752a64babffad62f84356 (diff) | |
download | mpd-b2e3c0757b2507db727d5b722b5043d3f98c7ee5.tar.gz mpd-b2e3c0757b2507db727d5b722b5043d3f98c7ee5.tar.xz mpd-b2e3c0757b2507db727d5b722b5043d3f98c7ee5.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.
Diffstat (limited to 'src/decoder')
-rw-r--r-- | src/decoder/ffmpeg_decoder_plugin.c | 49 |
1 files changed, 47 insertions, 2 deletions
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) { |