通过操作Linux系统下的/dev/video0 USB摄像头设备节点和/dev/fb0 LCD设备节点,将USB摄像头的视频数据显示到LCD上面。
从/dev/video0设备节点通过v4l2框架接口读出的数据是yuyv的,这些数据是不能直接显示在lcd上面的,需要转换成rgb才能显示在lcd上面。
主要参考:https://blog.csdn.net/zhangdaxia2/article/details/72972406?utm_source=blogxgwz0
主要还是使用上面的源代码。
代码编译运行后,视频在LCD上显示有很大的问题。可能有些参数还需要修改。
如下:
其中应该主要就是显示的坐标的确定:
之前代码的LCD像素的显示是:
cnt = x*(varinfo.xres)+y; // LCD像素位置
cnt1 = (x*width+width-y)*3; // 图片像素位置,width-y用于解决图像显示左右反了的问题
*(p+cnt) = (pdata[cnt1]<<0) | (pdata[cnt1+1]<<8) | (pdata[cnt1+2]<<16);
根据自己的LCD的特点修改为如下的形式后,就可以正常的显示了:
for(x=XOFFSET; x<(height + XOFFSET); x++){
for(y=YOFFSET; y<(width + YOFFSET) ; y++){
cnt = y * (varinfo.bits_per_pixel/8) + x * fixinfo.line_length;// LCD像素位置
//cnt1 = (x*width+y)*3; // 图片像素位置,有上下倒置问题
cnt1 = (((height + XOFFSET) - x)*width + (y - YOFFSET))*3;
*(p+cnt) = pdata[cnt1+0];
*(p+cnt+1) = pdata[cnt1+1];
*(p+cnt+2) = pdata[cnt1+2];
*(p+cnt+3) = 0x00;
}
}
其中在操作Framebuffer的地址空间的时候尤其需要注意如果,像素的赋值操作到映射的空间地址之外,就会报出段错误。
出现段错误:
uint* p = (uint *)mmap(0, screen_size, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);
uint location = 0;
location = x * (varinfo.bits_per_pixel/8) + y * fixinfo.line_length;
出现段错误语句:Segmentation fault
当location是1051264多的时候就会在如下的语句报出段错
*(p+location) = 0xFFFFFF;
分析应该是p指针是int*型的,每次偏移一个就是加的4个地址空间,所以location=1051264的时候,其实指针已经偏移到了1051264*4=4205056.超出了开始时mmap映射的地址空间大小screen_size= 4196352。所以会报出段错误。所以讲指针改为char *型,每次偏移就是一个地址空间。就不会超出映射的地址空间范围。
如下形式就不会段错误:
static char* fbmmap;
fbmmap = (char*)mmap(0, screen_size, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);
char* p = fbmmap;
int location = 0;
location = x * (varinfo.bits_per_pixel/8) + y * fixinfo.line_length;
*(p+location) = 0xFF;
完整的代码下载:https://github.com/SkyDreamcode/InfraredTemperatureInstrument-raspberrypi.git
下面是显示rgb不同颜色时的字段:
p: int *
cnt = x*(varinfo.xres)+y;
*(p+cnt) = 0xFF0000; //red
*(p+cnt) = 0x00FF00; //green
*(p+cnt) = 0x0000FF; // blue
*(p+cnt) = 0xFF000000;//black
*(p+cnt) = 0x000000; //black
p:char *
cnt = x * (varinfo.bits_per_pixel/8) + y * fixinfo.line_length;
red:
*(p+cnt) = 0x00;
*(p+cnt+1) = 0x00;
*(p+cnt+2) = 0xFF;
green:
*(p+cnt) = 0x00;
*(p+cnt+1) = 0xFF;
*(p+cnt+2) = 0x00;
*(p+cnt+3) = 0x00;
blue:
*(p+cnt) = 0xFF;
*(p+cnt+1) = 0x00;
*(p+cnt+2) = 0x00;
*(p+cnt+3) = 0x00;
black:
*(p+cnt) = 0x00;
*(p+cnt+1) = 0x00;
*(p+cnt+2) = 0x00;
*(p+cnt+3) = 0xFF;
black:
*(p+cnt) = 0x00;
*(p+cnt+1) = 0x00;
*(p+cnt+2) = 0x00;
*(p+cnt+3) = 0x00;