zigbee無線感測網實訓---實現LCD開發板連線攝像頭實時顯示(The Fifth day)
阿新 • • 發佈:2019-01-09
攝像頭:
常見的攝像頭:針孔攝像頭(有線和無線)、紅外攝像頭(有線),usb攝像頭;
攝像頭採集影象的格式:yuyv 、jpeg(v4l2)
api_v4l2.h
/************************************************* File name : api_v4l2.h Create date : 2014-07-01 19:42 Modified date : 2014-07-01 19:42 Author : heqingde Email : [email protected] ***********************************************/ #ifndef API_V4L2_H_ #define API_V4L2_H_ #define VIDEO_WIDTH 640 #define VIDEO_HEIGHT 480 #define MAX_CAM_RES 32 //camres res #define BUFFER_COUNT 4 //buffer zone #define FPS 30 #define MAX_CAM_RES 32 //#define CAMERA_DEVICE "/dev/video1" #define exit_error(s)\ do{\ printf("%s is error\n",s);\ return (-1);\ }while(0) /********************************* * NAME:VideoBuffer struct * Function: Describe buffer V4L2 driver assigns and maps * Member: start: point of buffer * length: total length of buffer **********************************/ typedef struct Video_Buffer { void *start; int length; }VideoBuffer; /******************************* * name :fream_buffer * Function: save fream * member: buf :point of buf * length:total length op buf ********************************/ typedef struct Frame_Buffer { char buf[1843200]; int length; }FrameBuffer; /************************************ *name:CamRes *Function:Camera format *Member: width : format width *height: format height */ typedef struct CamRes { int width; int height; }CamRes; /************************************* *name:CamResList struct *Function:CamRes format list *Member: cam_res :struct CamRes *res_num:Camera format number */ typedef struct CamResList { struct CamRes *cam_res; int res_num; }CamResList; /************************************* *Name:open_device Function *Function:open the device */ void linux_v4l2_open_device(); /************************************* *name:device_init *Function:Initial Camera v4l2 */ int linux_v4l2_device_init(const char *dev); /************************************* *name: init_mmap *Function: mmap */ int linux_v4l2_init_mmap(); /************************************ *name:start_capturing *Function: starting Capture Options */ int linux_v4l2_start_capturing(); /************************************ *name:stop_capturing *Function: stop Capture Options */ int linux_v4l2_stop_capturing(); /************************************ *name :device_uinit *Function:uinit device */ int linux_v4l2_device_uinit(); /************************************ *name :linux_v4l2_get_fream *Function:save device_stream data; */ int linux_v4l2_get_fream(FrameBuffer *freambuf); #endif /*API_V4L2_H*/
camera.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #include <pthread.h> #include "lcdjpg.h" #include "api_v4l2.h" //包含攝像頭的標頭檔案 int lcd_draw_jpg(unsigned int x,unsigned int y,const char *pjpg_path,char *pjpg_buf,unsigned int jpg_buf_size,unsigned int jpg_half); int iPhonex; struct sockaddr_in phoneaddr; //執行緒的功能函式,接收來自手機app傳送的控制命令 void *myrecvmsg(void *arg) { char buf[200]; int addrsize=sizeof(phoneaddr); while(1) { bzero(buf,200);//清零 //聊天,收發資料,接收手機發送過來的控制命令 recvfrom(iPhonex,buf,200,0,(struct sockaddr *)&phoneaddr,&addrsize); printf("phone send msg is:%s ip:%s port:%hu\n",buf,inet_ntoa(phoneaddr.sin_addr),ntohs(phoneaddr.sin_port)); } } int main(void) { //買手機--->建立套接字 iPhonex = socket( AF_INET, SOCK_DGRAM,0); // 定義一個ipv4地址結構體變數 struct sockaddr_in bindaddr; bindaddr.sin_family = AF_INET; bindaddr.sin_addr.s_addr = inet_addr("192.168.1.123");//繫結開發板無線網絡卡的ip bindaddr.sin_port = htons(2234); //繫結埠號 //買卡--->繫結自己的ip int ret = bind(iPhonex, (struct sockaddr *)&bindaddr, sizeof(bindaddr)); if(ret == -1) { printf("繫結失敗!\n"); exit(0); } //開啟攝像頭 linux_v4l2_device_init("/dev/video7"); //啟動攝像捕捉 linux_v4l2_start_capturing(); //開始捕捉 //建立執行緒,專門接受手機端傳送過來的資訊 pthread_t p_id; pthread_create( &p_id, NULL, myrecvmsg, NULL); FrameBuffer mybuf; while(1) { linux_v4l2_get_fream(&mybuf); //開發板顯示攝像頭拍攝的畫面 lcd_draw_jpg(0,0,NULL,mybuf.buf,mybuf.length,0); //將畫面傳輸給手機 sendto(iPhonex,mybuf.buf,mybuf.length,0,(struct sockaddr *)&phoneaddr,sizeof(phoneaddr)); printf("phone ip:%s port:%hu\n",inet_ntoa(phoneaddr.sin_addr),ntohs(phoneaddr.sin_port)); //拍照.... } return 0; }
common.c
/**************************************************************************************** *Éè ¼Æ:ÎÂ×Óì÷ *ÈÕ ÆÚ:2015-5-29 *˵ Ã÷:³£Óú¯Êý ****************************************************************************************/ #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <stdlib.h> #include <sys/stat.h> /**************************************************** *º¯ÊýÃû³Æ:file_size_get *ÊäÈë²ÎÊý:pfile_path -Îļþ·¾¶ *·µ »Ø Öµ:-1 -ʧ°Ü ÆäËûÖµ -Îļþ´óС *˵ Ã÷:»ñÈ¡Îļþ´óС ****************************************************/ unsigned long file_size_get(const char *pfile_path) { unsigned long filesize = -1; struct stat statbuff; if(stat(pfile_path, &statbuff) < 0) { return filesize; } else { filesize = statbuff.st_size; } return filesize; } unsigned char bcc_check(unsigned char *buf, int n) { int i; unsigned char bcc=0; for(i = 0; i < n; i++) { bcc ^= *(buf+i); } return (~bcc); }
lcdjpg.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdlib.h>
#include "lcdjpg.h"
#if EN_LCD_SHOW_JPG
#include "jpeglib.h"
#endif
//#include "api_v4l2.h"
unsigned long file_size_get(const char *pfile_path);
static char g_color_buf[FB_SIZE]={0};
static int g_fb_fd;
static int *g_pfb_memory;
/* video_chat.c »ÖлÏÔʾµÄ×ø±ê */
volatile int g_jpg_in_jpg_x;
volatile int g_jpg_in_jpg_y;
//LCD»µã
void lcd_draw_point(unsigned int x,unsigned int y, unsigned int color)
{
*(g_pfb_memory+y*800+x)=color;
}
#if EN_LCD_SHOW_JPG
int lcd_draw_jpg(unsigned int x,unsigned int y,const char *pjpg_path,char *pjpg_buf,unsigned int jpg_buf_size,unsigned int jpg_half)
{
//³õʼ»¯LCD
g_fb_fd = open("/dev/fb0", O_RDWR);
if(g_fb_fd<0)
{
printf("open lcd error\n");
return -1;
}
g_pfb_memory = (int *)mmap( NULL, //Ó³ÉäÇøµÄ¿ªÊ¼µØÖ·£¬ÉèÖÃΪNULLʱ±íʾÓÉϵͳ¾ö¶¨Ó³ÉäÇøµÄÆðʼµØÖ·
FB_SIZE, //Ó³ÉäÇøµÄ³¤¶È
PROT_READ|PROT_WRITE, //ÄÚÈÝ¿ÉÒÔ±»¶ÁÈ¡ºÍдÈë
MAP_SHARED, //¹²ÏíÄÚ´æ
g_fb_fd, //ÓÐЧµÄÎļþÃèÊö´Ê
0 //±»Ó³Éä¶ÔÏóÄÚÈݵÄÆðµã
);
/*¶¨Òå½âÂë¶ÔÏ󣬴íÎó´¦Àí¶ÔÏó*/
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
char *pcolor_buf = g_color_buf;
char *pjpg;
unsigned int i=0;
unsigned int color =0;
unsigned int count =0;
unsigned int x_s = x;
unsigned int x_e ;
unsigned int y_e ;
int jpg_fd;
unsigned int jpg_size;
unsigned int jpg_width;
unsigned int jpg_height;
if(pjpg_path!=NULL)
{
/* ÉêÇëjpg×ÊÔ´£¬È¨Ï޿ɶÁ¿Éд */
jpg_fd=open(pjpg_path,O_RDWR);
if(jpg_fd == -1)
{
printf("open %s error\n",pjpg_path);
return -1;
}
/* »ñÈ¡jpgÎļþµÄ´óС */
jpg_size=file_size_get(pjpg_path);
/* ΪjpgÎļþÉêÇëÄÚ´æ¿Õ¼ä */
pjpg = malloc(jpg_size);
/* ¶ÁÈ¡jpgÎļþËùÓÐÄÚÈݵ½ÄÚ´æ */
read(jpg_fd,pjpg,jpg_size);
}
else
{
jpg_size = jpg_buf_size;
pjpg = pjpg_buf;
}
/*×¢²á³ö´í´¦Àí*/
cinfo.err = jpeg_std_error(&jerr);
/*´´½¨½âÂë*/
jpeg_create_decompress(&cinfo);
/*Ö±½Ó½âÂëÄÚ´æÊý¾Ý*/
jpeg_mem_src(&cinfo,pjpg,jpg_size);
/*¶ÁÎļþÍ·*/
jpeg_read_header(&cinfo, TRUE);
/*¿ªÊ¼½âÂë*/
jpeg_start_decompress(&cinfo);
if(jpg_half)
{
x_e = x_s+(cinfo.output_width/2);
y_e = y +(cinfo.output_height/2);
/*¶Á½âÂëÊý¾Ý*/
while(cinfo.output_scanline < cinfo.output_height)
{
pcolor_buf = g_color_buf;
/* ¶ÁÈ¡jpgÒ»ÐеÄrgbÖµ */
jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
/* ÔÙ¶ÁÈ¡jpgÒ»ÐеÄrgbÖµ */
jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
for(i=0; i<(cinfo.output_width/2); i++)
{
/* »ñÈ¡rgbÖµ */
color = *(pcolor_buf+2);
color = color | *(pcolor_buf+1)<<8;
color = color | *(pcolor_buf)<<16;
/* ÏÔʾÏñËصã */
lcd_draw_point(x,y,color);
pcolor_buf +=6;
x++;
}
/* »»ÐÐ */
y++;
x = x_s;
}
}
else
{
x_e = x_s+cinfo.output_width;
y_e = y +cinfo.output_height;
/*¶Á½âÂëÊý¾Ý*/
while(cinfo.output_scanline < cinfo.output_height )
{
pcolor_buf = g_color_buf;
/* ¶ÁÈ¡jpgÒ»ÐеÄrgbÖµ */
jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
for(i=0; i<cinfo.output_width; i++)
{
/* »ñÈ¡rgbÖµ */
color = *(pcolor_buf+2);
color = color | *(pcolor_buf+1)<<8;
color = color | *(pcolor_buf)<<16;
/* ÏÔʾÏñËصã */
lcd_draw_point(x,y,color);
pcolor_buf +=3;
x++;
}
/* »»ÐÐ */
y++;
x = x_s;
}
}
/*½âÂëÍê³É*/
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
if(pjpg_path!=NULL)
{
/* ¹Ø±ÕjpgÎļþ */
close(jpg_fd);
/* ÊÍ·ÅjpgÎļþÄÚ´æ¿Õ¼ä */
free(pjpg);
}
//LCD¹Ø±Õ
/* È¡ÏûÄÚ´æÓ³Éä */
munmap(g_pfb_memory, FB_SIZE);
/* ¹Ø±ÕLCDÉ豸 */
close(g_fb_fd);
return 0;
}
#endif
lcdjpg.h
#ifndef __LCD_H__
#define __LCD_H__
#define LCD_WIDTH 800
#define LCD_HEIGHT 480
#define FB_SIZE (LCD_WIDTH * LCD_HEIGHT * 4)
#define EN_LCD_SHOW_JPG 1
/* video_chat.c 畫中畫顯示的座標 */
extern volatile int g_jpg_in_jpg_x;
extern volatile int g_jpg_in_jpg_y;
#endif
編譯:
虛擬機器:
arm-none-linux-gnueabi-gcc *.c -o main -I/home/gec/jpeg/include -L./ -lapi_v4l2_arm -lpthread -L/home/gec/jpeg/lib -ljpeg
//*號表示萬用字元
//-I --> 指明標頭檔案的路徑
//-L --> 指明庫檔案的路徑
//-l --> 指定要連線的庫名(去掉字首lib 去掉字尾.** 剩下的就是庫的名字)
LCD開發板:
$:tftp -g 192.168.1.147 -r main
$:chmod 777 main
$:./main
結果: