linux3536的H264编码记录(YUV422转H264)

一:首先进行YUV422对YUV420的转换

https://blog.csdn.net/li_wen01/article/details/53767245

linux3536的H264编码记录(YUV422转H264)_第1张图片

YUV422的数据格式分布:

YUV420数据格式分布:

linux3536的H264编码记录(YUV422转H264)_第2张图片

YUYV是交叉分布存储,每两组Y公用一组UV,YUV420是顺序存储,每4个Y共用一组UV分量,所以我们需要把YUYV的Y分量全部读取,然后隔行读取UV分量(eg:输入大小:640*480*2,输出大小640*480*3/2),将YUV分开存储。

void yuv22_cover_yuv420(char *i_buf,char o_buf,int width,int height)
{
    int j,i;
    char *y,*u,*v;
    int  index_y,index_u,index_v;
        
    y=o_buf;
    u=o_buf+(width*height);
    v=o_buf+width*height+width*height/4);
    index_y = 0;
    index_u = 0;
    index_v = 0;
    for(j=0;j     {
        for(i=0;i         {
            *(y+(index_y++))= *(i_buf + width*j +i);
            *(y+(index_y++))= *(i_buf + width*j +i+2);
            if(j%2 == 0)
            {
                *(u + (index_u++)) = *(i_buf + width * j + i + 1);
                *(v + (index_v++)) = *(i_buf + width * j + i + 3);
            } }}}

二:

主要是从摄像头得到非压缩的YUV422的数据,然后进行编码

Image ->venc(编码通道)(可完成视频内容的遮挡和覆盖等内容REGION)->输出Coded stream,

VENC模块由编码通道子模块和编码协议子模块(H.264/H265/JPEG/MJPEG)组成,通道支持接收YUV个数图像输入,支持格式YUV420(H.264/H265/),YUV422(JPEG/MJPEG),通道模块接受外部原始图像数据,比较图像尺寸和编码通道尺寸,

如果输入图像比编码通道尺寸大,VENC按编码通道尺寸大小,调用VGS对原图像进行缩小,对缩小的图像进行编码。如果输入图像比编码通道尺寸小,直接丢弃,如果通道相当,直接编码。完成视频区域管理之后,图像被送入具体的协议类型编码通道,完成视频编码,输出码流。编码通道作为基本容器,保存编码通道的多种用户设置和管理通道的多种资源,编码控制器提供对编码参数的控制和调整,从而对输出码率进行控制。(码率控制,编码器两个概念)

1:码率控制:跟图像的压缩比和图像的质量有关,码率器提供了三种码率控制模式,CBR,VBR,FIXQP

CBR:固定比特率:保证编码平稳 ,VBR:可变波特率,图像质量平稳,FIXQP固定的QP值。

码流帧配置方式:单包模式和多包模式,多包模式:对于H264,I帧包含4个NAL包(4个NAL包分别为sps包、pps 包、sei包、Islice 包,这里假设pps 包只有一个,且4 个NAL包是独立的,包类型不同);单包模式对于H.264,当为I 帧时,调用HI_MPI_VENC_GetStream 接口,一个I 帧包含1个NAL包(该NAL包的包类型为Islice 包,且包含sps、pps、sei、
Islice 的数据);默认多包模式,

当用户调用分包接口,(例如:HI_MPI_VENC_SetH264SliceSplit 时,一帧会被分成多个slice,如果用户选择单包模式时,对于I 帧来说,该帧第一个ISlice 包会包含 sps、pps、sei 的数据,该帧的其他ISlice 则没有。即对于H.264,sps、pps、sei的数据只会出现在I 帧的第一个Islice 中并合为1个包,且包类型为ISlice;对于JPEG/MJPEG来说,图像参数包只会出现在一帧的第一个数据包中并合为1 个包,且包类型为数据包。

SPS+PPS+Islice+无效数据+码流。

编码帧存储:支持两种方式Private VB池创建编码通道时由VENC创建私有的VB池作为该通道的参考帧和重构帧buffer

UserVB不分配参考帧和重构帧,而是由用户调用接口HI_MPI_VB_CreatePool 创建一个视频缓存VB池,再通过调用接口HI_MPI_VENC_AttachVbPool 把某个编码通道绑定到固定的视频缓存VB池中。

编码帧的VB的大小:FrameSize = YHeaderSize + CHeaderSize + YSize + CSize

建议使用select方式获取码流,且按照如下的流程:(1)调用HI_MPI_VENC_Query 函数查询编码通道状态;(2)确保u32CurPacks和u32LeftStreamFrames 同时大于0;(3)调用malloc 分配u32CurPacks 个包信息结构体(4)调用HI_MPI_VENC_GetStream 获取编码码流;(5)调用HI_MPI_VENC_ReleaseStream 释放码流缓存。

 

 

 

你可能感兴趣的:(个人随笔)