如何使用 IPP 将 RGB 转换为 NV12 颜色 space
How to convert RGB to NV12 color space using IPP
英特尔® 媒体 SDK 等视频编码器需要 NV12 视频输入格式。
NV12 format 是在内存中排序的 YUV 4:2:0 格式,首先是 Y 平面,然后是交错 UV 平面中的打包色度样本。
示例:
YYYYYY
YYYYYY
UVUVUV
RGB颜色格式,指Pixel-Order RGB(byte per pixel,低字节为Red):
RGBRGBRGBRGBRGB
RGBRGBRGBRGBRGB
我做了一些网络研究,发现关于 NV12,YUV 被定义为 YCbCr 颜色 space。
目前至少有 2 种可能的 YCbCr 格式适用于 NV12:
我的问题是:是否有IPP函数将RGB颜色space转换为NV12?
我发现IPP功能存在:
很难找到,因为功能名称或描述没有提到 NV12。
该功能使用BT.601标准。
这是一个代码示例,用于将 RGB 转换为 NV12 BT.601 标准:
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.
该解决方案包括两个阶段:
- 从 RGB 转换为 BGR(交换频道)。
代码示例使用 ippiSwapChannels_8u_C3R
进行 RGB 到 BGR 的转换。
- 从 BGR 转换为 NV12。
代码示例使用 ippiBGRToYCbCr420_709CSC_8u_C3P2R
进行 BGR 到 NV12 的转换。
示例函数需要一些额外的内存 space 来存储中间 BGR 图像。
指向草图内存的指针被传递给函数(内存应该在函数外部分配)。
这是一个代码示例,用于将 RGB 转换为 NV12 BT.709 标准:
//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...
}
英特尔® 媒体 SDK 等视频编码器需要 NV12 视频输入格式。
NV12 format 是在内存中排序的 YUV 4:2:0 格式,首先是 Y 平面,然后是交错 UV 平面中的打包色度样本。
示例:
YYYYYY
YYYYYY
UVUVUV
RGB颜色格式,指Pixel-Order RGB(byte per pixel,低字节为Red):
RGBRGBRGBRGBRGB
RGBRGBRGBRGBRGB
我做了一些网络研究,发现关于 NV12,YUV 被定义为 YCbCr 颜色 space。 目前至少有 2 种可能的 YCbCr 格式适用于 NV12:
我的问题是:是否有IPP函数将RGB颜色space转换为NV12?
我发现IPP功能存在:
很难找到,因为功能名称或描述没有提到 NV12。
该功能使用BT.601标准。
这是一个代码示例,用于将 RGB 转换为 NV12 BT.601 标准:
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.
该解决方案包括两个阶段:
- 从 RGB 转换为 BGR(交换频道)。
代码示例使用ippiSwapChannels_8u_C3R
进行 RGB 到 BGR 的转换。 - 从 BGR 转换为 NV12。
代码示例使用ippiBGRToYCbCr420_709CSC_8u_C3P2R
进行 BGR 到 NV12 的转换。
示例函数需要一些额外的内存 space 来存储中间 BGR 图像。
指向草图内存的指针被传递给函数(内存应该在函数外部分配)。
这是一个代码示例,用于将 RGB 转换为 NV12 BT.709 标准:
//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...
}