FFmpeg基础:封装格式转换

news/2024/11/2 5:39:05/

不同的视频封装格式有不同的特点,有的功能强大支持多个视频流、音频流和字幕文件比如MKV格式,有的形成的文件极小、加载速度极快,适合网络播放比如flv格式,有的体积小能跨平台播放比如MOV格式。为了适应不同场景下的播放需求,有时候我们需要将视频的封装格式进行转换。这里介绍一下如何通过FFmpeg库实现不同封装格式的转换。封装格式转换的流程如下所示:
在这里插入图片描述
FFmpeg库实现封装格式转换的示例如下所示:
(输出的封装格式通过文件的后缀名称来进行确定)

#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>//输出包的详细信息(pts,dts,time_base)
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);
}//@1输入视频文件地址 @2输出视频文件地址
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""argument1 input mp4 file path.\n""argument2 output flv file path.\n""\n", argv[0]);return 1;}in_filename = argv[1]; //input fileout_filename = argv[2];//output file//打开输入视频的上下文并获取流信息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");//拷贝数据包,并转换时间基time_basepkt.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;
}

http://www.ppmy.cn/news/641636.html

相关文章

html视频文件哪种格式好,常见的视频格式有哪些?

视频格式实质是视频编码方式&#xff0c;可以分为适合本地播放的本地影像视频和适合在网络中播放的网络流媒体影像视频两大类。尽管后者在播放的稳定性和播放画面质量上可能没有前者优秀&#xff0c;但网络流媒体影像视频的广泛传播性使之正被广泛应用于视频点播、网络演示、远…

TS数据流的解析

TS数据流的解析 文档修改信息 1 TS 数据流简介 1.1 TS流的构成1.2 TS流的产生1.3 TS流的格式1.4 参考文档1.5 小结 2 TS数据流包头的解析 2.1 解析步骤2.2 包长解析2.3 PID解析2.4 负载单元开始标志解析2.5 小结 3 PAT表的解析 3.1 解析步骤3.2 PAT表的描述3.3 PAT表的获取3…

Apache IoTDB 系列教程-7:时序数据文件格式 TsFile

在大数据生态中有很多文件格式&#xff0c;像 Parquet&#xff0c;ORC&#xff0c;Avro 等等&#xff0c;都是针对嵌套数据设计的文件格式。这些文件格式普遍具有预先定义的schema&#xff0c;数据以行式写入&#xff0c;按属性组织&#xff0c;列式存储。但是这些文件格式一般…

TS流格式(转)

TS流格式&#xff08;转&#xff09; 一 从TS流开始 数字电视机顶盒接收到的是一段段的码流&#xff0c;我们称之为TS&#xff08;Transport Stream&#xff0c;传输流&#xff09;&#xff0c;每个TS流都携带一些信息&#xff0c;如Video、Audio以及我们需要学习的PAT、PMT等信…

TS流讲解--什么是ts流

TS流讲解--什么是ts流 目录(?)[-] 一 从TS流开始 一 TS流PS流PES流和ES流都是什么二 TS流是如何产生的三 TS流的格式是怎样的 二 从TS流到PATPMT 一 PAT表Program Association Table节目关联表 1 PAT表的描述表格分析2 PAT表的定义代码分析3 PAT表的结构代码分析 4 PAT表…

Vegas渲染的时候选什么格式?

在使用Vegas制作视频后渲染选取格式的时候&#xff0c;很多小伙伴经常会苦恼。不知道该选哪个格式渲染好&#xff0c;所以今天小编就这个问题来为大家写一篇教程。 首先&#xff0c;编辑好你的视频后&#xff0c;点击“文件”——“渲染为”&#xff0c;进入视频格式的选择界面…

ts流格式解析

一 从TS流开始 数字电视机顶盒接收到的是一段段的码流&#xff0c;我们称之为TS&#xff08;Transport Stream&#xff0c;传输流&#xff09;&#xff0c;每个TS流都携带一些信息&#xff0c;如Video、Audio以及我们需要学习的PAT、PMT等信息。因此&#xff0c;我们首先需要了…

jq 给按钮添加方法_告别存储烦恼,4种快速将M2TS格式转换为MKV的方法。

目前市场上的蓝光碟片和高清摄象机上录制的视频片段通常是M2TS形式。 由于高质量的视频&#xff0c;M2TS格式往往需要占据很大的空间&#xff0c;给用户带来很多不便。 因此&#xff0c;很多人选择将M2TS转换为MKV&#xff0c;作为一种开放的免费多媒体容器格式&#xff0c;MKV…