Я пытаюсь преобразовать кадр 3-канального упакованного rgb в nv12, используя библиотеку nvidia npp. Вот код, который у меня есть:
//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);
}
Его в основном основано на этот вопрос переполнения стека, но я подстроил его под свой случай. Как примечание стороны, frameToWrite.getSize()
рассчитывается так:
mFrameSize = ((getBytesPerPixel() * mWidth) + mPaddingInBytes) * mHeight;
где getBytesPerPixel()
обычно возвращается 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);
Кроме того, размер шага должен быть равен длине строки в байтах плюс заполнение в соответствии с пунктом 4.2.1 документации АЭС.
Что касается извлечения изображения из памяти, из моего личного опыта самый простой способ сделать это просто с помощью cudaMemcpy
Так как npp выделяет 2D память только с виртуальным разделением, в то время как исходные данные все еще выровнены, следовательно, 1D cudaMemcpy
вызова достаточно, чтобы получить данные обратно.