开发者

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

开发者 https://www.devze.com 2023-11-19 10:44 出处:网络 作者: 乐山劲松
播发yuv格式图片:ffplay -f rawvideo -video_size 1920X1080 -pixel_format  yuyv422  my.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;     /* pythonV4L2_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;		/* pphprivate data, depends on pixelformat */
				__u32			flags;		/* format flags (V4L2_PIX_FMT_FLAG_*) */
				union {
					/* enum v4l2_ycbcr_encoding */
					__u32			ycbcr_encandroid;
					/* 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_http://www.devze.comSHARED, fd, mapbuffer.m.offset);       //设备映射到缓冲区内存
	sizpythone=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图片内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号