ffmpeg实战教程(四)格式转换如MP4转MKV等
来源:互联网 发布:离婚证制作软件 编辑:程序博客网 时间:2024/06/05 15:09
知识延伸:
I,P,B帧和PTS,DTS的关系
基本概念:
I frame :帧内编码帧 又称intra picture,I 帧通常是每个 GOP(MPEG 所使用的一种视频压缩技术)的第一个帧,经过适度地压缩,做为随机访问的参考点,可以当成图象。I帧可以看成是一个图像经过压缩后的产物。
P frame: 前向预测编码帧 又称predictive-frame,通过充分将低于图像序列中前面已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧;
B frame: 双向预测内插编码帧 又称bi-directional interpolated prediction frame,既考虑与源图像序列前面已编码帧,也顾及源图像序列后面已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧;
PTS:Presentation Time Stamp。PTS主要用于度量解码后的视频帧什么时候被显示出来
DTS:Decode Time Stamp。DTS主要是标识读入内存中的bit流在什么时候开始送入解码器中进行解码。
在没有B帧存在的情况下DTS的顺序和PTS的顺序应该是一样的。
IPB帧的不同:
I frame:自身可以通过视频解压算法解压成一张单独的完整的图片。
P frame:需要参考其前面的一个I frame 或者B frame来生成一张完整的图片。
B frame:则要参考其前一个I或者P帧及其后面的一个P帧来生成一张完整的图片。
两个I frame之间形成一个GOP,在x264中同时可以通过参数来设定bf的大小,即:I 和p或者两个P之间B的数量。
通过上述基本可以说明如果有B frame 存在的情况下一个GOP的最后一个frame一定是P.
DTS和PTS的不同:
DTS主要用于视频的解码,在解码阶段使用.PTS主要用于视频的同步和输出.在display的时候使用.在没有B frame的情况下.DTS和PTS的输出顺序是一样的.
用ffmpeg实现格式的转化,比如MP4转MKV。
本程序并不进行视音频的编码和解码工作。而是直接将视音频压缩码流从一种封装格式文件中获取出来然后打包成另外一种封装格式的文件。因为不需要进行视音频的编码和解码,所以不会有视音频的压缩损伤。
思路:
程序包含了对两个文件的处理:读取输入文件和写入输出文件。然后使用了一个avcodec_copy_context()拷贝输入的AVCodecContext到输出的AVCodecContext。然后再从输出的AVCodecContext写进输出文件
关键函数:
输入文件操作:
avformat_open_input():打开媒体的的过程开始于avformat_open_input。av_read_frame():从输入文件中读取一个AVPacket。
输出文件操作:
avformat_alloc_output_context2():初始化输出视频码流的AVFormatContext。avformat_new_stream():创建输出码流的AVStream。avcodec_copy_context():拷贝输入视频码流的AVCodecContex的数值t到输出视频的AVCodecContext。avio_open():打开输出文件。avformat_write_header():写文件头(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。av_interleaved_write_frame():将AVPacket(存储视频压缩码流数据)写入文件。av_write_trailer():写文件尾(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。
效果示例,把一个MP4格式转为AVI。
源码:
#include <stdio.h>#define __STDC_CONSTANT_MACROS#ifdef _WIN32//Windowsextern "C"{#include "libavformat/avformat.h"};#else//Linux...#ifdef __cplusplusextern "C"{#endif#include <libavformat/avformat.h>#ifdef __cplusplus};#endif#endifint main(int argc, char* argv[]){ AVOutputFormat *ofmt = NULL; //Input AVFormatContext and Output AVFormatContext AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL; AVPacket pkt; const char *in_filename, *out_filename; int ret, i; int frame_index=0; in_filename = "ws.mp4";//Input file URL out_filename = "ws.avi";//Output file URL av_register_all(); //Input if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {//打开媒体文件 printf( "Could not open input file."); goto end; } if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {//获取视频信息 printf( "Failed to retrieve input stream information"); goto end; } av_dump_format(ifmt_ctx, 0, in_filename, 0); //初始化输出视频码流的AVFormatContext。 avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename); if (!ofmt_ctx) { printf( "Could not create output context\n"); ret = AVERROR_UNKNOWN; goto end; } ofmt = ofmt_ctx->oformat; for (i = 0; i < ifmt_ctx->nb_streams; i++) { //Create output AVStream according to input AVStream AVStream *in_stream = ifmt_ctx->streams[i]; AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);// 初始化AVStream if (!out_stream) { printf( "Failed allocating output stream\n"); ret = AVERROR_UNKNOWN; goto end; } //关键:Copy the settings of AVCodecContext if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) { printf( "Failed to copy context from input to output stream codec context\n"); goto end; } out_stream->codec->codec_tag = 0; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } //Output information------------------ av_dump_format(ofmt_ctx, 0, out_filename, 1); //Open output file if (!(ofmt->flags & AVFMT_NOFILE)) { ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);//打开输出文件。 if (ret < 0) { printf( "Could not open output file '%s'", out_filename); goto end; } } //Write file header if (avformat_write_header(ofmt_ctx, NULL) < 0) { printf( "Error occurred when opening output file\n"); goto end; } while (1) { AVStream *in_stream, *out_stream; //Get an AVPacket 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]; //Convert PTS/DTS pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(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; //Write if (av_interleaved_write_frame(ofmt_ctx, &pkt) < 0) {//将AVPacket(存储视频压缩码流数据)写入文件 printf( "Error muxing packet\n"); break; } printf("Write %8d frames to output file\n",frame_index); av_free_packet(&pkt); frame_index++; } //Write file trailer av_write_trailer(ofmt_ctx);end: avformat_close_input(&ifmt_ctx); /* close output */ if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) avio_close(ofmt_ctx->pb); avformat_free_context(ofmt_ctx); return 0;}
- ffmpeg实战教程(四)格式转换如MP4转MKV等
- ffmpeg实战教程(一)Mp4,mkv等格式解码为h264和yuv数据
- ffmpeg mkv转mp4
- ffmpeg转mp4格式
- ffmpeg实战教程(六)Android CMake实现解码(MP4转YUV)
- 现在 MKV、MP4 等格式的压缩与效果都更好,为什么 RMVB 还是那么流行?
- h264格式的flv和mkv无损转换成mp4的方法
- h264格式的flv和mkv无损转换成mp4的方法
- ffmpeg 转换mkv到avi
- 通过adb录制视频并通过FFMPEG将MP4转换成GIF格式(一)
- 通过adb录制视频并通过FFMPEG将MP4转换成GIF格式(二)
- 分离(MP4/FLV/MKV等)中的H.264视频信息 保存并播放
- ffmpeg 教程之 mp4 文件转换为m3u8 ts 文件
- mp4格式(转)
- 苹果 mov avi 转 mp4 等格式
- Linux搭建FFMPEG环境实现MP4格式转m3u8格式
- 视频转换格式 qlv 转 mp4 详解
- Android Multimedia实战(四)MediaProjection实现截图,与MediaMuxer实现录屏为MP4,Gif格式
- 网站防蜘蛛爬虫控制--怎么使用robots.txt及其详解
- 初学C
- Visionect Technology简介
- random用法
- 数据挖掘比赛入门_以去年阿里天猫推荐比赛为例
- ffmpeg实战教程(四)格式转换如MP4转MKV等
- 微信小程序开发—(十一)navigator
- Spring 根据参数名称注入值
- 折线分割平面
- tornado模板参数传递
- java san jiaoxing
- 生产管理系统产品管理的添加方法
- U3D-- U3d Shader的一些知识
- DialogActivity