ZBLOG

编写一个V4L2相机程序来for mat

以下是一个简单的V4L2相机程序,可以设置图像格式(如YUYV或MJPEG等)并捕获图像:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

// V4L2头文件
#include <linux/videodev2.h>

#define DEVICE "/dev/video0"

int main(int argc, char **argv)
{
    int fd;
    struct v4l2_capability cap;
    struct v4l2_format fmt;
    struct v4l2_requestbuffers reqbuf;
    struct v4l2_buffer buf;
    void *mem[4];
    unsigned int nbufs;

    // 打开设备文件
    fd = open(DEVICE, O_RDWR);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // 查询设备功能
    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
        perror("VIDIOC_QUERYCAP");
        exit(EXIT_FAILURE);
    }

    printf("Driver: %s\n", cap.driver);
    printf("Card: %s\n", cap.card);

    // 设置图像格式为YUYV 640x480
    memset(&fmt, 0, sizeof(fmt));
   fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   fmt.fmt.pix.width = 640; 
   fmt.fmt.pix.height = 480; 
   fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; 
   if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { 
       perror("VIDIOC_S_FMT"); 
       exit(EXIT_FAILURE); 
   }

    // 请求内存映射缓冲区
    memset(&reqbuf, 0, sizeof(reqbuf));
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory = V4L2_MEMORY_MMAP;
    reqbuf.count = 4;
    if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1) {
        perror("VIDIOC_REQBUFS");
        exit(EXIT_FAILURE);
    }

    nbufs = reqbuf.count;

    // 映射内存
    for (int i = 0; i < nbufs; ++i) {
        memset(&buf, 0, sizeof(buf));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index = i;
        if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
            perror("VIDIOC_QUERYBUF");
            exit(EXIT_FAILURE);
        }
        mem[i] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
                MAP_SHARED, fd, buf.m.offset);
        if (mem[i] == MAP_FAILED) {
            perror("mmap");
            exit(EXIT_FAILURE);
        }
    }

    // 入队请求缓冲区
    for (int i = 0; i < nbufs; ++i) {
        memset(&buf, 0, sizeof(buf));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index = i;
        if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
            perror("VIDIOC_QBUF");
            exit(EXIT_FAILURE);
       }
   }

   // 启动视频采集
    int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {
        perror("VIDIOC_STREAMON");
        exit(EXIT_FAILURE);
    }

    // 捕获一帧图像
    memset(&buf, 0, sizeof(buf));
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) {
        perror("VIDIOC_DQBUF");
        exit(EXIT_FAILURE);
   }

   printf("Captured frame %d\n", buf.index);

   // 停止视频采集
   if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {
       perror("VIDIOC_STREAMOFF");
       exit(EXIT_FAILURE);
   }

   // 解除内存映射
   for (int i = 0; i < nbufs; ++i)
       munmap(mem[i], buf.length);

   close(fd);

   return EXIT_SUCCESS;
}

如果要设置不同的格式,可以更改V4L2_PIX_FMT_YUYV。常见的格式包括MJPEG、H.264等,请参考V4L2 API文档进行设置。 内容由零声教学AI助手生成,来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=1544

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?