Nppi 颜色转换问题
Nppi Color Conversion Issue
我正在尝试使用 Nvidia 的 npp 库将 3 通道打包 rgb 帧转换为 nv12。这是我到目前为止的代码:
//cpu buffer that will hold converted data
Npp8u* converted_data = (Npp8u*)malloc(frameToWrite.getWidth());
memset(converted_data, 0, frameToWrite.getSize());
//Begin - load data and convert rgb to yuv
{
NppStatus ret = NPP_SUCCESS;
int stepSource;
Npp8u* frame = nppiMalloc_8u_C3(frameToWrite.getWidth(), frameToWrite.getHeight(), &stepSource);
cudaMemcpy2D(frame, stepSource, frameToWrite.getFrame(), frameToWrite.getSizePerRow(), frameToWrite.getWidth(), frameToWrite.getHeight(), cudaMemcpyHostToDevice);
int stepDestP1, stepDestP2, stepDestP3;
Npp8u* m_stYuvP1 = nppiMalloc_8u_C1(frameToWrite.getWidth(), frameToWrite.getHeight(), &stepDestP1);
Npp8u* m_stYuvP2 = nppiMalloc_8u_C1(frameToWrite.getWidth(), frameToWrite.getHeight(), &stepDestP2);
Npp8u* m_stYuvP3 = nppiMalloc_8u_C1(frameToWrite.getWidth(), frameToWrite.getHeight(), &stepDestP3);
int d_steps[3] = { stepDestP1, stepDestP2, stepDestP3 };
Npp8u* d_ptrs[3] = { m_stYuvP1, m_stYuvP2, m_stYuvP3 };
NppiSize ROI = { frameToWrite.getWidth(), frameToWrite.getHeight() };
if ((ret = nppiRGBToYUV_8u_C3P3R(frame, stepSource, d_ptrs, stepDestP1, ROI)) != NPP_SUCCESS)
return ERROR_CODE_NVENC_ERROR_UNKNOWN;
cudaMemcpy2D(converted_data, frameToWrite.getWidth(), m_stYuvP1, stepDestP1, frameToWrite.getWidth(), frameToWrite.getHeight(), cudaMemcpyDeviceToHost);
}
它主要基于 this 堆栈溢出问题,但我对其进行了调整以适合我的情况。作为旁注,frameToWrite.getSize()
是这样计算的:
mFrameSize = ((getBytesPerPixel() * mWidth) + mPaddingInBytes) * mHeight;
其中 getBytesPerPixel()
通常 returns 3
.
最终我的问题是:
- 我应该如何从设备内存中检索转换后的图像数据?
- 我是否以正确的方式将未转换的图像数据传递给设备?
Npp8u* converted_data = (Npp8u*)malloc(frameToWrite.getWidth());
memset(converted_data, 0, frameToWrite.getSize());
首先,如果您还没有注意到,您可能在这里分配了很少的内存,然后在更大的区域上使用 memset,这可能会导致不需要的行为。
关于您的问题:
很难说你的 frameToWrite.getWidth()
和 frameToWrite.getHeight()
return 是什么 - 它是图像尺寸还是字节尺寸?通常,当您分配 NPP 缓冲区时,您应该像这样使用字节维度:
nppiMalloc_8u_C1(pixelWidth*bytesPerPixel, pixelHeight, &stepSource);
此外,根据 NPP 文档第 4.2.1 点,步长应等于以字节为单位的行长度加上填充。
至于从内存中检索图像,根据我的个人经验,最简单的方法就是简单地使用 cudaMemcpy
因为 npp 仅使用虚拟分割分配 2D 内存,而原始数据仍然排列,因此 sinle 1D cudaMemcpy
调用足以取回数据。
我正在尝试使用 Nvidia 的 npp 库将 3 通道打包 rgb 帧转换为 nv12。这是我到目前为止的代码:
//cpu buffer that will hold converted data
Npp8u* converted_data = (Npp8u*)malloc(frameToWrite.getWidth());
memset(converted_data, 0, frameToWrite.getSize());
//Begin - load data and convert rgb to yuv
{
NppStatus ret = NPP_SUCCESS;
int stepSource;
Npp8u* frame = nppiMalloc_8u_C3(frameToWrite.getWidth(), frameToWrite.getHeight(), &stepSource);
cudaMemcpy2D(frame, stepSource, frameToWrite.getFrame(), frameToWrite.getSizePerRow(), frameToWrite.getWidth(), frameToWrite.getHeight(), cudaMemcpyHostToDevice);
int stepDestP1, stepDestP2, stepDestP3;
Npp8u* m_stYuvP1 = nppiMalloc_8u_C1(frameToWrite.getWidth(), frameToWrite.getHeight(), &stepDestP1);
Npp8u* m_stYuvP2 = nppiMalloc_8u_C1(frameToWrite.getWidth(), frameToWrite.getHeight(), &stepDestP2);
Npp8u* m_stYuvP3 = nppiMalloc_8u_C1(frameToWrite.getWidth(), frameToWrite.getHeight(), &stepDestP3);
int d_steps[3] = { stepDestP1, stepDestP2, stepDestP3 };
Npp8u* d_ptrs[3] = { m_stYuvP1, m_stYuvP2, m_stYuvP3 };
NppiSize ROI = { frameToWrite.getWidth(), frameToWrite.getHeight() };
if ((ret = nppiRGBToYUV_8u_C3P3R(frame, stepSource, d_ptrs, stepDestP1, ROI)) != NPP_SUCCESS)
return ERROR_CODE_NVENC_ERROR_UNKNOWN;
cudaMemcpy2D(converted_data, frameToWrite.getWidth(), m_stYuvP1, stepDestP1, frameToWrite.getWidth(), frameToWrite.getHeight(), cudaMemcpyDeviceToHost);
}
它主要基于 this 堆栈溢出问题,但我对其进行了调整以适合我的情况。作为旁注,frameToWrite.getSize()
是这样计算的:
mFrameSize = ((getBytesPerPixel() * mWidth) + mPaddingInBytes) * mHeight;
其中 getBytesPerPixel()
通常 returns 3
.
最终我的问题是:
- 我应该如何从设备内存中检索转换后的图像数据?
- 我是否以正确的方式将未转换的图像数据传递给设备?
Npp8u* converted_data = (Npp8u*)malloc(frameToWrite.getWidth());
memset(converted_data, 0, frameToWrite.getSize());
首先,如果您还没有注意到,您可能在这里分配了很少的内存,然后在更大的区域上使用 memset,这可能会导致不需要的行为。
关于您的问题:
很难说你的 frameToWrite.getWidth()
和 frameToWrite.getHeight()
return 是什么 - 它是图像尺寸还是字节尺寸?通常,当您分配 NPP 缓冲区时,您应该像这样使用字节维度:
nppiMalloc_8u_C1(pixelWidth*bytesPerPixel, pixelHeight, &stepSource);
此外,根据 NPP 文档第 4.2.1 点,步长应等于以字节为单位的行长度加上填充。
至于从内存中检索图像,根据我的个人经验,最简单的方法就是简单地使用 cudaMemcpy
因为 npp 仅使用虚拟分割分配 2D 内存,而原始数据仍然排列,因此 sinle 1D cudaMemcpy
调用足以取回数据。