[FFmpeg-devel] [PATCH] examples: add remuxing example
Nicolas George
george at nsup.org
Sun Jan 19 13:57:08 CET 2014
Le decadi 30 nivôse, an CCXXII, Stefano Sabatini a écrit :
> Show how to perform streamcopy from one container to another.
> ---
> doc/examples/Makefile | 1 +
> doc/examples/remuxing.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 165 insertions(+)
> create mode 100644 doc/examples/remuxing.c
>
> diff --git a/doc/examples/Makefile b/doc/examples/Makefile
> index f085532..a25455e 100644
> --- a/doc/examples/Makefile
> +++ b/doc/examples/Makefile
> @@ -17,6 +17,7 @@ EXAMPLES= decoding_encoding \
> filtering_audio \
> metadata \
> muxing \
> + remuxing \
> resampling_audio \
> scaling_video \
> transcode_aac \
> diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c
> new file mode 100644
> index 0000000..5bf1640
> --- /dev/null
> +++ b/doc/examples/remuxing.c
> @@ -0,0 +1,164 @@
> +/*
> + * Copyright (c) 2013 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/libavcodec remuxing API example.
> + *
> + * Remux streams from one container format to another.
> + * @example doc/examples/remuxing.c
> + */
> +
> +#include <libavutil/timestamp.h>
> +#include <libavformat/avformat.h>
> +
> +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;
const AVRational *time_base = &...
to avoid an extra copy.
> +
> + 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);
> +}
> +
> +int main(int argc, char **argv)
> +{
> + AVOutputFormat *ofmt = NULL;
> + AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
> + AVPacket pkt;
> + const char *in_filename, *out_filename;
> + int ret, i;
> +
> + if (argc < 3) {
> + printf("usage: %s input output\n"
> + "API example program to remux a media file with libavformat and libavcodec.\n"
> + "The output format is guessed according to the file extension.\n"
> + "\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);
> +
> + avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
> + if (!ofmt_ctx) {
> + fprintf(stderr, "Could not create output context\n");
> + ret = AVERROR_UNKNOWN;
> + goto end;
> + }
> +
> + ofmt = ofmt_ctx->oformat;
> +
> + 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 allocating 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;
> + }
> + if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
> + out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
> + }
> + av_dump_format(ofmt_ctx, 0, out_filename, 1);
> +
> + if (!(ofmt->flags & AVFMT_NOFILE)) {
> + ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
> + if (ret < 0) {
> + fprintf(stderr, "Could not open output file '%s'", out_filename);
> + goto end;
> + }
> + }
> +
> + 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 */
> + pkt.pts = av_rescale_q(pkt.pts, in_stream->time_base, out_stream->time_base);
> + pkt.dts = av_rescale_q(pkt.dts, in_stream->time_base, out_stream->time_base);
Maybe use AV_ROUND_PASS_MINMAX to handle the cases where pkt.pts or pkt.dts
is unset.
> + pkt.duration = av_rescale_q(pkt.duration, 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:
> +
> + /* close input */
> + avformat_close_input(&ifmt_ctx);
> +
> + /* close output */
> + if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
> + avio_close(ofmt_ctx->pb);
> + avformat_free_context(ofmt_ctx);
> +
> + if (ret < 0 && ret != AVERROR_EOF) {
> + fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
> + return 1;
> + }
> +
> + return 0;
> +}
Regards,
--
Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140119/7e4410e4/attachment.asc>
More information about the ffmpeg-devel
mailing list