1. 程式人生 > >C語言高階應用---操作linux下V4L2攝像頭應用程式

C語言高階應用---操作linux下V4L2攝像頭應用程式

#include "CameralOpt.h"
int video_fd ; 
int length ; 
char *yuv[COUNT] ; 
struct v4l2_buffer  enqueue  , dequeue ;  //定義出入隊的操作結構體成員

int Init_Cameral(int Width , int Hight)
{
	//引數檢查
	char *videodevname = NULL ; 
	videodevname = "/dev/video0" ; 
	
	//開啟裝置
	video_fd = open(videodevname , O_RDWR);
	if(-1 == video_fd )
	{
		perror("open video device fail");
		return -1 ; 
	}

	int i ; 
	int ret ; 
	struct v4l2_format  format ; 
	format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
	format.fmt.pix.width  = Width; 
	format.fmt.pix.height = Hight; 
	format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV ;  //我支援的格式是這個

	ret = ioctl(video_fd , VIDIOC_S_FMT , &format);
	if(ret != 0)
	{
		perror("set video format fail");
		return -2 ; 
	}


	//申請buffer,切割成幾個部分
	//3
	struct v4l2_requestbuffers  requestbuffer ; 
	requestbuffer.count = COUNT ; 
	requestbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
	requestbuffer.memory = V4L2_MEMORY_MMAP ; 

	ret = ioctl(video_fd , VIDIOC_REQBUFS , &requestbuffer);
	if(ret != 0)
	{
		perror("request buffer fail ");
		return -3  ;
	}
	
	
	//querybuffer
	struct v4l2_buffer querybuffer ; 
	querybuffer.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
	querybuffer.memory = V4L2_MEMORY_MMAP ; 

	for(i = 0 ; i < COUNT ; i++)
	{
		querybuffer.index = i ; 	

		ret = ioctl(video_fd , VIDIOC_QUERYBUF , &querybuffer);
		if(ret != 0)
		{
			perror("query buffer fail");
			return -4 ; 
		}
	
//		printf("index:%d length:%d  offset:%d \n" , 
//		querybuffer.index , querybuffer.length , querybuffer.m.offset);
		length = querybuffer.length ; 

		//將攝像頭記憶體印射到程序的記憶體地址
		yuv[i] = mmap(0,querybuffer.length , PROT_READ | PROT_WRITE , MAP_SHARED , video_fd , querybuffer.m.offset );


		//列隊
		
		struct v4l2_buffer  queuebuffer ; 
		queuebuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
		queuebuffer.memory =  V4L2_MEMORY_MMAP ; 
		queuebuffer.index = i ; 	

		ret = ioctl(video_fd , VIDIOC_QBUF , &queuebuffer);
		if(ret != 0)
		{
			perror("queuebuffer fail");
			return -5 ; 
		}
	}
	//初始化入隊出隊
	enqueue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
	dequeue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 
	enqueue.memory = V4L2_MEMORY_MMAP ; 
	dequeue.memory = V4L2_MEMORY_MMAP ; 

	return 0 ; 
}

int Exit_Cameral(void)
{
	int i ; 
	for(i = 0 ; i < COUNT ; i++)
		munmap(yuv+i , length);
	close(video_fd);
	return 0 ; 
}

int Start_Cameral(void)
{
	//開啟攝像頭
	int ret ; 
	int on = 1 ; 
	ret = ioctl(video_fd , VIDIOC_STREAMON , &on);
	if(ret != 0)
	{
		perror("start Cameral fail");
		return -1 ; 
	}
	return 0 ; 
}
int Stop_Cameral(void)
{
	//停止攝像頭
	int ret ; 
	int off= 1 ; 
	ret = ioctl(video_fd , VIDIOC_STREAMOFF, &off);
	if(ret != 0)
	{
		perror("stop Cameral fail");
		return -1 ; 
	}
	return 0 ;
}

int Get_Picture(char *buffer)
{
	int ret ; 
	//出隊
	ret = ioctl(video_fd , VIDIOC_DQBUF , &dequeue);
	if(ret != 0)
	{
		perror("dequeue fail");
		return -1 ; 
	}

	//獲取圖片資料 YUV   yuv[dequeue.index]
	memcpy(buffer , yuv[dequeue.index] , dequeue.length);
//	write(yuyv_fd , yuv[dequeue.index] , dequeue.length);

	enqueue.index = dequeue.index ; 
	ret = ioctl(video_fd , VIDIOC_QBUF , &enqueue);
	if(ret != 0)
	{
		perror("enqueue fail");
		return -2 ; 
	}
	return 0 ; 
}



執行結果:樓主本人大笑大笑,長得醜別噴。大哭