V4L2编程步骤

来源:互联网 发布:淘宝返利用什么 编辑:程序博客网 时间:2024/06/10 01:34

1.定义结构体描述摄像头

struct camera {char *device_name;//摄像头名字int fd;//句柄int width;int height;int display_depth;int image_size;//一帧图像大小int frame_number;struct v4l2_capability v4l2_cap;//struct v4l2_cropcap v4l2_cropcap;//设置摄像头的捕捉能力struct v4l2_format v4l2_fmt;struct v4l2_crop crop;//窗口取景参数struct buffer *buffers;};

2.设置摄像头参数

具体情况具体设置

 cam->display_depth = 5; /* RGB24 */

3.摄像头参数设置

3.1打开摄像头

void open_camera(struct camera *cam) {    struct stat st;    if (-1 == stat(cam->device_name, &st)) {        fprintf(stderr, "Cannot identify '%s': %d, %s\n", cam->device_name,                errno, strerror(errno));        exit(EXIT_FAILURE);    }    if (!S_ISCHR(st.st_mode)) {        fprintf(stderr, "%s is no device\n", cam->device_name);        exit(EXIT_FAILURE);    }    cam->fd = open(cam->device_name, O_RDWR, 0); //  | O_NONBLOCK    if (-1 == cam->fd) {        fprintf(stderr, "Cannot open '%s': %d, %s\n", cam->device_name, errno,                strerror(errno));        exit(EXIT_FAILURE);    }}

3.2摄像属性、格式等。

void init_camera(struct camera *cam) {struct v4l2_capability *cap = &(cam->v4l2_cap);//查询摄像头属性struct v4l2_cropcap *cropcap = &(cam->v4l2_cropcap);//设置摄像头的捕捉能力struct v4l2_crop *crop = &(cam->crop);//设置取景参数struct v4l2_format *fmt = &(cam->v4l2_fmt);//设置视频输出格式unsigned int min;if (-1 == xioctl(cam->fd, VIDIOC_QUERYCAP, cap)) {if (EINVAL == errno) {fprintf(stderr, "%s is no V4L2 device\n", cam->device_name);exit(EXIT_FAILURE);} else {errno_exit("VIDIOC_QUERYCAP");}}if (!(cap->capabilities & V4L2_CAP_VIDEO_CAPTURE)) {fprintf(stderr, "%s is no video capture device\n", cam->device_name);exit(EXIT_FAILURE);}if (!(cap->capabilities & V4L2_CAP_STREAMING)) {fprintf(stderr, "%s does not support streaming i/o\n",cam->device_name);exit(EXIT_FAILURE);}printf("\nVIDOOC_QUERYCAP\n");printf("the camera driver is %s\n", cap->driver);printf("the camera card is %s\n", cap->card);printf("the camera bus info is %s\n", cap->bus_info);printf("the version is %d\n", cap->version);/* Select video input, video standard and tune here. */CLEAR(*cropcap);cropcap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;crop->c.width = cam->width;crop->c.height = cam->height;crop->c.left = 0;crop->c.top = 0;crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;CLEAR(*fmt);fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;fmt->fmt.pix.width = cam->width;fmt->fmt.pix.height = cam->height;fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; //yuv422fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; //隔行扫描if (-1 == xioctl(cam->fd, VIDIOC_S_FMT, fmt))errno_exit("VIDIOC_S_FMT");/* Note VIDIOC_S_FMT may change width and height. *//* Buggy driver paranoia. */min = fmt->fmt.pix.width * 2;if (fmt->fmt.pix.bytesperline < min)fmt->fmt.pix.bytesperline = min;min = fmt->fmt.pix.bytesperline * fmt->fmt.pix.height;if (fmt->fmt.pix.sizeimage < min)fmt->fmt.pix.sizeimage = min;init_mmap(cam);}

3.3初始化缓冲区队列

void init_mmap(struct camera *cam) {struct v4l2_requestbuffers req;CLEAR(req);req.count = 4;req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;req.memory = V4L2_MEMORY_MMAP;//分配内存if (-1 == xioctl(cam->fd, VIDIOC_REQBUFS, &req)) {if (EINVAL == errno) {fprintf(stderr, "%s does not support ""memory mapping\n", cam->device_name);exit(EXIT_FAILURE);} else {errno_exit("VIDIOC_REQBUFS");}}if (req.count < 2) {fprintf(stderr, "Insufficient buffer memory on %s\n", cam->device_name);exit(EXIT_FAILURE);}cam->buffers = calloc(req.count, sizeof(*(cam->buffers)));if (!cam->buffers) {fprintf(stderr, "Out of memory\n");exit(EXIT_FAILURE);}for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {struct v4l2_buffer buf;CLEAR(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = n_buffers;//将VIDIOC_REQBUFS中分配的数据缓存转换成物理地址if (-1 == xioctl(cam->fd, VIDIOC_QUERYBUF, &buf))errno_exit("VIDIOC_QUERYBUF");cam->buffers[n_buffers].length = buf.length;cam->buffers[n_buffers].start = mmap(NULL /* start anywhere */,buf.length, PROT_READ | PROT_WRITE /* required */,MAP_SHARED /* recommended */, cam->fd, buf.m.offset);if (MAP_FAILED == cam->buffers[n_buffers].start)errno_exit("mmap");}}

3.4启动摄像头

void start_capturing(struct camera *cam) {unsigned int i;enum v4l2_buf_type type;for (i = 0; i < n_buffers; ++i) {struct v4l2_buffer buf;CLEAR(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;if (-1 == xioctl(cam->fd, VIDIOC_QBUF, &buf))errno_exit("VIDIOC_QBUF");}type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (-1 == xioctl(cam->fd, VIDIOC_STREAMON, &type))errno_exit("VIDIOC_STREAMON");}

3.5停止摄像头

void stop_capturing(struct camera *cam) {enum v4l2_buf_type type;type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (-1 == xioctl(cam->fd, VIDIOC_STREAMOFF, &type))errno_exit("VIDIOC_STREAMOFF");}


0 0
原创粉丝点击