Chinaunix首页 | 论坛 | 博客
  • 博客访问: 851138
  • 博文数量: 290
  • 博客积分: 511
  • 博客等级: 下士
  • 技术积分: 1590
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-29 13:14
文章分类

全部博文(290)

文章存档

2018年(28)

2017年(19)

2016年(8)

2015年(1)

2014年(14)

2013年(12)

2012年(22)

2011年(186)

分类:

2011-12-17 13:19:29

原文地址:UVC驱动测试程序 作者:dingzerong

UVC驱动测试程序开发

视频设备数据读取操作流程:

*1. 打开设备文件。 int fd=open(”/dev/video0″,O_RDWR);

2. 取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability

3. 选择视频输入,一个视频设备可以有多个视频输入。VIDIOC_S_INPUT,struct v4l2_input

*4. 设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。

VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format

*5. 向驱动申请帧缓冲,一般不超过5个。struct v4l2_requestbuffers

*6. 将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制。mmap

*7. 将申请到的帧缓冲全部入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer

8. 开始视频的采集。VIDIOC_STREAMON

*9. 出队列以取得已采集数据的帧缓冲,取得原始采集数据。VIDIOC_DQBUF

*10. 将缓冲重新入队列尾,这样可以循环采集。VIDIOC_QBUF

11. 停止视频的采集。VIDIOC_STREAMOFF

*12. 关闭视频设备。close(fd);

 

加*的为,最基本过程。

该测试程序为最简单的测试程序,他只测试驱动必须实现的对应的V4L2的最基本接口。

 

#include  
#include  
#include
#include //系统输入输出,必加
#include    
#include
#include
#include
#include
#include //v4l的头文件,必加(其中include了videodev2.h-V4L2头文件)
#include
#include
#include

 

uvcvideo<-videodev,v4l1_compat

UVCVIDEO即UVC驱动(免驱驱动)它依赖VIDEODEV,V4L1_COMPAT(V4L2向前兼容模块)

