YUYV422到YUV420PSEMI格式的转化

来源:互联网 发布:三唑仑片淘宝网上名称 编辑:程序博客网 时间:2024/06/06 09:59

 

1.1  颜色空间说明

由于TI提供的H264编码器只支持YUV420PSEMI颜色空间的视频图像格式,而OV5642不支持输出这个格式,所以选用了与之比较接近的YUYV422格式,然后由ARM进行转换。

YUV420PSEMI的格式如下图所示。UV分量是交错的,与Y分量分开而单独存储在Y分量后面。整幅图像Y分量占2/3,UV分量占1/3。

 

YUYV422格式如下图所示。YUV三个分量是交错存储的。

 

1.2  Matlab代码实现颜色空间转换

为了实现YUYV422到YUV420PSEMI格式的转换,首先使用Matlab进行编程验证算法可行,然后再移植到视频编码的程序中。Matlab实现两种格式转换的核心代码如下所示。

 

fid = fopen('test_422.264', 'r' );

if fid == -1

    error('Cannot open file.');

end

hor = 640;

ver = 480;

for i=1:ver

    picture(i,:) = fread(fid, hor * 2, 'uint16');

end

fclose(fid);

picture = picture./4;

y = uint8(zeros(ver, hor));

u = uint8(zeros(ver, hor));

v = uint8(zeros(ver, hor));

for i = 1:ver

    for j = 1:4:hor * 2

        y(i, (j + 1)/2) = picture(i, j);

        u(i, (j + 1)/2) = picture(i, j + 1);

        u(i, (j + 3)/2) = picture(i, j + 1);

        y(i, (j + 3)/2) = picture(i, j + 2);

        v(i, (j + 1)/2) = picture(i, j + 3);

        v(i, (j + 3)/2) = picture(i, j + 3);

    end

end

% figure,imshow(y, [ ]);

frame(:, :, 1) = y;

frame(:, :, 2) = u;

frame(:, :, 3) = v;

rgb = ycbcr2rgb(frame);

figure,imshow(rgb);

 

% write 420 file

fid = fopen('test_420.264', 'w' );

if fid == -1

    error('Cannot open file.');

end

for i = 1:ver

    fwrite(fid, y(i,:), 'uint8');

end

for i = 1:2:ver

    for j = 1:2:hor

        fwrite(fid, u(i,j), 'uint8');

        fwrite(fid, v(i,j), 'uint8');

    end

end

fclose(fid);

 

取一幅原始的YUYV422格式的图像来进行处理,其原始图像如下所示。


经过Matlab转换之后的图像效果如下所示。


可以看出,经过该算法转换过后,图像质量变化不大,证明该算法是可行的,可以将其用到视频编码程序中。

1.3  C语言实现颜色空间转换

在视频编码程序中进行图像格式转换时,必须要注意OV5642传过来的数据时10-bit,而不是像TVP5150那样为8-bit。如果是8-bit数据,那么处理比较方便,因为在编码器支持的是8-bit格式,而且DMAI中的Buffer模块也是将像素点数据定义的8-bit模式。所以,在使用C语言对视频缓冲区数据进行格式转换时,需要对指向这些数据的指针进行强制类型转换,将Int8 *型转换为Int16 *型。使用C语言进行格式转换的代码如下所示。

 

Void YUYV10_to_YUV420PSEMI8(Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf)

{

    BufferGfx_Dimensions srcDim;

    BufferGfx_Dimensions dstDim;

    UInt32 srcOffset, dstOffset;

    Int8 *src, *dst_Y, *dst_UV;

Int i, j;

 

    BufferGfx_getDimensions(hSrcBuf, &srcDim);

    BufferGfx_getDimensions(hDstBuf, &dstDim);

 

    src    = Buffer_getUserPtr(hSrcBuf);

    dst_Y  = Buffer_getUserPtr(hDstBuf);

    dst_UV = Buffer_getUserPtr(hDstBuf) + srcDim.width * srcDim.height;

 

    if (dst_Y != src) {

        for (i = 0; i < srcDim.height; i++) {

            if (i % 2 == 1) {

                for (j = 0; j < srcDim.width * 4; j += 8) {

                    *dst_Y = ((*((Int16 *)(src + 0))) / 4) & 0xff;

                    dst_Y ++;

                    *dst_Y = ((*((Int16 *)(src + 4))) / 4) & 0xff;

                    dst_Y ++;

                    *dst_UV = ((*((Int16 *)(src + 2))) / 4) & 0xff;

                    dst_UV ++;

                    *dst_UV = ((*((Int16 *)(src + 6))) / 4) & 0xff;

                    dst_UV ++;

                    src += 8;

                }

            }

            else {

                for (j = 0; j < srcDim.width * 4; j += 8) {

                    *dst_Y = ((*((Int16 *)(src + 0))) / 4) & 0xff;

                    dst_Y ++;

                    *dst_Y = ((*((Int16 *)(src + 4))) / 4) & 0xff;

                    dst_Y ++;

                    src += 8;

                }

            }

        }

    }

    Buffer_setNumBytesUsed(hDstBuf, srcDim.width * srcDim.height * 3 / 2);

}

 

使用该算法进行YUYV422到YUV420PSEMI颜色空间的转换,经过测试表明图像效果良好。