千家信息网

YUV420 Planar 转换为 YUV422 Packed

发表于:2024-10-12 作者:千家信息网编辑
千家信息网最后更新 2024年10月12日,YUV格式通常有两大类:打包(packed)格式和平面(planar)格式。Packed 格式将YUV分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel),比如相邻两个
千家信息网最后更新 2024年10月12日YUV420 Planar 转换为 YUV422 Packed



YUV格式通常有两大类:打包(packed)格式和平面(planar)格式。


Packed 格式将YUV分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel),

比如相邻两个像素组成一个宏像素,UYVY


Planar 格式使用三个数组分开存放YUV三个分量。

在使用 FFMPEG avcodec_decode_video() 函数解码H.264码流后,得到 planar 格式存储的YUV分量

data[0], linesize[0], 描述Y分量的地址和跨度(stride)
data[1], data[2], linesize[1], 描述U,V分量的地址和跨度(stride)


在某些场合下,我们需要将YUV420 Planar格式转化成 YUV422 Packed格式,以方便显示或处理。下面这个函数使用MMX指令完成这个任务。


void YUV420toUYVY422(unsigned char *pszSrcY, int iSrcPitchY, unsigned char *pszSrcU,
unsigned char *pszSrcV, int iSrcPitchUV, unsigned char *pszDst,
int iSrcWidth, int iSrcHeight, int iDstPitch)
{
int iSrcStride = iSrcPitchY + iSrcPitchY - iSrcWidth;
int iSrcStrideU = (iSrcPitchY - iSrcWidth) >> 1;
int iDstStride =(iDstPitch - iSrcWidth) << 1;

__asm
{
push ebx
mov edi , [pszDst]
mov esi , [pszSrcY]
mov eax , [pszSrcU]
mov ebx , [pszSrcV]
mov ecx , [iSrcHeight]
mov edx , [iSrcWidth]
cyc:
movq mm0, qword ptr[esi] //y1(yyyyyyyy)
movq mm1, qword ptr[esi + 8] //y2 (yyyyyyyy)
movq mm2 , qword ptr [eax] //u ( u u u u u u u u)
movq mm3 , qword ptr [ebx] //v ( v v v v v v v v)
movq mm4 , mm2

//push eax
//xor eax, eax
//movd mm2, eax //u ( u u u u u u u u)
//movd mm3, eax //v ( v v v v v v v v)
//movq mm4, mm2
//pop eax

//-----------------------------------------------------
//punpcklbw mmDST, mmSRC
//交叉组合 mmDST 与 mmSRC 低位双字(4B)中的字节,
//结果(8B)放入 mmDST
//-----------------------------------------------------
//before:
//MM0 == 01 02 03 04 _ 05 06 07 08 hex
//MM1 == 09 0a 0b 0c _ 0d 0e 0f 00 hex
//punpcklbw MM0, MM1, after:
//MM0 = 0d 05 0e 06 0f 07 00 08 h (64bit full)
//-----------------------------------------------------
//when write MM0 to memory: 08 00 07 0f 06 0e 05 0d h
//-----------------------------------------------------
punpcklbw mm2 , mm3 // uv1 ( LOW 8B v u v u v u v u)
punpckhbw mm4 , mm3 // uv2 (v u v u v u v u HI 8B )
movq mm6 , mm2
movq mm7 , mm4
movq mm3 , mm2
movq mm5 , mm4
punpcklbw mm2 , mm0 // uyvy1 ( y v y u y v y u)
punpckhbw mm3 , mm0 // uyvy2 (y v y u y v y u )
punpcklbw mm4 , mm1 // uyvy3 ( Y v Y u Y v Y u)
punpckhbw mm5 , mm1 // uyvy4 (Y v Y u Y v Y u )
movq qword ptr [edi] , mm2
movq qword ptr [edi+8] , mm3
movq qword ptr [edi+16] , mm4
movq qword ptr [edi+24] , mm5

add esi , [iSrcPitchY]
add edi , [iDstPitch]

movq mm0 , qword ptr [esi] //y1
movq mm1 , qword ptr [esi+8] //y2
movq mm2 , mm6
movq mm4 , mm7
movq mm3 , mm2
movq mm5 , mm4
punpcklbw mm2 , mm0 // uyvy 1 //low byte mix
punpckhbw mm3 , mm0 // uyvy 2 //high byte mix
punpcklbw mm4 , mm1 // uyvy 3
punpckhbw mm5 , mm1 // uyvy 4
movq qword ptr [edi] , mm2
movq qword ptr [edi+8] , mm3
movq qword ptr [edi+16] , mm4
movq qword ptr [edi+24] , mm5

sub esi , [iSrcPitchY]
sub edi , [iDstPitch]
add eax , 8 //U
add ebx , 8 //V
add esi , 16 //Y
add edi , 32 //DST

sub edx , 16 //WIDTH
ja cyc //repeat until current row completes

mov edx, [iSrcWidth] //Reload width at new row
add esi , [iSrcStride] //Reload stride at new row
add eax , [iSrcStrideU] //U stride
add ebx , [iSrcStrideU] //V stride
add edi , [iDstStride] //Y stride

sub ecx,2 //HEIGHT 480
ja cyc //repeat until all rows complete

emms
pop ebx
}
}


0