int start_capturing(int fd_v4l)
{
        unsigned int i=0;
        struct v4l2_buffer buf;
        enum v4l2_buf_type type;

        memset(&buf, 0, sizeof (buf));//向驱动申请缓冲buf
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 buf.memory = V4L2_MEMORY_MMAP;
        buf.index = i;
        if (ioctl(fd_v4l, VIDIOC_QUERYBUF, &buf) < 0)//是否申请成功
        {
            printf(“VIDIOC_QUERYBUF error\n”);
            return -1;
        }

        buffers.length = buf.length;
        buffers.offset = (size_t) buf.m.offset;
        buffers.start = mmap (NULL, buffers.length,PROT_READ | PROT_WRITE, MAP_SHARED, fd_v4l, buffers.offset);

//以内存映射方式将申请的驱动缓冲映射到用户空间buffers中

 if (ioctl (fd_v4l, VIDIOC_QBUF, &buf) < 0)
 {
             printf(“VIDIOC_QBUF error\n”);
             return -1;
        }//驱动缓冲区是否可以输出

        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//设置缓冲区buf类型

   
int v4l_capture_setup(void)//抓图前准备工作
{     char * v4l_device = “/dev/video0″;
        struct v4l2_format fmt;
        struct v4l2_control ctrl;
        int fd_v4l = 0;
 struct v4l2_crop crop;
        if ((fd_v4l = open(v4l_device, O_RDWR, 0)) < 0)
        {
                printf(“Unable to open %s\n”, v4l_device);
                return 0;
        }

        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
  //fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
 //fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
//fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
 fmt.fmt.pix.width = g_width;
        fmt.fmt.pix.height = g_height;
 //printf (“fmt.fmt.pix.sizeimage =%d\n”,fmt.fmt.pix.sizeimage);
        if (ioctl(fd_v4l, VIDIOC_S_FMT, &fmt) < 0)//设置视频格式
        {
                //printf(“set format failed\n”);
  printf(“not a mjpeg format \n”);
                fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
        }
        if (ioctl(fd_v4l, VIDIOC_S_FMT, &fmt) < 0)
        {
                //printf(“set format failed\n”);
                printf(“not a jpeg format \n”);
                fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
        }
        if (ioctl(fd_v4l, VIDIOC_S_FMT, &fmt) < 0)
        {
                //printf(“set format failed\n”);
                printf(“not a mjpeg format \n”);
                printf(“set format failed\n”);
  return 0;
        }
 //printf (“fmt.fmt.pix.sizeimage =%d\n”,fmt.fmt.pix.sizeimage);
  ctrl.id = V4L2_CID_BRIGHTNESS ;
 //ctrl.value = V4L2_CTRL_TYPE_INTEGER + 0;
 ctrl.value = g_rotate;
        if (ioctl(fd_v4l, VIDIOC_S_CTRL, &ctrl) < 0)//设置控制信息
        {
                printf(“set ctrl failed\n”);
                return 0;
        }

int v4l_capture_test(int fd_v4l, const char * file)//抓图过程
{
 int i;
        struct v4l2_buffer buf;
        struct v4l2_buffer temp_buf;
        struct v4l2_format fmt;
        FILE * fd_y_file = 0;
        int count = g_capture_count;//=1
    
        if ((fd_y_file = fopen(file, “wb”)) < 0)//打开设备
        {
                printf(“Unable to create y frame recording file\n”);
                return -1;
        }
 //printf (“fopen_return_fd_y_file = %d \n”,fd_y_file);
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//设置视频格式类型,必须与v4l2_buf_type一致
 
        if (ioctl(fd_v4l, VIDIOC_G_FMT, &fmt) < 0)//获得驱动支持格式,V4L2_format 确定
        {
                printf(“get format failed\n”);
                return -1;
        }
        else
        {
                printf(“Width = %d\n”, fmt.fmt.pix.width);//输出v4l2_format 的信息
                printf(“Height = %d\n”, fmt.fmt.pix.height);
        //printf(“Image size = %d\n”, imagesize);
  printf(“Image size = %d\n”, fmt.fmt.pix.sizeimage);              
  printf(“pixelformat = %d\n”, fmt.fmt.pix.pixelformat);
        }

        if (start_capturing(fd_v4l) < 0)//最开始是否可以抓图
        {
                printf(“start_capturing failed\n”);
                return -1;
        }
   
        memset(&buf, 0, sizeof (buf));//初始化缓冲区空间

        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//设置输出视频类型,必须与v4l2_buf_type一致
        buf.memory = V4L2_MEMORY_MMAP;//采用内存映射方式,将数据映射到用户空间
        if (ioctl (fd_v4l, VIDIOC_DQBUF, &buf) < 0)printf(“VIDIOC_DQBUF failed.\n”);//缓冲区数据申请出队
             
 //printf (“fwrite start \n”);
 //printf (“size = %d \n”,fmt.fmt.pix.sizeimage);
 
 unsigned char *ptcur = buffers.start; 
// printf (“buf.bytesused = %d \n”,buf.bytesused);
 int i1;
 for(i1=0; i1        {
        if((buffers.start[i1] == 0×000000FF) && (buffers.start[i1+1] == 0×000000C4)) {
  printf(“huffman table finded! \nbuf.bytesused = %d\nFFC4 = %d \n”,buf.bytesused,i1);
  break;     
   }
 }
 if(i1 == buf.bytesused)//若无哈弗曼表,则将数据全部输出
 {
 printf(“huffman table don’t exist! \n”);  
        printf (“buf.bytesused = %d \n”,buf.bytesused);
        if(buf.bytesused == 0)return -1;
        fwrite(buffers.start, buf.bytesused, 1, fd_y_file);
        printf (“fwrite all end \n”);
 }
 else //若有哈弗曼表,则从jpeg图像开始处FFD8,写入文件
 {
 for(i=0; i        {
 if((buffers.start[i] == 0×000000FF) && (buffers.start[i+1] == 0×000000D8)) break;  
 ptcur++;
 }
 printf(“i = %d,FF = %02x,D8 = %02x\n”,i,buffers.start[i],buffers.start[i+1]);
 int imagesize =buf.bytesused – i;
// int imagesize = fmt.fmt.pix.sizeimage;
// printf (“buf.bytesused = %d \n”,buf.bytesused);
 printf (“imagesize = %d \n”,imagesize);
 if(imagesize == 0)return -1;
 fwrite(ptcur, imagesize, 1, fd_y_file);
 printf (“fwrite end \n”);
 }
        fclose(fd_y_file);
        close(fd_v4l);
        return 0;
}

用arm-linux-gcc-4.3.2编译成功,下载至mini2440,./capture file.jpg,通过文件查看,可以看见图像。

 

 

http://www.emsym.com/blog/?p=1042

阅读(1152) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~