Hi,
I'm trying to use a framebuffer on the i.MX6QP in YUV422P.
Everything works fine when my data starts at the beginning of the buffer (fb_var_screeninfo.yoffset = 0).
I have my Y plane, followed by my Cb and Cr planes with half the width of the Y plane.
However, when I try to use double-buffering with a virtual size bigger than the actual size and a non-zero yoffset, the chroma are incorrect. I would expect to have the whole plane layout shifted by yoffset * xres_virtual bytes.
Where can I find documentation about the memory layout for YUV422P ?
Here is my code:
#include <linux/fb.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <string.h>
#include "ipu.h" // Customized version of <linux/ipu.h>
using namespace std;
int main ()
{
int framebuffer_device;
struct fb_var_screeninfo var_info;
char* buf;
framebuffer_device = open ("/dev/fb2", O_RDWR);
ioctl(framebuffer_device, FBIOGET_VSCREENINFO, &var_info);
var_info.xres = 1920;
var_info.yres = 1080;
var_info.xres_virtual = 3000;
var_info.yres_virtual = 3000;
var_info.activate |= FB_ACTIVATE_FORCE;
var_info.nonstd = IPU_PIX_FMT_YUV422P;
int result = ioctl(framebuffer_device, FBIOPUT_VSCREENINFO, &var_info);
cout << "FBIOPUT_VSCREENINFO: " << result << endl;
//ioctl(framebuffer_device, FBIOBLANK, FB_BLANK_UNBLANK);
buf = (char*)mmap(0, var_info.xres_virtual * var_info.yres_virtual * 2, PROT_READ | PROT_WRITE, MAP_SHARED, framebuffer_device, 0);
if (buf == nullptr)
cout << "mmap failed" << endl;
memset(buf, 0, var_info.xres_virtual * var_info.yres_virtual * 2);
const uint32_t lumaStride = var_info.xres_virtual;
const uint32_t chromaStride = var_info.xres_virtual / 2;
const uint32_t nextImageLineOffset = 1200;
const uint32_t imageStride = var_info.xres_virtual * nextImageLineOffset;
// Even frame - Blue: Y=128, Cb=255, Cr=96
memset(buf, 128, lumaStride * 1080);
memset(buf + lumaStride * 1080, 255, chromaStride * 1080);
memset(buf + (lumaStride + chromaStride) * 1080, 96, chromaStride * 1080);
// Odd frame - Pink: Y=255, Cb=160, Cr=192
memset(buf + imageStride, 255, lumaStride * 1080);
memset(buf + imageStride + lumaStride * 1080, 160, chromaStride * 1080);
memset(buf + imageStride + (lumaStride + chromaStride) * 1080, 192, chromaStride * 1080);
for (int k = 0; k < 100; k++)
{
uint32_t lineOffset = (k % 2) ? nextImageLineOffset : 0;
var_info.yoffset = lineOffset;
ioctl(framebuffer_device, FBIOPAN_DISPLAY, &var_info);
sleep(1);
}
munmap(buf, var_info.xres_virtual * var_info.yres_virtual * 2);
close(framebuffer_device);
return 0;
}