在将VO和RGN模块调试完成后,接下来就是将程序的QT画面渲染到RGN的模块中了,大致的思路是:
在RGN模块中有个结构体BITMAP_S用于存放图像信息的,其中有个成员变量pData用于存放图像数据,那我们可以通过把QT的图像数据写进该成员变量中,以达到绘制QT_UI的效果。
思路大概是这么个思路,那具体应该怎么实现:
QT端
QT端需要把自身的UI绘制成图像,这里可以使用render函数将UI画到对应的QPainter中,
QImage image((uchar *)pVirtaddr+1, 1920, 1080, QImage::Format_RGBA8888);
QPainter painter(&image);
this->render(&painter,QPoint(this->x(),this->y()));
这样就把该控件的UI画到了QPainter的image上,这样就把UI画到了图像上了。
然后我们需要在图像更新后就调用一次render函数去重画图像,对于图像要如何给到rockit那边的rgn呢?可以用共享内存的方式也可以用rockit的RK_MPI_SYS_MmzAlloc_Cached
申请一块跨进程的缓存。然后通过RK_MPI_MB_Handle2UniqueId
获取该缓存的全局唯一ID,然后再用RK_MPI_MB_UniqueId2Fd
转换成fd文件描述符,然后用mmap
去映射到该内存就行了
MbBlk = MB_INVALID_HANDLE;
s32Ret = RK_SUCCESS;
s32UniqueId = -1;
s32Size = 4 * 1920 * 1080 + 1;
s32Ret = RK_MPI_SYS_MmzAlloc_Cached(&MbBlk, RK_NULL, RK_NULL, s32Size);
if (s32Ret != RK_SUCCESS) {
return ;
}
s32UniqueId = RK_MPI_MB_Handle2UniqueId(MbBlk);
if (s32UniqueId < 0) {
return ;
}
s32DupFd = RK_MPI_MB_UniqueId2Fd(s32UniqueId);
pVirtaddr = mmap64(NULL, s32Size, PROT_READ | PROT_WRITE, MAP_SHARED, s32DupFd, 0);
RK_MPI_SYS_MmzAlloc_Cached
RK_MPI_MB_Handle2UniqueId
RK_MPI_MB_UniqueId2Fd
Rockit端
在rockit端也是一样的,通过RK_MPI_MB_UniqueId2Fd
从唯一ID获取到文件描述符,然后mmap
映射出来,然后在后续将映射出来的地址赋值给pData,然后通过简单的一些rockit提供的读图像数据的sdk就可以获取到QT写进去的图像信息了。
s32DupFd = RK_MPI_MB_UniqueId2Fd(1);
if (s32DupFd < 0) {
return 0;
}
RK_LOGE("RK_MPI_MB_UniqueId2Fd s32DupFd = %d\n",s32DupFd);
pVirtAddr = mmap64(NULL, 4*1920*1080+1, PROT_READ | PROT_WRITE, MAP_SHARED, s32DupFd, 0);
if(pVirtAddr == RK_NULL) {
return 0;
}
stBitmap.pData = (RK_VOID *)((RK_U8 *)pVirtAddr + 1);
这里基本功能就大致实现了,但是有个点需要注意一下,就是在上述代码中我所获取到得地址都是加1后再进行图像数据得存放和读取,为什么要这样呢,因为由于申请的内存是共享的,所以必定会出现同时操作的,这样就会导致读写不同步,使得有时候读出来的图像并不完整,所以在这里我把共享内存的第一个字节作为一个条件变量进行读写的同步,这样就不会出现图像显示不完整的情况了。