C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C语言生成yuv图片

C语言调用摄像头实现生成yuv未压缩图片

作者:乐山劲松

这篇文章主要为大家详细介绍了C语言如何调用摄像头实现生成yuv未压缩图片,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以参考一下

播发yuv格式图片:ffplay -f rawvideo -video_size 1920X1080 -pixel_format  yuyv422  my.yuv

此图片是没有进行过任何压缩处理的图片,是摄像头最高分辨率的图片。

实现代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>  //v4l2 头文件
#include <string.h>
#include <sys/mman.h>
int main(void)
{
	//1.打开设备
	int fd = open("/dev/video0", O_RDWR);
	if(fd < 0)
	{
		perror("打开设备失败");
		return -1;
	}
	//设置采集格式	
	struct v4l2_format {
		enum v4l2_buf_type {
			V4L2_BUF_TYPE_VIDEO_CAPTURE        = 1,
			V4L2_BUF_TYPE_VIDEO_OUTPUT         = 2,
			V4L2_BUF_TYPE_VIDEO_OVERLAY        = 3,
		}type;
		union {
			//	struct v4l2_pix_format         pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
			struct v4l2_window             win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
			struct v4l2_vbi_format         vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
			struct v4l2_sliced_vbi_format  sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
			__u8   raw_data[200];                   /* user-defined */
			struct v4l2_pix_format {
				__u32			width;
				__u32			height;
				__u32			pixelformat;
				__u32			field;		/* enum v4l2_field */
				__u32			bytesperline;	/* for padding, zero if unused */
				__u32			sizeimage;
				__u32			colorspace;	/* enum v4l2_colorspace */
				__u32			priv;		/* private data, depends on pixelformat */
				__u32			flags;		/* format flags (V4L2_PIX_FMT_FLAG_*) */
				union {
					/* enum v4l2_ycbcr_encoding */
					__u32			ycbcr_enc;
					/* enum v4l2_hsv_encoding */
					__u32			hsv_enc;
				};
				__u32			quantization;	/* enum v4l2_quantization */
				__u32			xfer_func;	/* enum v4l2_xfer_func */
			}pix;
		} fmt;
	}vfmt;
	vfmt.type=1;	
	vfmt.fmt.pix.width=1920;         //720p=1280*720  1080p=1920*1080
	vfmt.fmt.pix.pixelformat=v4l2_fourcc('Y','U','Y','V');         //生成不压缩的图片
	                                                              //播发yuv格式图片:ffplay -f rawvideo -video_size 1920X1080 -pixel_format  yuyv422  my.yuv
	int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);
	if(ret < 0)
	{
		perror("设置格式失败");
	}
	//4.申请内核缓冲区个数
	struct v4l2_requestbuffers {
		__u32			count;     //申请个数
		__u32			type;		/* enum v4l2_buf_type */
		__u32			memory;		/* enum v4l2_memory */
		__u32			capabilities;
		__u32			reserved[1];
	}reqbuffer;
	reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	reqbuffer.count = 1; //申请4个缓冲区
	reqbuffer.memory=V4L2_BUF_CAP_SUPPORTS_MMAP;      //映射方式
	ret  = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);
	if(ret < 0)
	{
		perror("申请队列空间失败");
	}
	//设置 设备映射到内存的选项
	struct v4l2_buffer {
		__u32			index;
		__u32			type;
		__u32			bytesused;
		__u32			flags;
		__u32			field;
		struct timeval		timestamp;
		struct v4l2_timecode	timecode;
		__u32			sequence;
		/* memory location */
		__u32			memory;
		union {
			__u32           offset;
			unsigned long   userptr;
			struct v4l2_plane *planes;
			__s32		fd;
		} m;
		__u32			length;
		__u32			reserved2;
		union {
			__s32		request_fd;
			__u32		reserved;
		};
	}mapbuffer;
	unsigned char *mptr;
	unsigned int  size;
	mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	mapbuffer.index = 0;
	ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//查询缓冲区状态
	if(ret < 0)
	{
		perror("查询内核空间队列失败");
	}
	int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(fd, VIDIOC_STREAMON, &type);     //启动流
	if(ret < 0)
	{
		perror("开启失败");
	}
	mptr= (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE, 
		MAP_SHARED, fd, mapbuffer.m.offset);       //设备映射到缓冲区内存
	size=mapbuffer.length;
	ret  = ioctl(fd, VIDIOC_QBUF, &mapbuffer);    //把缓冲区数据放入读队列中
	if(ret < 0)                                   
	{
		perror("放回失败");
	}
	ret = ioctl(fd, VIDIOC_DQBUF, &mapbuffer);       //读当前队列缓冲区的数据
	if(ret < 0)
	{
		perror("提取数据失败");
	}
	FILE *file=fopen("my.yuv", "w+");
	fwrite(mptr,mapbuffer.length, 1, file);
	fclose(file);
	munmap(mptr, size);
	close(fd);
	return 0;
}

到此这篇关于C语言调用摄像头实现生成yuv未压缩图片的文章就介绍到这了,更多相关C语言生成yuv图片内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文