[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