ffmpeg视频拼接合成/多YUV拼接合成一个YUV

       最近在预研融屏/多画面显示,接触ffmpeg比较多,首先想到的是将多YUV合成一个YUV,然后再渲染显示,立马动手起来。

       首先,先从简单的来,选取两个YUV,分辨率分别为480*272、352*288,然后合成目标702*288的YUV,这样是考虑多画面时有不一致的分辨率,把它们弄成统一的分辨率再合成,YUV的格式都是YUV420P采样格式,统一分辨率是352*288。

       第二,裁减YUV,利用到ffmpeg的sws_scale函数去裁减,先初始化SwsContext

/*
   in_w --- 源分辨率的宽, in_h ---- 源分辨率的高
   frame_msg->width/height --- 需要裁减成的分辨率
   SWS_BICUBLIN --- 裁减时使用的算法
*/
code_msg->pSwsCtx = sws_getContext(in_w, in_h, AV_PIX_FMT_YUV420P, 
		                       frame_msg->width, frame_msg->height, AV_PIX_FMT_YUV420P,
						SWS_BICUBLIN, NULL, NULL, NULL);

然后进行裁减

/*
code_msg->pFrame->data --- 源YUV
code_msg->pCodecCtx->height --- 源YUV的高
code_msg->pSwsframe->data --- 裁减后的YUV
*/
ret = sws_scale(code_msg->pSwsCtx, code_msg->pFrame->data, code_msg->pFrame->linesize, 0, 
			code_msg->pCodecCtx->height, code_msg->pSwsframe->data, code_msg->pSwsframe->linesize)

详细使用请参考: https://blog.csdn.net/weixin_33859844/article/details/90305179

       第三,合成YUV,首先申请一个AVFrame来存储目标YUV,然后将两个YUV拷贝进这个目标容器就行了,拷贝时注意U、V分量,在Y420采样中,在水平和垂直清晰方面,Cb和Cr都是Y的一半,所以U、V分量在拷贝时各自拷贝一半即可。我是将两个YUV左右显示的。

/*
RENDER_HEIGHT --- 目标YUV的高
RENDER_WIDTH  --- 目标YUV的宽
code_msg_01.pSwsframe --- 裁减后的YUV
code_msg_02.pFrame --- 第二个YUV
pDstFrame->data --- 目标YUV
*/
while(nYIndex<RENDER_HEIGHT)
{
    memcpy(pDstFrame->data[0] + nYIndex*RENDER_WIDTH, code_msg_01.pSwsframe->data[0]+nYIndex*RENDER_WIDTH/2, RENDER_WIDTH/2);
    memcpy(pDstFrame->data[0] + nYIndex*RENDER_WIDTH+ RENDER_WIDTH/2, code_msg_02.pFrame->data[0]+nYIndex*RENDER_WIDTH/2, RENDER_WIDTH/2);
    nYIndex++;
			
    //Y420采样,在水平和垂直清晰方面,Cb和Cr都是Y的一半,所以U、V分量在拷贝时各自拷贝一半即可
    if(nUVIndex<RENDER_HEIGHT/2)
    {
        memcpy(pDstFrame->data[1] + nUVIndex*RENDER_WIDTH/2, code_msg_01.pSwsframe->data[1]+nUVIndex*code_msg_01.pSwsframe->width/2,code_msg_01.pSwsframe->width/2);
        memcpy(pDstFrame->data[1] + nUVIndex*RENDER_WIDTH/2+ RENDER_WIDTH/4, code_msg_02.pFrame->data[1]+nUVIndex*RENDER_WIDTH/4, RENDER_WIDTH/4);

        //U
        memcpy(pDstFrame->data[2] + nUVIndex*RENDER_WIDTH/2, code_msg_01.pSwsframe->data[2]+nUVIndex*code_msg_01.pSwsframe->width/2, code_msg_01.pSwsframe->width/2);
        memcpy(pDstFrame->data[2] + nUVIndex*RENDER_WIDTH/2+ RENDER_WIDTH/4, code_msg_02.pFrame->data[2]+nUVIndex*RENDER_WIDTH/4, RENDER_WIDTH/4);
        nUVIndex++;
    }
}

       最后,效果图如下:

测试使用的代码请参考: //download.csdn.net/download/karongsmile/12242104

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章