樹莓派中將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上顯示有很大的問題。可能有些參數還需要修改。

如下:

其中應該主要就是顯示的座標的確定:

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章