Camera[2] ioctl访问摄像头驱动

Posted we1less

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Camera[2] ioctl访问摄像头驱动相关的知识,希望对你有一定的参考价值。

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <string.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>


struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_requestbuffers req_buf;
struct v4l2_buffer kbuf;
enum v4l2_buf_type buf_type;
int i;
struct video_buffer{
	void * start;
	int length;
};
struct video_buffer *buffer;

int open_camera(void)
{
	int fd;
	fd = open("/dev/video0",O_RDWR);
	if(fd < 0){
		perror("open /dev/video0 is fail");
		return -1;
	}
	return fd;
}

int check_device(int fd)
{
	if(ioctl(fd,VIDIOC_QUERYCAP,&cap) == -1){
		perror("query device is fail");
		return -1;
	}
	if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)){
		return -1;
	}

	return 0;
}

int set_camera_fmt(int fd)
{
	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    //分辨率
	fmt.fmt.pix.width = 720;
	fmt.fmt.pix.height = 576;
	fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
	fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;

	if(ioctl(fd,VIDIOC_S_FMT,&fmt) == -1){
		perror("set camera fmt is fail");
		return -1;
	}
	
	return 0;
}

int init_buffer(int fd)
{
	//1.分配缓冲区   这里如果数据量大 可以多开点
	req_buf.count = 4;
	req_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	req_buf.memory = V4L2_MEMORY_MMAP;
	
	if(ioctl(fd,VIDIOC_REQBUFS,&req_buf) == -1){
		perror("set VIDIOC_REQBUFS is fail");
		return -1;
	}
	
	buffer = calloc(req_buf.count,sizeof(*buffer));
	for(i=0; i<req_buf.count; i++){
		kbuf.index = i;
		kbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		kbuf.memory = V4L2_MEMORY_MMAP;
		if(ioctl(fd,VIDIOC_QUERYBUF,&kbuf) == -1){
			perror("set VIDIOC_QUERYBUF is fail");
			return -1;
		}
		buffer[i].length = kbuf.length;
		buffer[i].start = mmap(NULL,kbuf.length,  PROT_READ| PROT_WRITE, MAP_SHARED,fd,kbuf.m.offset);

		if(ioctl(fd,VIDIOC_QBUF,&kbuf) == -1){
			perror("set VIDIOC_QBUF is fail");
			return -1;
		}
	
	}
	return 0;
}

int start_camera(int fd)
{
	buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if(ioctl(fd,VIDIOC_STREAMON,&buf_type) == -1){
		perror("set VIDIOC_STREAMON is fail");
		return -1;
	}
	return 0;

}

int stop_camera(int fd)
{
	buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if(ioctl(fd,VIDIOC_STREAMOFF,&buf_type) == -1){
		perror("set VIDIOC_STREAMON is fail");
		return -1;
	}
	return 0;

}


int build_picture(int fd)
{
	FILE * fp;
	memset(&kbuf,0,sizeof(kbuf));
	kbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if(ioctl(fd,VIDIOC_DQBUF,&kbuf) == -1){
		perror("set VIDIOC_DQBUF is fail");
		return -1;
	}

	fp = fopen("picture.yuv","w");
	fwrite(buffer[kbuf.index].start,1,buffer[kbuf.index].length,fp);
	fclose(fp);

	if(ioctl(fd,VIDIOC_QBUF,&kbuf) == -1){
			perror("set VIDIOC_QBUF is fail");
			return -1;
	}
	return 0;
}

int camera_read_data(int fd)
{
	int ret;
	fd_set rfds;
	struct timeval tim;
	tim.tv_sec = 2;
	tim.tv_usec = 0;

	FD_ZERO(&rfds);
	FD_SET(fd, &rfds);
	ret = select(fd+1, &rfds,NULL,NULL, &tim);
	if(ret == -1){
		perror("select is fail");
		return -1;
	}else if(ret == 0){
		perror("select timeout");
		return -1;
	}else{
		build_picture(fd);
	}
	return 0;
}

int data_free(int fd)
{
	for(i=0; i<4; i++){
		munmap(buffer[i].start,buffer[i].length);
	}
	free(buffer);
	close(fd);
}

int main(int argc, const char *argv[])
{
	int fd,ret;
	//1.打开驱动
	fd = open_camera();
	if(fd == -1){
		return -1;
	}

	//2.查询是否是一个摄像头设备
	ret = check_device(fd);
	if(ret == -1){
		return -1;
	}

	//3.设置图像采集的格式
	ret = set_camera_fmt(fd);
	if(ret != 0){
		return -1;
	}

	//4.缓冲区的操作
	init_buffer(fd);
	
	//5.开始采集数据
	start_camera(fd);

	//6.读取数据
	camera_read_data(fd);

	//7.停止采集
	stop_camera(fd);
	//8.释放缓冲区
	data_free(fd);

	return 0;
}

以上是关于Camera[2] ioctl访问摄像头驱动的主要内容,如果未能解决你的问题,请参考以下文章

camera驱动

v4l2编程 关于linux中无驱动摄像头无法驱动问题 会的话麻烦你看一下 万分感谢

camera驱动

android camera:camera 驱动 GT2005

Camera基础摄像头驱动原理和开发&&V4L2子系统驱动架构

android摄像头(camera)之 v4l2的c测试代码