I am getting a Linx DMA-BUF from the GPU in XBGR32 format and I need to use FFMpeg's libswscale to convert it on the ARM to NV12.
I've been able to almost get it working based on various SO posts and the documentation.
Here is the LCD screen that is the actual output of the GPU:
Here is the encoded data from the NV12 frame created by libswscale - it should show the same colors as the screen:
Please note that the pictures were not taken at exactly the same time.
What am I doing wrong?
Here is the relevant part of my code:
/* Prepare to mmap the GBM BO */
union gbm_bo_handle handleUnion = gbm_bo_get_handle(bo);
struct drm_omap_gem_info req;
req.handle = handleUnion.s32;
ret = drmCommandWriteRead(m_DRMController.fd, DRM_OMAP_GEM_INFO,&req, sizeof(req));
if (ret) {
qDebug() << "drmCommandWriteRead(): Cannot set write/read";
}
// Perform actual memory mapping of GPU output
gpuMmapFrame = (char *)mmap(0, req.size, PROT_READ | PROT_WRITE, MAP_SHARED,m_DRMController.fd, req.offset);
assert(gpuMmapFrame != MAP_FAILED);
// Use ffmpeg to do the SW BGR32 to NV12
static SwsContext *swsCtx = NULL;
int width = RNDTO2( convertWidth );
int height = RNDTO2( convertHeight );
int ystride = RNDTO32 ( width );
int uvstride = RNDTO32 ( width / 2 );
int uvsize = uvstride * ( height / 2 );
void *plane[] = { y, u, u + uvsize, 0 };
int stride[] = { ystride, uvstride, uvstride, 0 };
// Output of GPU is XBGR32
// #define V4L2_PIX_FMT_XBGR32 v4l2_fourcc('X', 'R', '2', '4') /* 32 BGRX-8-8-8-8 */
swsCtx = sws_getCachedContext( swsCtx, convertWidth, convertHeight, AV_PIX_FMT_BGR32, width, height, AV_PIX_FMT_NV12,
SWS_FAST_BILINEAR , NULL, NULL, NULL );
int linesize[1] = { convertWidth * 4 };
const uint8_t *inData[1] = { (uint8_t*)gpuMmapFrame };
if ( gpuMmapFrame ) {
sws_scale( swsCtx, (const uint8_t *const *)inData, linesize, 0, convertHeight, (uint8_t *const *)plane, stride );
}
// Unmap it
munmap(gpuMmapFrame,req.size);
// Now send the frame to the encoder
dce.submitFrameToEncode(swEncodeBufferNV12);