【C语言】之使用V4L2编程获取摄像头设备信息

如果想进一步了解V4L2编程,可以访问V4L2编程帮助手册官网

http://v4l.videotechnology.com/dwg/

或者在我的网盘上下载

https://pan.baidu.com/s/15gmKHxXrXqT-lCr5HnVYVQ

里面包含了所有关于V4L2编程的命令和例程,好了,不多说了,下面以一个示例简单使用 V4L2 来操作摄像头获取摄像头设备信息


/*****************************************************
 * 文件名:GetCameraInfo.c
 * 文件描述:linux下使用v4l2编程查询摄像头设备信息 
 * 编写人:王廷云
 * 编写日期:2017-12-1
 * 修改日期:2018-1-1
*****************************************************/
#include <stdio.h>
#include <unistd.h>

#include <sys/types.h>                      // 下面四个头文件是linux系统编程特有的
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include <linux/videodev2.h>                // 操作摄像头设备

int main(int argc, char **argv)
{	
	int ret, i, j;
	int fd;

	/* 打开摄像头设备 */ 
	fd = open("/dev/video0", O_RDWR);       // 注意查看摄像头设备名
	if (-1 == fd)
	{
		perror("open /dev/video0");
		return -1;
	}

	/* 查询打开的设备是否属于摄像头:设备video不一定是摄像头*/
	struct v4l2_capability cap;
	ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
	if (-1 == ret)
	{
		perror("ioctl VIDIOC_QUERYCAP");
		close(fd);
	}
	if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
	{
		/* 如果为摄像头设备则打印摄像头驱动名字 */
		printf("Driver    Name: %s\n", cap.driver);         
	}
	else
	{
		printf("open file is not video\n");
		close(fd);
		return -2;
	}

	/* 查询摄像头可捕捉的图片类型,VIDIOC_ENUM_FMT: 枚举摄像头帧格式 */
	struct v4l2_fmtdesc fmt;
	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // 指定需要枚举的类型
	for (i = 0; ; i++)                      // 有可能摄像头支持的图片格式不止一种 
	{
		fmt.index = i;
		ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt);
		if (-1 == ret)                      // 获取所有格式完成
		{
			break;	
		}
		
		/* 打印摄像头图片格式 */
		printf("Picture Format: %s\n", fmt.description);    

		/* 查询该图像格式所支持的分辨率 */	
		struct v4l2_frmsizeenum frmsize;
		frmsize.pixel_format = fmt.pixelformat;
		for (j = 0; ; j++)                  // 该格式支持分辨率不止一种
		{
			frmsize.index = j;
			ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize);
			if (-1 == ret)                  // 获取所有图片分辨率完成
			{
				break;
			}
			
			/* 打印图片分辨率 */
			printf("width: %d height: %d\n",
			        frmsize.discrete.width,frmsize.discrete.height);
		}

	}
	
	close(fd);                              // 不要忘记关闭打开的设备

	return 0;
}
  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
以下是使用v4l2获取mjpeg格式图片的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <linux/videodev2.h> #define CAMERA_DEVICE "/dev/video0" #define CAPTURE_FILE "capture.jpeg" #define BUFFER_COUNT 4 struct buffer { void *start; size_t length; }; int main() { int fd; struct v4l2_capability cap; struct v4l2_format fmt; struct v4l2_requestbuffers req; struct v4l2_buffer buf; enum v4l2_buf_type type; struct buffer *buffers; int i, n_buffers; FILE *fp; // 打开摄像头设备 fd = open(CAMERA_DEVICE, O_RDWR); if (fd == -1) { perror("Failed to open camera device"); return EXIT_FAILURE; } // 查询摄像头设备的能力 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) { perror("Failed to query camera device"); return EXIT_FAILURE; } // 检查是否支持视频捕获 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { fprintf(stderr, "Camera device does not support video capture\n"); return EXIT_FAILURE; } // 检查是否支持流形式的视频捕获 if (!(cap.capabilities & V4L2_CAP_STREAMING)) { fprintf(stderr, "Camera device does not support streaming\n"); return EXIT_FAILURE; } // 设置摄像头设备的格式 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_MJPEG; if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { perror("Failed to set camera device format"); return EXIT_FAILURE; } // 请求摄像头设备的缓冲区 memset(&req, 0, sizeof(req)); req.count = BUFFER_COUNT; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { perror("Failed to request camera device buffers"); return EXIT_FAILURE; } // 映射摄像头设备的缓冲区 buffers = calloc(req.count, sizeof(*buffers)); for (i = 0, n_buffers = 0; i < req.count; 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("Failed to query camera device buffer"); return EXIT_FAILURE; } buffers[i].length = buf.length; buffers[i].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (buffers[i].start == MAP_FAILED) { perror("Failed to map camera device buffer"); return EXIT_FAILURE; } n_buffers++; } // 启动摄像头设备的视频流 for (i = 0; i < n_buffers; 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("Failed to enqueue camera device buffer"); return EXIT_FAILURE; } } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) { perror("Failed to start camera device stream"); return 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("Failed to dequeue camera device buffer"); return EXIT_FAILURE; } // 保存图片到文件 fp = fopen(CAPTURE_FILE, "wb"); if (fp == NULL) { perror("Failed to open capture file"); return EXIT_FAILURE; } fwrite(buffers[buf.index].start, buf.bytesused, 1, fp); fclose(fp); // 停止摄像头设备的视频流 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) { perror("Failed to stop camera device stream"); return EXIT_FAILURE; } // 释放摄像头设备的缓冲区 for (i = 0; i < n_buffers; i++) { if (munmap(buffers[i].start, buffers[i].length) == -1) { perror("Failed to unmap camera device buffer"); return EXIT_FAILURE; } } free(buffers); // 关闭摄像头设备 if (close(fd) == -1) { perror("Failed to close camera device"); return EXIT_FAILURE; } return EXIT_SUCCESS; } ``` 这段代码使用v4l2库调用摄像头设备的API,请求摄像头设备的缓冲区,映射缓冲区,启动视频流,从视频流中获取一张图片,保存图片到文件,停止视频流,释放缓冲区,最后关闭摄像头设备。请注意,此代码中的图片格式为MJPEG,如果你需要获取其他格式的图片,需要修改代码中的像素格式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值