[FFmpeg-devel] [PATCH] doc/examples: add avio_writing examples
Stefano Sabatini
stefasab at gmail.com
Wed Nov 5 18:35:18 CET 2014
Show how to use the AVIO writing API.
---
.gitignore | 1 +
configure | 1 +
doc/examples/Makefile | 1 +
doc/examples/avio_writing.c | 225 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 228 insertions(+)
create mode 100644 doc/examples/avio_writing.c
diff --git a/.gitignore b/.gitignore
index 793d33a..628ffb1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,7 @@
/doc/avoptions_format.texi
/doc/doxy/html/
/doc/examples/avio_reading
+/doc/examples/avio_writing
/doc/examples/decoding_encoding
/doc/examples/demuxing_decoding
/doc/examples/extract_mvs
diff --git a/configure b/configure
index 570878d..5b3a246 100755
--- a/configure
+++ b/configure
@@ -1310,6 +1310,7 @@ COMPONENT_LIST="
EXAMPLE_LIST="
avio_reading_example
+ avio_writing_example
decoding_encoding_example
demuxing_decoding_example
extract_mvs_example
diff --git a/doc/examples/Makefile b/doc/examples/Makefile
index 07251fe..ad10b5b 100644
--- a/doc/examples/Makefile
+++ b/doc/examples/Makefile
@@ -12,6 +12,7 @@ CFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS)
LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS)
EXAMPLES= avio_reading \
+ avio_writing \
decoding_encoding \
demuxing_decoding \
extract_mvs \
diff --git a/doc/examples/avio_writing.c b/doc/examples/avio_writing.c
new file mode 100644
index 0000000..27ef21a
--- /dev/null
+++ b/doc/examples/avio_writing.c
@@ -0,0 +1,225 @@
+/*
+ * 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 write callback.
+ * @example avio_writing.c
+ */
+
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+#include <libavformat/avio.h>
+#include <libavutil/file.h>
+#include <libavutil/timestamp.h>
+
+struct buffer_data {
+ uint8_t *buf;
+ size_t size;
+ uint8_t *ptr;
+ size_t room; ///< size left in the buffer
+};
+
+static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt, const char *tag)
+{
+ AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base;
+
+ printf("%s: pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
+ tag,
+ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base),
+ av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base),
+ av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base),
+ pkt->stream_index);
+}
+
+static int write_packet(void *opaque, uint8_t *buf, int buf_size)
+{
+ struct buffer_data *bd = (struct buffer_data *)opaque;
+ while (buf_size > bd->room) {
+ int64_t offset = bd->ptr - bd->buf;
+ bd->buf = av_realloc_f(bd->buf, 2, bd->size);
+ if (!bd->buf)
+ return AVERROR(ENOMEM);
+ bd->size *= 2;
+ bd->ptr = bd->buf + offset;
+ bd->room = bd->size - offset;
+ }
+ printf("write packet pkt_size:%d used_buf_size:%zu buf_size:%zu buf_room:%zu\n", buf_size, bd->ptr-bd->buf, bd->size, bd->room);
+
+ /* copy buffer data to buffer_data buffer */
+ memcpy(bd->ptr, buf, buf_size);
+ bd->ptr += buf_size;
+ bd->room -= buf_size;
+
+ return buf_size;
+}
+
+int main(int argc, char *argv[])
+{
+ AVFormatContext *ifmt_ctx = NULL;
+ AVFormatContext *ofmt_ctx = NULL;
+ AVIOContext *avio_ctx = NULL;
+ uint8_t *avio_ctx_buffer = NULL;
+ size_t avio_ctx_buffer_size = 4096;
+ char *in_filename = NULL;
+ char *out_filename = NULL;
+ int i, ret = 0;
+ struct buffer_data bd = { 0 };
+ const size_t bd_buf_size = 1024;
+ AVPacket pkt;
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s input_file output_file\n"
+ "API example program to show how to write to a custom buffer "
+ "accessed through AVIOContext.\n"
+ "Remux the content of input_file to output_file, writing to a custom buffer.\n"
+ "The output file must support the same codec as the input file.\n", argv[0]);
+ return 1;
+ }
+ in_filename = argv[1];
+ out_filename = argv[2];
+
+ av_register_all();
+
+ if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
+ fprintf(stderr, "Could not open input file '%s'", in_filename);
+ goto end;
+ }
+
+ if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
+ fprintf(stderr, "Failed to retrieve input stream information");
+ goto end;
+ }
+
+ av_dump_format(ifmt_ctx, 0, in_filename, 0);
+
+ /* fill opaque structure used by the AVIOContext write callback */
+ bd.ptr = bd.buf = av_malloc(bd_buf_size);
+ if (!bd.buf) {
+ ret = AVERROR(ENOMEM);
+ goto end;
+ }
+ bd.size = bd.room = bd_buf_size;
+
+ 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,
+ 1, &bd, NULL, &write_packet, NULL);
+ if (!avio_ctx) {
+ ret = AVERROR(ENOMEM);
+ goto end;
+ }
+
+ ret = avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", NULL);
+ if (ret < 0) {
+ fprintf(stderr, "Could not create output context\n");
+ goto end;
+ }
+ ofmt_ctx->pb = avio_ctx;
+
+ for (i = 0; i < ifmt_ctx->nb_streams; i++) {
+ AVStream *in_stream = ifmt_ctx->streams[i];
+ AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
+ if (!out_stream) {
+ fprintf(stderr, "Failed creating output stream\n");
+ ret = AVERROR_UNKNOWN;
+ goto end;
+ }
+
+ ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to copy context from input to output stream codec context\n");
+ goto end;
+ }
+ out_stream->codec->codec_tag = 0;
+ if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
+ out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ }
+ av_dump_format(ofmt_ctx, 0, out_filename, 1);
+
+ ret = avformat_write_header(ofmt_ctx, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "Error occurred when opening output file\n");
+ goto end;
+ }
+
+ while (1) {
+ AVStream *in_stream, *out_stream;
+
+ ret = av_read_frame(ifmt_ctx, &pkt);
+ if (ret < 0)
+ break;
+
+ in_stream = ifmt_ctx->streams[pkt.stream_index];
+ out_stream = ofmt_ctx->streams[pkt.stream_index];
+ log_packet(ifmt_ctx, &pkt, "in");
+
+ /* copy packet */
+ av_packet_rescale_ts(&pkt, in_stream->time_base, out_stream->time_base);
+ pkt.pos = -1;
+ log_packet(ofmt_ctx, &pkt, "out");
+
+ ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
+ if (ret < 0) {
+ fprintf(stderr, "Error muxing packet\n");
+ break;
+ }
+ av_free_packet(&pkt);
+ }
+
+ av_write_trailer(ofmt_ctx);
+end:
+
+ avformat_close_input(&ifmt_ctx);
+
+ /* close output */
+ avformat_free_context(ofmt_ctx);
+ av_freep(&avio_ctx->buffer);
+ av_free(avio_ctx);
+
+ /* write buffer to file */
+ {
+ FILE *out_file = fopen(out_filename, "w");
+ if (!out_file) {
+ fprintf(stderr, "Could not open file '%s'\n", out_filename);
+ ret = AVERROR(errno);
+ } else {
+ fwrite(bd.buf, bd.size, 1, out_file);
+ fclose(out_file);
+ }
+ }
+
+ av_free(bd.buf);
+
+ if (ret < 0 && ret != AVERROR_EOF) {
+ fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
+ return 1;
+ }
+
+ return 0;
+}
--
1.8.3.2
More information about the ffmpeg-devel
mailing list