视频编码

视频音频的解码介绍过了,接下来是编码,相对于解码来说,编码流程相对麻烦一些。不过不要担心,小编带你装一把。

视频编码流程

第一步:注册组件

av_register_all();

第二步:初始化封装格式上下文

avformat_alloc_context()

第三步:打开输出文件

avio_open()

第四步:创建输出码流(视频流 )

AVStream* av_video_stream = avformat_new_stream() //只是创建内存,目前不知道是什么类型的流,但是们希望是视频流

第五步:查找视频编码器

5.1 获取编码器上下文

AVCodecContext* avcodec_context = av_video_stream->codec;

5.2设置编码器上下文参数

avcodec_context->codec_id = avoutput_format->video_codec;//设置编码器ID
avcodec_context->codec_type = AVMEDIA_TYPE_VIDEO;//设置编码器类型
avcodec_context->pix_fmt = AV_PIX_FMT_YUV420P;//设置读取像素数据格式(编码的是像素数据格式),这个类型是根据解码的时候指定的视频像素数据格式类型
//设置视频宽高
avcodec_context->width = 640;
avcodec_context->height = 352;
//设置帧率
//这里设置为每秒25帧 fps(f:frame 帧,ps:每秒)
avcodec_context->time_base.num = 1;
avcodec_context->time_base.den = 25;
//设置码率(码率bps:单位时间内传输的二进制数据量),码率也是比特率,比特率越高,传输速度越快
//kbps:每秒传输千位
avcodec_context->bit_rate = 468000;//码率 = 视频大小(bit)/时间(秒)。码率越大证明视频越大
//设置GOP(GOP:画面组,一组连续的画面),影响视频质量问题
/**
*MPEG格式画面类型:I帧,P帧,B帧
*I帧:原始帧(原始视频数据,完整的画面),关键帧(必须要有,如果没有则不能进行编解码操作),视频的第一帧总是是I帧
*P帧:向前预测帧(帧间预测编码帧):预测前面一帧的类型,处理数据,前面一帧可能是I帧,也可能是B帧
*B帧:前后预测帧(双向预测编码帧),B帧压缩率高,但同时对解码性能要求也高
*I帧越少,视频越小。其实说白了。B 和 P 帧是对I帧的压缩处理,从而减小视频大小
*/
avcodec_context->gop_size = 250;//每250帧插入一个I帧
设置量化参数. 量化系数越小,视频越清晰(这个量化参数都是些数学算法,有兴趣可以了解一下。),这里采用默认值。
avcodec_context->qmin = 10;//最小量化系数
avcodec_context->qmax = 51;//最大量化系数
//设置B帧最大值
avcodec_context->max_b_frames = 0;//不需要B帧

5.3 查找编码器(h264),默认情况下FFmpeg没有编译进行h264库,所以要编译h264库

AVCodec* avcodec = avcodec_find_encoder(avcodec_context->codec_id);

第六步:打开编码器(h264编码器)

打开以前做一些编码延时问题优化。编码选项->编码设置
AVDictionary *param = 0;
if (avcodec_context->codec_id == AV_CODEC_ID_H264) {
//需要查看x264源码->x264.c文件
//第一个值:预备参数
//key: preset
//value: slow->慢
//value: superfast->超快
av_dict_set(¶m, "preset", "slow", 0);
//第二个值:调优
//key: tune->调优
//value: zerolatency->零延迟
av_dict_set(¶m, "tune", "zerolatency", 0);
}
打开:avcodec_open2();

第七步:写入文件头信息

avformat_write_header();

第八步:循环编码yuv文件(视频像素数据)->编码为视频压缩数据(h264格式)

这一步有很多设置操作,具体可以参考demo

第9步:视频编码处理

9.1 发送一帧视频像素数据

avcodec_send_frame()

9.2 接收一帧视频像素数据->编码为->视频压缩数据格式

avcodec_receive_packet();

9.3 判定是否编码成功

第10步:将视频压缩数据->写入到输出文件中

av_write_frame();

第11步:写入剩余帧数据->可能没有

flush_encoder();

第12步:写入文件尾部信息

av_write_trailer();

第13步:释放内存

步骤比较多,但实现代码不是特别复杂,为了大家能够更深入理解,请大家参考[demo](https://github.com/xiaoyuancai/FFMPEG_demo_VideoEncode)

你可能感兴趣的:(视频编码)