播发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;
- }