您的位置:首页 > 其它

UVC驱动测试程序

2012-12-11 12:50 267 查看
原文:http://hi.baidu.com/wlvvdnjilgcfjqe/item/efdec7f437d1000ec7dc4548

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 <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/ioctl.h>//系统输入输出,必加

#include <unistd.h>

#include <stdint.h>

#include <stdio.h>

#include <stdlib.h>

#include <asm/types.h>

#include <linux/videodev.h>//v4l的头文件,必加(其中include了videodev2.h-V4L2头文件)

#include <sys/mman.h>

#include <string.h>

#include <malloc.h>

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<buf.bytesused; 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<buf.bytesused; 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,通过文件查看,可以看见图像。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: