FFMpeg libswscale XBGR32 to NV12 almost working but colors are wrong

372 Views Asked by At

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: enter image description here

Here is the encoded data from the NV12 frame created by libswscale - it should show the same colors as the screen: enter image description here

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);
0

There are 0 best solutions below