zigbee无线传感网实训---实现LCD开发板连接摄像头实时显示(The Fifth day)

承接实训第四天:zigbee无线传感网实训---在LCD屏上显示JPG图片、 触摸屏、相册(The fourth day)

摄像头:
        常见的摄像头:针孔摄像头(有线和无线)、红外摄像头(有线),usb摄像头;
        摄像头采集图像的格式:yuyv 、jpeg(v4l2)

文件准备:libapi_v4l2_arm.so

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

结果:

注:实训第六天将完成开发板WiFi:zigbee无线传感网实训---完成开发板WiFi(The Sixth day)

猜你喜欢

转载自blog.csdn.net/myclass1312/article/details/82591598