//#Rockie Cheng
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>         
#include <fcntl.h>           
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h>       
#include <linux/videodev2.h>
#define CLEAR(x) memset (&(x), 0, sizeof (x))  //宏定义清楚
struct buffer {
        void *                  start;
        size_t                  length;
};  //定义一个buffer结构体,这个结构体用于盛放申请到的内存首地址和长度
static char *dev_name = "/dev/video0";//摄像头设备名
static int  fd = -1;  //文件描述符fd
struct buffer *buffers = NULL;
static unsigned int  n_buffers = 0;
FILE *file_fd;  //
static unsigned long file_length;
static unsigned char *file_name;
//获取一帧数据,
static int read_frame (void)
{
struct v4l2_buffer buf;  //用于盛放一帧数据的信息
unsigned int i;
CLEAR (buf);
pe = V4L2_BUF_TYPE_VIDEO_CAPTURE;
= V4L2_MEMORY_MMAP;
int ff = ioctl (fd, VIDIOC_DQBUF, &buf);  //从视频缓冲区的输出队列中取得一个已经保存有一帧视频数据的视频缓冲区
if(ff<0)
printf("failture\n"); //出列采集的帧缓冲
assert (buf.index < n_buffers);
  printf ("buf.index dq is %d,\n",buf.index);
fwrite(buffers[buf.index].start, buffers[buf.index].length, 1, file_fd); //将其写入文件中
ff=ioctl (fd, VIDIOC_QBUF, &buf); //再将其入列,投放一个空的视频缓冲区到视频缓冲区输入队列中
if(ff<0)printf输出格式linux
printf("failture VIDIOC_QBUF\n");
return 1;
}
//主函数
int main (int argc,char ** argv)
{
struct v4l2_capability cap;
/*储存了硬件的信息,由驱动填写各个元素的值,包含:驱动名称,硬件名称,版本号,
硬件支持的功能:V4L2_CAP_VIDEO_CAPTURE(支持视频捕捉接口)*/
struct v4l2_format fmt;
/*流数据的格式,
struct v4l2_format
{
enum v4l2_buf_type type;
union
{
struct v4l2_pix_format pix;
// V4L2_BUF_TYPE_VIDEO_CAPTURE包含每幅图片的一行,一列所占的像素个数,width和heigth;
//像素格式与压缩类型pixelformat;一幅图像的数据所用的最大字节数imagesize=bytesline*heigth
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
} fmt;
};
*/
unsigned int i;
enum v4l2_buf_type type;
//所申请的缓冲区的类型,与struct v4l2_format和struct v4l2_requestbuffers结构体中的type一样,
//由用户定义,比如可以为V4L2_BUF_TYPE_VIDEO_CAPTURE
file_fd = fopen("test-mmap.jpg", "w");//以只写方式打开文件,返回值是锁打开的文件的首地址
fd = open (dev_name, O_RDWR  | O_NONBLOCK, 0);//打开摄像头设备,无阻塞方式打开
int ff=ioctl (fd, VIDIOC_QUERYCAP, &cap);//获取硬件的参数,结构会存放在cap中,这是由驱动自动填写的
if(ff<0)
    printf("failture VIDIOC_QUERYCAP\n");
struct v4l2_fmtdesc fmt1;
int ret;
memset(&fmt1, 0, sizeof(fmt1));
fmt1.index = 0;
pe = V4L2_BUF_TYPE_VIDEO_CAPTURE;
while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt1)) == 0) //获取当前驱动支持的视频格式
{
    fmt1.index++;
    printf("{ pixelformat = '%c%c%c%c', description = '%s' }\n",fmt1.pixelformat & 0xFF, (fmt1.pixelformat >> 8) & 0xFF,(fmt1.pixelformat >> 16) & 0xFF, (fmt1.pixelformat >> 24) &
0xFF,fmt1.description);         
}
CLEAR (fmt);
pe = V4L2_BUF_TYPE_VIDEO_CAPTURE;