如何使用IPP将RGB转换为NV12色彩空间

时间:2016-06-11 21:41:16

标签: c rgb yuv intel-ipp

像英特尔®MediaSDK这样的视频编码器需要NV12视频输入格式。

NV12 format是YUV 4:2:0格式,在内存中首先排列Y平面,然后是交错UV平面中的打包色度样本。

例:
YYYYYY
YYYYYY
UVUVUV

enter image description here

RGB颜色格式,指像素级RGB(每像素字节,低字节为红色):
RGBRGBRGBRGBRGB
RGBRGBRGBRGBRGB

enter image description here

我做了一些网络研究,发现对于NV12,YUV被定义为YCbCr颜色空间。 目前至少有两种可能的YCbCr格式适用于NV12:

我的问题是:IPP函数将RGB色彩空间转换为NV12吗?

1 个答案:

答案 0 :(得分:10)

我发现IPP功能存在:

ippiRGBToYCbCr420_8u_C3P2R

很难找到,因为功能名称或描述没有提到NV12 该功能使用BT.601标准。

以下是 BT.601 标准中 RGB 转换为 NV12 的代码示例:

void Rgb2NV12(const unsigned char I[], int image_width, int image_height, unsigned char J[])
{
    IppStatus ipp_status;
    int srcStep = image_width*3;
    int dstYStep = image_width;
    int dstCbCrStep = image_width;
    IppiSize roiSize = {image_width, image_height};

    const Ipp8u* pSrc = (Ipp8u*)I;

    Ipp8u *pDstY    = (Ipp8u*)J;                            //Y color plane is the first image_width*image_height pixels of J.
    Ipp8u *pDstCbCr = (Ipp8u*)&J[image_width*image_height]; //In NV12 format, UV plane starts below Y.

    ipp_status = ippiRGBToYCbCr420_8u_C3P2R(pSrc, srcStep, pDstY, dstYStep, pDstCbCr, dstCbCrStep, roiSize);

    //if (ipp_status != ippStsNoErr), Handle errors...          
}

使用BT.709标准将RGB转换为NV12:

至于2019年,BT.709(HDTV)标准可能比BT.601(SDTV)更具相关性。

IPP缺乏在BT.709标准中从RGB直接转换为NV12的功能 有一项功能可将 BGR 转换为 NV12 该解决方案包括两个阶段:

  1. RGB 转换为 BGR (交换渠道) 代码示例使用ippiSwapChannels_8u_C3R进行 RGB BGR 转换。
  2. BGR 转换为 NV12 代码示例使用ippiBGRToYCbCr420_709CSC_8u_C3P2R BGR 转换为 NV12
  3. 示例函数需要一些额外的内存空间来存储中间BGR图像 指向草图存储器的指针被传递给函数(存储器应该在函数外部分配)。

    以下是 BT.709 标准中 RGB 转换为 NV12 的代码示例:

    //sketch_buff - Temporary buffer for storing image in BGR format.
    //              Size of sketch_buff must be at least image_width*image_height*3 bytes.
    void Rgb2NV12_709(const unsigned char I[],
                      const int image_width, 
                      const int image_height,
                      unsigned char sketch_buff[],
                      unsigned char J[])
    {
        IppStatus ipp_status;    
        int srcStep = image_width*3;
        int dstBgrStep = image_width*3;
        int dstYStep = image_width;
        int dstCbCrStep = image_width;
        IppiSize roiSize = {image_width, image_height};
    
        const Ipp8u* pRGB = (Ipp8u*)I;
        Ipp8u* pBGR = (Ipp8u*)sketch_buff; //BGR image is stored in sketch_buff
        Ipp8u *pDstY    = (Ipp8u*)J;                            //Y color plane is the first image_width*image_height pixels of J.
        Ipp8u *pDstCbCr = (Ipp8u*)&J[image_width*image_height]; //In NV12 format, UV plane starts below Y.
    
        const int bgrOrder[3] = {2, 1, 0};
    
        //Swap Red and Blue color channels - convert from RGB to BGR
        //Store the result into sketch_buff (sketch buffer is allocated outside the function)
        ipp_status = ippiSwapChannels_8u_C3R(pRGB, srcStep, pBGR, dstBgrStep, roiSize, bgrOrder);
    
        //if (ipp_status != ippStsNoErr), Handle errors...
    
        //Convert BGR to NV12 in BT.709 standard
        ipp_status = ippiBGRToYCbCr420_709CSC_8u_C3P2R(pBGR, srcStep, pDstY, dstYStep, pDstCbCr, dstCbCrStep, roiSize);
    
        //if (ipp_status != ippStsNoErr), Handle errors...
    }