解复用
传递
输出
源媒体流或文件
解复用器
复用器
目标媒体流或文件
函数调用流程
函数接口
int avformat_alloc_output_context2(AVFormatContext **ctx, ff_const59 AVOutputFormat *oformat, const char *format_name, const char *filename);
创建AVFormatContext用于输出格式的format,对应的使用avformat_free_context()函数释放AVFormatContext。
ctx:该函数用于创建的AVFormatContext
oformat:指定创建的格式,如果此值为NULL,则以format_name或filename为准
format_name:用于指定输出的格式如“mp4”
filename:用于指定输出目录或url
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
在AVFormatContext输出的时候,如果想要输出音频和视频都需要通过该函数创建一条流操作句柄,每条流都需要填充codec参数,可以使用avcodec_parameters_copy从其他流的codec信息中填充codec参数。
int avio_open(AVIOContext **s, const char *url, int flags);
打开输出文件或url
int avformat_write_header(AVFormatContext *s, AVDictionary **options);
创建流的私有数据并且向输出文件写入流header
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
pkt中是存储的是媒体数据,通过该函数写入目标文件中
int av_write_trailer(AVFormatContext *s);
向输出文件写入尾部信息,例如mp4文件中的moov box
需要注意
代码示例
#ifdef __cplusplus extern "C" {
#endif #include <libavutil/timestamp.h> #include <libavformat/avformat.h> #ifdef __cplusplus } #endif 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); } 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; int stream_index = 0; int *stream_mapping = NULL; int stream_mapping_size = 0; 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]; 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; } stream_mapping_size = ifmt_ctx->nb_streams; stream_mapping = av_mallocz_array(stream_mapping_size, sizeof(*stream_mapping)); if (!stream_mapping) {
ret = AVERROR(ENOMEM); goto end; } ofmt = ofmt_ctx->oformat; for (i = 0; i < ifmt_ctx->nb_streams; i++) {
AVStream *out_stream; AVStream *in_stream = ifmt_ctx->streams[i]; AVCodecParameters *in_codecpar = in_stream->codecpar; if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO && in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO && in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
stream_mapping[i] = -1; continue; } stream_mapping[i] = stream_index++; out_stream = avformat_new_stream(ofmt_ctx, NULL); if (!out_stream) {
fprintf(stderr, "Failed allocating output stream\n"); ret = AVERROR_UNKNOWN; goto end; } ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar); if (ret < 0) {
fprintf(stderr, "Failed to copy codec parameters\n"); goto end; } out_stream->codecpar->codec_tag = 0; } 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]; if (pkt.stream_index >= stream_mapping_size || stream_mapping[pkt.stream_index] < 0) {
av_packet_unref(&pkt); continue; } pkt.stream_index = stream_mapping[pkt.stream_index]; out_stream = ofmt_ctx->streams[pkt.stream_index]; log_packet(ifmt_ctx, &pkt, "in"); pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); 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_packet_unref(&pkt); } av_write_trailer(ofmt_ctx); end: avformat_close_input(&ifmt_ctx); if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) avio_closep(&ofmt_ctx->pb); avformat_free_context(ofmt_ctx); av_freep(&stream_mapping); if (ret < 0 && ret != AVERROR_EOF) {
fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); return 1; } return 0; }
交流群:
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。
本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/152786.html
锐起无盘安装图文教程
下一篇
2025-03-07 15:45