2 * Copyright (c) 2013 Stefano Sabatini
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * libavformat/libavcodec demuxing and muxing API example.
27 * Remux streams from one container format to another.
31 #include <libavutil/timestamp.h>
32 #include <libavformat/avformat.h>
34 static void log_packet(const AVFormatContext
*fmt_ctx
, const AVPacket
*pkt
, const char *tag
)
36 AVRational
*time_base
= &fmt_ctx
->streams
[pkt
->stream_index
]->time_base
;
38 printf("%s: pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
40 av_ts2str(pkt
->pts
), av_ts2timestr(pkt
->pts
, time_base
),
41 av_ts2str(pkt
->dts
), av_ts2timestr(pkt
->dts
, time_base
),
42 av_ts2str(pkt
->duration
), av_ts2timestr(pkt
->duration
, time_base
),
46 int main(int argc
, char **argv
)
48 AVOutputFormat
*ofmt
= NULL
;
49 AVFormatContext
*ifmt_ctx
= NULL
, *ofmt_ctx
= NULL
;
51 const char *in_filename
, *out_filename
;
55 printf("usage: %s input output\n"
56 "API example program to remux a media file with libavformat and libavcodec.\n"
57 "The output format is guessed according to the file extension.\n"
62 in_filename
= argv
[1];
63 out_filename
= argv
[2];
67 if ((ret
= avformat_open_input(&ifmt_ctx
, in_filename
, 0, 0)) < 0) {
68 fprintf(stderr
, "Could not open input file '%s'", in_filename
);
72 if ((ret
= avformat_find_stream_info(ifmt_ctx
, 0)) < 0) {
73 fprintf(stderr
, "Failed to retrieve input stream information");
77 av_dump_format(ifmt_ctx
, 0, in_filename
, 0);
79 avformat_alloc_output_context2(&ofmt_ctx
, NULL
, NULL
, out_filename
);
81 fprintf(stderr
, "Could not create output context\n");
82 ret
= AVERROR_UNKNOWN
;
86 ofmt
= ofmt_ctx
->oformat
;
88 for (i
= 0; i
< ifmt_ctx
->nb_streams
; i
++) {
89 AVStream
*in_stream
= ifmt_ctx
->streams
[i
];
90 AVStream
*out_stream
= avformat_new_stream(ofmt_ctx
, in_stream
->codec
->codec
);
92 fprintf(stderr
, "Failed allocating output stream\n");
93 ret
= AVERROR_UNKNOWN
;
97 ret
= avcodec_copy_context(out_stream
->codec
, in_stream
->codec
);
99 fprintf(stderr
, "Failed to copy context from input to output stream codec context\n");
102 out_stream
->codec
->codec_tag
= 0;
103 if (ofmt_ctx
->oformat
->flags
& AVFMT_GLOBALHEADER
)
104 out_stream
->codec
->flags
|= CODEC_FLAG_GLOBAL_HEADER
;
106 av_dump_format(ofmt_ctx
, 0, out_filename
, 1);
108 if (!(ofmt
->flags
& AVFMT_NOFILE
)) {
109 ret
= avio_open(&ofmt_ctx
->pb
, out_filename
, AVIO_FLAG_WRITE
);
111 fprintf(stderr
, "Could not open output file '%s'", out_filename
);
116 ret
= avformat_write_header(ofmt_ctx
, NULL
);
118 fprintf(stderr
, "Error occurred when opening output file\n");
123 AVStream
*in_stream
, *out_stream
;
125 ret
= av_read_frame(ifmt_ctx
, &pkt
);
129 in_stream
= ifmt_ctx
->streams
[pkt
.stream_index
];
130 out_stream
= ofmt_ctx
->streams
[pkt
.stream_index
];
132 log_packet(ifmt_ctx
, &pkt
, "in");
135 pkt
.pts
= av_rescale_q_rnd(pkt
.pts
, in_stream
->time_base
, out_stream
->time_base
, AV_ROUND_NEAR_INF
|AV_ROUND_PASS_MINMAX
);
136 pkt
.dts
= av_rescale_q_rnd(pkt
.dts
, in_stream
->time_base
, out_stream
->time_base
, AV_ROUND_NEAR_INF
|AV_ROUND_PASS_MINMAX
);
137 pkt
.duration
= av_rescale_q(pkt
.duration
, in_stream
->time_base
, out_stream
->time_base
);
139 log_packet(ofmt_ctx
, &pkt
, "out");
141 ret
= av_interleaved_write_frame(ofmt_ctx
, &pkt
);
143 fprintf(stderr
, "Error muxing packet\n");
146 av_free_packet(&pkt
);
149 av_write_trailer(ofmt_ctx
);
152 avformat_close_input(&ifmt_ctx
);
155 if (ofmt_ctx
&& !(ofmt
->flags
& AVFMT_NOFILE
))
156 avio_close(ofmt_ctx
->pb
);
157 avformat_free_context(ofmt_ctx
);
159 if (ret
< 0 && ret
!= AVERROR_EOF
) {
160 fprintf(stderr
, "Error occurred: %s\n", av_err2str(ret
));