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图片内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
