本文以H264视频流为例,讲解解码流数据的步骤。
为突出重点,本文只专注于讨论解码视频流数据,不涉及其它(如开发环境的配置等)。如果您需要这方面的信息,请和我联系。
- 准备变量
定义AVCodecContext。如果您使用类,可以定义成类成员。我这里定义成全局变量。
定义一个AVFrame,AVFrame描述一个多媒体帧。解码后的数据将被放在其中。
- 初始化解码器
现在开始初始化您的解码器。我把整个初始化过程包在了一个函数里,除非您有更好的主意,我建议您也这么做。函数长得象这样:
BOOL H264_Init()
{
…
}
初始化libavcodec,MMPEG要求,这个函数一定要第一个被调用:
挂上所有的codec。也许只挂一个H264的codec就行,我没试过:
得到H264的解码器:
创建一个AVCodecContext,并用默认值初始化:
更改g_pCodecCtx的一些成员变量的值,您应该从解码方得到这些变量值:
g_pCodecCtx->time_base.den = 25;
g_pCodecCtx->bit_rate = 0; //初始化为0
g_pCodecCtx->frame_number = 1; //每包一个视频帧
g_pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
g_pCodecCtx->width = 704; //这两行:视频的宽度和高度
g_pCodecCtx->height = 576
I420是YUV格式的一种,而YUV有packed format和planar format两种,而I420属于planar format的一种。
同时I420表示了YUV的采样比例4:2:0。4:2:0的YUV并不是说没有V分量,而是指对于每一个行,只有一个U或者V分量。比如第一行里,是YUYYUY,到了第二行是YVYYVY,那么对于每一行来说就是4:2:0或者4:0:2。需要说明的是,这里的排列方式是针对packedformat而言的,因此并不适用于I420这样的planar format。Packed format和plannerformat的区别在于,packedformat中的YUV是混合在一起的,因此就有了UYVY、YUYV等等,他们在码流中排列的方式有所不同。而对于plannerformat每一个Y分量,U分量和V分量都是以独立的平面组织的,也就是说所有的U分量都在Y分量之后出现,而V分量在所有的U分量之后。就像三个大色块一样。这样的组织方式除了I420以外还有YV12、IYUV等等。
有关YUV更详细的资料,可参考:http://www.fourcc.org/yuv.php
值得注意一点的是,planner format没有像packedformat那样的顺序性,那么是否意味着420和411就没有区别了呢,而且有些资料上也有写 IYUV is identical toI420。wiki上也对此有很明确的说明。表面上看IYUV和I420的data组织形式完全一样,都是4:1:1的YUV色平面组成,但是I420的UV分量是在2x2的像素点中采样得到的,而IYUV的UV分量是在1x4的行像素点中采样得到的,所以在表达的方式上还是有一定差异的。
--------------------------------------------------------------------------------------------------------------------
YV12 - YUV 4:2:0 planar format.
I420 - YUV 4:2:0 planar format with chroma planes in reverse order.
NV12 - YUV 4:2:0 with interleaved chroma samples.
YUY2 - YUV 4:2:2 packed format.
UYVY - YUV 4:2:2 packed format with different sample ordering.
I420
YUV是指亮度参量和色度参量分开表示的像素格式,而这样分开的好处就是不但可以避免相互干扰,还可以降低色度的采样率而不会对图像质量影响太大。YUV是一个比较笼统地说法,针对它的具体排列方式,可以分为很多种具体的格式。
YUV格式解析1(播放器——project2)YUV 的优点之一是,色度频道的采样率可比 Y 频道低,同时不会明显降低视觉质量。有一种表示法可用来描述 U 和 V 与 Y 的采样频率比例,这个表示法称为 A:B:C 表示法:
4:4:4 表示色度频道没有下采样。
•4:2:2 表示 2:1 的水平下采样,没有垂直下采样。对于每两个 U 样例或 V 样例,每个扫描行都包含四个 Y 样例。
•libx264是一个自由的H.264编码库,是x264项目的一部分,使用广泛,ffmpeg的H.264实现就是用的libx264。
代码要把一个I420视频文件编码为H264格式。I420是YUV中planar格式的一种,一张I420图片中有三个plane,分别存放整张图片的Y、U、V分量;采样比例为4:2:0,12bpp,Y:U:V的分量长度是4:1:1。
头文件1 #include <stdint.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <x264.h>
1 int width = 480; 2 int height = 360; 3 int fps = 25; 4 size_t yuv_size = width * height * 3 / 2; 5 x264_t *encoder; 6 x264_picture_t pic_in, pic_out; 7 int inf, outf; 8 uint8_t *yuv_buffer; 9 10 if (argc != 3) { 11 printf("usage: %s input output\n", argv[0]); 12 }
- 视频尺寸是480×360,YUV I420格式,每个像素1.5个字节,所以一张YUV图片大小是width * height * 1.5
-
encoder就是编码器,x264_t格式在x264.h文件中只有
typedef struct x264_t x264_t
编码器类型只需要也只能声明为x264_t的指针类型
- 每次编码时,YUV图片的信息都保存在pic_in中
- 输入输出的文件描述符
- 从文件读入的YUV的缓冲区