树莓派中将usb摄像头的数据通过Framebuffer显示到LCD屏上

通过操作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上显示有很大的问题。可能有些参数还需要修改。

如下:

树莓派中将usb摄像头的数据通过Framebuffer显示到LCD屏上_第1张图片

树莓派中将usb摄像头的数据通过Framebuffer显示到LCD屏上_第2张图片

其中应该主要就是显示的坐标的确定:

之前代码的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;

 树莓派中将usb摄像头的数据通过Framebuffer显示到LCD屏上_第3张图片

 完整的代码下载: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;

 

你可能感兴趣的:(camera,v4l2,显示,framebuffer,linux)