通過操作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;