2019独角兽企业重金招聘Python工程师标准>>>
https://github.com/shaobin0604/ffmpeg_tutorial
https://github.com/mpenkov/ffmpeg-tutorial
http://dranger.com/ffmpeg/
http://en.wikipedia.org/wiki/YUV
http://en.wikipedia.org/wiki/.mpg
代码:
git clone git@github.com:liyonghelpme2/libavTest.git
libav 是一系列 编码解码 音频 图像 视频的库。
ubuntu 上 apt-get source libav 得到源码。
基本模块包含: libavcodec libavformat libavutil libavdevice 等。
安装好这些模块之后, 在 /usr/share/doc/libavcodec-dev/ 文件夹下有一个例子,
在源代码文件夹中有一个avplay.c 的例子,
参考这两个例子 以及 一些tutorials 和 源代码,写一个将 RGB 值 转化成 视频程序。
主要参考 /usr/share/doc/libavcodec-dev/ 下的例子:
在其中有一个 video_encode_example 的函数, 该函数将 程序生成的一段数据 构造一个视频, 可以将该函数拷到新文件中, 同时写一个main函数,
在main函数中首先注册所有的 codec 解码编码器, 接着调用video_encode_example 函数生成一个mpg 视频。
#include
#include
av_register_all();
video_encode_example();
gcc xxx.c -lavcodec -lavformat
这个程序使用MPEG1VIDEO 编码解码器 将 YUV 空间的帧 转化成 一个MPEG1 标准的视频, YUV 和熟悉的RGB 颜色空间 之间通过一个矩阵进行转化, 关于YUV 参考http://en.wikipedia.org/wiki/YUV
一个MPEG文件可能包含多个流stream 音频, 视频, 字幕等。每个流包含多个帧frame,有关键帧,向后预测帧向前预测帧等。参考MPEG http://en.wikipedia.org/wiki/.mpg
将程序中生成的一帧帧图像 压入视频中基本过程:
分配编码解码器:
分配codec 编码解码器 分配codec的上下文(编码解码的过程是一个执行状态机的过程,上下文中会保存当前编码解码的状态)AVCodec AVCodecContext
avcodec_alloc_context3
设定上下文中的格式信息,包括视频的宽度 高度, bitrate, 帧率,每帧的像素格式等;
设定好上下文之后,可以在该上下文环境下,打开编码解码器,开始编码解码工作;avcodec_open
接着逐帧生成视频:
分配帧结构 和 帧数据缓冲区 用于放每一帧的YUV数据 AVFrame avcodec_alloc_frame picture_buf = malloc()
分配输出video 文件的缓冲区,out_buf = malloc(), 这个buffer 需要足够空间用于容纳一帧 outbuf_size 缓冲的大小
生成 40帧:每一帧压入视频中avcodec_encode_video, 接者将生成的数据写入到文件中, 循环压入下一帧。mpeg格式中 多个帧之间是存在一定关系的,因此压入某一帧生成的数据量是不一定的,但是当前生成的数据是独立的,可以写入文件中。(个人理解)
生成每一帧的YUV,对于RGB值比较好理解,例如要生成红色的 就是255 0 0 需要转化成对应的 YUV值, 在 libavutil 的colorspace头文件中有 RGB_TO_Y_CCIR 等函数用于转化代码 用于从RGB 空间转化到 YUV空间。
其中YUV 空间的 Y 空间宽度 高度是屏幕宽度高度,而UV 空间每个点的值是2*2矩阵点的平均值,因此数据宽度,高度只有Y的1半。而这3个通道的数据是放在3个不同的plane中的,可以参考avpicture_fill 函数的实现,这个函数实现了,设置每种类型图片buffer的填充。
在pixdesc.c 文件中的AVPixFmtDescriptor 中描述了每种帧格式缓冲区数据的放置方法,主要结构是AVPixFmtDescriptor
可以参考上方代码,制作显示红绿蓝条的视频