diff --git a/.gitignore b/.gitignore index 8a7427647b..d03a6b9ffd 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ /doc/config.texi /doc/avoptions_codec.texi /doc/avoptions_format.texi +/doc/examples/avio_reading /doc/examples/decoding_encoding /doc/examples/demuxing_decoding /doc/examples/filtering_audio diff --git a/configure b/configure index 8b88daf414..285a7a9eeb 100755 --- a/configure +++ b/configure @@ -1241,6 +1241,7 @@ COMPONENT_LIST=" " EXAMPLE_LIST=" + avio_reading_example decoding_encoding_example demuxing_decoding_example filtering_audio_example @@ -2390,6 +2391,7 @@ tinterlace_pad_test_deps="tinterlace_filter" zmq_filter_deps="libzmq" # examples +avio_reading="avformat avcodec avutil" decoding_encoding_example_deps="avcodec avutil" demuxing_decoding_example_deps="avcodec avformat avutil" filtering_audio_example_deps="avfilter avcodec avformat avutil" diff --git a/doc/Makefile b/doc/Makefile index 4092f52d1f..8077ea6e36 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -36,6 +36,7 @@ DOCS-$(CONFIG_MANPAGES) += $(MANPAGES) DOCS-$(CONFIG_TXTPAGES) += $(TXTPAGES) DOCS = $(DOCS-yes) +DOC_EXAMPLES-$(CONFIG_AVIO_READING_EXAMPLE) += avio_reading DOC_EXAMPLES-$(CONFIG_DECODING_ENCODING_EXAMPLE) += decoding_encoding DOC_EXAMPLES-$(CONFIG_DEMUXING_DECODING_EXAMPLE) += demuxing_decoding DOC_EXAMPLES-$(CONFIG_FILTERING_AUDIO_EXAMPLE) += filtering_audio diff --git a/doc/examples/Makefile b/doc/examples/Makefile index a25455e08c..f4f6c70d8c 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -11,7 +11,8 @@ CFLAGS += -Wall -g CFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS) LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS) -EXAMPLES= decoding_encoding \ +EXAMPLES= avio_reading \ + decoding_encoding \ demuxing_decoding \ filtering_video \ filtering_audio \ diff --git a/doc/examples/avio_reading.c b/doc/examples/avio_reading.c new file mode 100644 index 0000000000..a908954542 --- /dev/null +++ b/doc/examples/avio_reading.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2014 Stefano Sabatini + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @file + * libavformat AVIOContext API example. + * + * Make libavformat demuxer access media content through a custom + * AVIOContext read callback. + * @example doc/examples/avio_reading.c + */ + + +#include +#include +#include +#include + +struct buffer_data { + uint8_t *ptr; + size_t size; ///< size left in the buffer +}; + +static int read_packet(void *opaque, uint8_t *buf, int buf_size) +{ + struct buffer_data *bd = (struct buffer_data *)opaque; + buf_size = FFMIN(buf_size, bd->size); + + printf("ptr:%p size:%zu\n", bd->ptr, bd->size); + + /* copy internal buffer data to buf */ + memcpy(buf, bd->ptr, buf_size); + bd->ptr += buf_size; + bd->size -= buf_size; + + return buf_size; +} + +int main(int argc, char *argv[]) +{ + AVFormatContext *fmt_ctx = NULL; + AVIOContext *avio_ctx = NULL; + uint8_t *buffer = NULL, *avio_ctx_buffer = NULL; + size_t buffer_size, avio_ctx_buffer_size = 4096; + char *input_filename = NULL; + int ret = 0; + struct buffer_data bd = { 0 }; + + if (argc != 2) { + fprintf(stderr, "usage: %s input_file\n" + "API example program to show how to read from a custom buffer " + "accessed through AVIOContext.\n", argv[0]); + return 1; + } + input_filename = argv[1]; + + /* register codecs and formats and other lavf/lavc components*/ + av_register_all(); + + /* slurp file content into buffer */ + ret = av_file_map(input_filename, &buffer, &buffer_size, 0, NULL); + if (ret < 0) + goto end; + + /* fill opaque structure used by the AVIOContext read callback */ + bd.ptr = buffer; + bd.size = buffer_size; + + if (!(fmt_ctx = avformat_alloc_context())) { + ret = AVERROR(ENOMEM); + goto end; + } + + avio_ctx_buffer = av_malloc(avio_ctx_buffer_size); + if (!avio_ctx_buffer) { + ret = AVERROR(ENOMEM); + goto end; + } + avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, + 0, &bd, &read_packet, NULL, NULL); + if (!avio_ctx) { + ret = AVERROR(ENOMEM); + goto end; + } + fmt_ctx->pb = avio_ctx; + + ret = avformat_open_input(&fmt_ctx, NULL, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Could not open input\n"); + goto end; + } + + ret = avformat_find_stream_info(fmt_ctx, NULL); + if (ret < 0) { + fprintf(stderr, "Could not find stream information\n"); + goto end; + } + + av_dump_format(fmt_ctx, 0, input_filename, 0); + +end: + avformat_close_input(&fmt_ctx); + /* note: the internal buffer could have changed, and be != avio_ctx_buffer */ + av_freep(&avio_ctx->buffer); + av_freep(&avio_ctx); + av_file_unmap(buffer, buffer_size); + + if (ret < 0) { + fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); + return 1; + } + + return 0; +}