yuv转h264 plane调试笔记理解2--基于x264
YUV存储方式
YUV存储方式主要分为两种:Packeted 和 Planar。
Packeted方式类似RGB的存储方式,以像素矩阵为存储方式。
Planar方式将YUV分量分别存储到矩阵,每一个分量矩阵称为一个平面。
YUV420即以平面方式存储,色度抽样为4:2:0的色彩编码格式。其中YUV420P为三平面存储,YUV420SP为两平面存储。
常用的I420(YUV420P),NV12(YUV420SP),YV12(YUV420P),NV21(YUV420SP)等都是属于YUV420,NV12是一种两平面存储方式,Y为一个平面,交错的UV为另一个平面。
由此,I420就是存储方式为Planar,抽样方式为4:2:0,数据组成为YYYYYYYYUUVV的一种色彩编码格式。
除此之外,NV12的数据组成:YYYYYYYYUVUV 。YV12的数据组成:YYYYYYYYVVUU。NV21的数据组成:YYYYYYYYVUVU。
通常,用来远程传输的是I420数据,而本地摄像头采集的是NV12数据。
YUV420(NV12、NV21、I420、YV12)
NV12、NV21 的存储格式为 Y 平面,UV 打包,即:Y 信息存储在一个数组中,UV 信息存储在一个矩阵中。
不同点在于 UV 的排列顺序
NV12: YYYYYYYY UVUV => YUV420SP
NV21: YYYYYYYY VUVU => YUV420SP
I420、YV12 三个分量均为平面格式,即:分别存放在三个 Byte 型数组中
I420: YYYYYYYY UU VV => YUV420P
YV12: YYYYYYYY VV UU => YUV420P
///////////////////////////////////////////////////////////////////////////////////////////////
接着上一次的调试笔记来看,格式呈现灰白色是不对的,因为I420和nv12在存储方式上还是有区别的。
所以还是要理解x264在nv21和i420上是怎么解决的。x264有几个结构体x264_picture_t , x264_param_t,
x264_picture_t 这个是针对输入图像的格式设置编码参数的。比如输入的是yuvi420或者nv12要通过这个设置pts和plane。
x264是支持nv12图像作为输入的。
如果将I420改成NV12通常需要修改
if(csp == X264_CSP_NV12){
pPic_in->img.i_stride[0] = pParam->i_width;
pPic_in->img.i_stride[1] = pParam->i_width;
pPic_in->img.i_stride[2] = 0;
pPic_in->img.i_csp = X264_CSP_NV12;//这里将参数改成nv12
pPic_in->img.i_plane = 2;//这里包含两个平面,其中plane1 是y plane是uv的交错数据,不用另行提取
} else { // 其他暂认为都是YUV420格式
pPic_in->img.i_stride[0] = pParam->i_width;
pPic_in->img.i_stride[1] = pParam->i_width>>1;
pPic_in->img.i_stride[2] = pParam->i_width>>1;
pPic_in->img.i_csp = X264_CSP_I420;
pPic_in->img.i_plane = 3;
}
x264_picture_init(pPic_out);
x264_picture_alloc(pPic_in, csp, pParam->i_width, pParam->i_height);
在编码之前将Y和uv提取到plane中就行了。
case X264_CSP_NV12:
printf("nv12 enc y\n");
fread(pPic_in->img.plane[0],y_size,1,fp_src); //Y
fread(pPic_in->img.plane[1],y_size/2,1,fp_src); //uv
printf("nv12 enc uv end\n");
break;