原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/
资料链接:http://www.cnblogs.com/emouse/archive/2013/03/03/2943243.html
1.打开摄像头的设备节点文件。
fd = open (dev_name, O_RDWR | O_NONBLOCK, 0);
2.获取设备驱动信息。
int ioctl(int fd, int request, struct v4l2_capability *argp);
ioctl (fd, VIDIOC_QUERYCAP, &cap);
VIDIOC_QUERYCAP ::查询设备属性。
struct v4l2_capability { u8 driver[16]; // 驱动名字 u8 card[32]; // 设备名字 u8 bus_info[32]; // 设备在系统中的位置 u32 version; // 驱动版本号 u32 capabilities; // 设备支持的操作 u32 reserved[4]; // 保留字段 };
3.设置图像格式。
VIDIOC_G_FMT, VIDIOC_S_FMT
检查是否支持某种格式:VIDIOC_TRY_FMT
我的代码:
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = 320; fmt.fmt.pix.height = 240; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; ioctl (fd, VIDIOC_S_FMT, &fmt) ;
相关函数:
int ioctl(int fd, int request, struct v4l2_format *argp);
相关结构体:
struct v4l2_format { enum v4l2_buf_type type; // 帧类型,应用程序设置 union fmt { struct v4l2_pix_format pix; // 视频设备使用 struct v4l2_window win; struct v4l2_vbi_format vbi; struct v4l2_sliced_vbi_format sliced; u8 raw_data[200]; }; }; struct v4l2_pix_format { u32 width; // 帧宽,单位像素 u32 height; // 帧高,单位像素 u32 pixelformat; // 帧格式 enum v4l2_field field; u32 bytesperline; u32 sizeimage; enum v4l2_colorspace colorspace; u32 priv; };
例:显示当前帧的相关信息
struct v4l2_format fmt; fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; ioctl(fd, VIDIOC_G_FMT, &fmt); printf(“Current data format information: %d height:%d ”, fmt.fmt.pix.width,fmt.fmt.pix.height); struct v4l2_fmtdesc fmtdesc; fmtdesc.index=0; fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1) { if(fmtdesc.pixelformat & fmt.fmt.pix.pixelformat) { printf(“ format:%s ”,fmtdesc.description); break; } fmtdesc.index++; }
例:检查是否支持某种帧格式
struct v4l2_format fmt;
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_RGB32;
if(ioctl(fd,VIDIOC_TRY_FMT,&fmt)==-1)
if(errno==EINVAL) printf(“not support format RGB32! ”);
4.申请帧缓冲
ioctl (fd, VIDIOC_REQBUFS, &req);
我的代码:
req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; ioctl (fd, VIDIOC_REQBUFS, &req);
应用程序和设备有三种交换数据的方法,直接 read/write、内存映射(memory mapping)
和用户指针。这里只讨论内存映射(memory mapping)。
向设备申请缓冲区 VIDIOC_REQBUFS
int ioctl(int fd, int request, struct v4l2_requestbuffers *argp);
相关结构体:
struct v4l2_requestbuffers { u32 count; // 缓冲区内缓冲帧的数目 enum v4l2_buf_type type; // 缓冲帧数据格式 enum v4l2_memory memory; // 区别是内存映射还是用户指针方式 u32 reserved[2]; };