Nppi颜色转换问题

时间:2015-07-24 20:22:46

标签: c++ npp

我正在尝试使用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()通常会返回3

最终我的问题是:

  • 如何从设备内存中检索转换后的图像数据?
  • 我是否以正确的方式将未转换的图像数据传递给设备?

1 个答案:

答案 0 :(得分:0)

Npp8u* converted_data = (Npp8u*)malloc(frameToWrite.getWidth());
memset(converted_data, 0, frameToWrite.getSize());

首先,如果您还没有注意到,那么您可能在这里分配了很少的内存,然后在更大的区域使用memset,这可能会导致不必要的行为。

关于你的问题:
很难说你的frameToWrite.getWidth()frameToWrite.getHeight()返回什么 - 是图像尺寸还是字节尺寸?通常,在分配NPP缓冲区时,应使用字节维数,如下所示:
nppiMalloc_8u_C1(pixelWidth*bytesPerPixel, pixelHeight, &stepSource);
另外,根据NPP文档要点4.2.1,步长应等于行长(以字节为单位)加填充。
至于从内存中检索图像,从我的个人经验来看,最简单的方法就是使用cudaMemcpy因为npp只分配2D内存,而原始数据仍然存在,所以sinle 1D {{1调用足以获取数据。