V4L2 camera 驱动 capture测试程序【转】
转自:http://blog.csdn.net/kickxxx/article/details/6336346
在网上找了一个测试程序, 看了看,是根据capture.c修改的。测试步骤如下 . gcc -o capture_image capture_image.c . ctrl+alt+f1 切换到ubuntu的控制台,切换到控制台模式是因为在图形模式下看不到测试图形,这可能和framebuffer的设置有关 . sudo modprobe vivi . sudo ./capture_image -d /dev/video0 这时可以看到在屏幕左上角有一个640x480大小窗口,内容是彩色条格,彩色条格不停的移动,持续时间5秒 在ubuntu下还可以使用cheese测试 . sudo apt-get install cheese . sudo modprobe vivi . 启动 cheese后,就可以看到滚动的彩色条格 附上测试程序 [c-sharp] view plain copy #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 <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>
#include <linux/fb.h>
#define CLEAR(x) memset (&(x), 0, sizeof (x)) struct buffer {
void * start;
size_t length;
}; static char * dev_name = NULL;
static int fd = -;
struct buffer * buffers = NULL;
static unsigned int n_buffers = ;
static int time_in_sec_capture=;
static int fbfd = -;
static struct fb_var_screeninfo vinfo;
static struct fb_fix_screeninfo finfo;
static char *fbp=NULL;
static long screensize=; static void errno_exit (const char * s)
{
fprintf (stderr, "%s error %d, %s/n",s, errno, strerror (errno));
exit (EXIT_FAILURE);
} static int xioctl (int fd,int request,void * arg)
{
int r;
do r = ioctl (fd, request, arg);
while (- == r && EINTR == errno);
return r;
} inline int clip(int value, int min, int max) {
return (value > max ? max : value < min ? min : value);
} static void process_image (const void * p){ //ConvertYUVToRGB32
;
unsigned char* in=(char*)p;
int width=;
int height=;
int istride=;
int x,y,j;
int y0,u,y1,v,r,g,b;
long location=; for ( y = ; y < height + ; ++y) {
for (j = , x=; j < width * ; j += ,x +=) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/) +
(y+vinfo.yoffset) * finfo.line_length; y0 = in[j];
u = in[j + ] - ;
y1 = in[j + ];
v = in[j + ] - ; r = ( * y0 + * v + ) >> ;
g = ( * y0 - * u - * v + ) >> ;
b = ( * y0 + * u + ) >> ; fbp[ location + ] = clip(b, , );
fbp[ location + ] = clip(g, , );
fbp[ location + ] = clip(r, , );
fbp[ location + ] = ; r = ( * y1 + * v + ) >> ;
g = ( * y1 - * u - * v + ) >> ;
b = ( * y1 + * u + ) >> ; fbp[ location + ] = clip(b, , );
fbp[ location + ] = clip(g, , );
fbp[ location + ] = clip(r, , );
fbp[ location + ] = ;
}
in +=istride;
}
} static int read_frame (void)
{
struct v4l2_buffer buf;
unsigned int i; CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP; if (- == xioctl (fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return ;
case EIO: default:
errno_exit ("VIDIOC_DQBUF");
}
} assert (buf.index < n_buffers);
printf("v4l2_pix_format->field(%d)/n", buf.field);
//assert (buf.field ==V4L2_FIELD_NONE);
process_image (buffers[buf.index].start);
if (- == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF"); return ;
} static void run (void)
{
unsigned int count;
int frames;
frames = * time_in_sec_capture; while (frames-- > ) {
for (;;) {
fd_set fds;
struct timeval tv;
int r;
FD_ZERO (&fds);
FD_SET (fd, &fds); tv.tv_sec = ;
tv.tv_usec = ; r = select (fd + , &fds, NULL, NULL, &tv); if (- == r) {
if (EINTR == errno)
continue;
errno_exit ("select");
} if ( == r) {
fprintf (stderr, "select timeout/n");
exit (EXIT_FAILURE);
} if (read_frame ())
break; }
}
} static void stop_capturing (void)
{
enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (- == xioctl (fd, VIDIOC_STREAMOFF, &type))
errno_exit ("VIDIOC_STREAMOFF");
} static void start_capturing (void)
{
unsigned int i;
enum v4l2_buf_type type; for (i = ; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i; if (- == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
} type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (- == xioctl (fd, VIDIOC_STREAMON, &type))
errno_exit ("VIDIOC_STREAMON"); } static void uninit_device (void)
{
unsigned int i; for (i = ; i < n_buffers; ++i)
if (- == munmap (buffers[i].start, buffers[i].length))
errno_exit ("munmap"); if (- == munmap(fbp, screensize)) {
printf(" Error: framebuffer device munmap() failed./n");
exit (EXIT_FAILURE) ;
}
free (buffers);
} static void init_mmap (void)
{
struct v4l2_requestbuffers req; //mmap framebuffer
fbp = (char *)mmap(NULL,screensize,PROT_READ | PROT_WRITE,MAP_SHARED ,fbfd, );
if ((int)fbp == -) {
printf("Error: failed to map framebuffer device to memory./n");
exit (EXIT_FAILURE) ;
}
memset(fbp, , screensize);
CLEAR (req); req.count = ;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP; if (- == xioctl (fd, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
fprintf (stderr, "%s does not support memory mapping/n", dev_name);
exit (EXIT_FAILURE);
} else {
errno_exit ("VIDIOC_REQBUFS");
}
} if (req.count < ) { //if (req.count < 2)
fprintf (stderr, "Insufficient buffer memory on %s/n",dev_name);
exit (EXIT_FAILURE);
} buffers = calloc (req.count, sizeof (*buffers)); if (!buffers) {
fprintf (stderr, "Out of memory/n");
exit (EXIT_FAILURE);
} for (n_buffers = ; n_buffers < req.count; ++n_buffers) {
struct v4l2_buffer buf; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers; if (- == xioctl (fd, VIDIOC_QUERYBUF, &buf))
errno_exit ("VIDIOC_QUERYBUF"); buffers[n_buffers].length = buf.length;
buffers[n_buffers].start =mmap (NULL,buf.length,PROT_READ | PROT_WRITE ,MAP_SHARED,fd, buf.m.offset); if (MAP_FAILED == buffers[n_buffers].start)
errno_exit ("mmap");
} } static void init_device (void)
{
struct v4l2_capability cap;
struct v4l2_cropcap cropcap;
struct v4l2_crop crop;
struct v4l2_format fmt;
unsigned int min; // Get fixed screen information
if (-==xioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
printf("Error reading fixed information./n");
exit (EXIT_FAILURE);
} // Get variable screen information
if (-==xioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error reading variable information./n");
exit (EXIT_FAILURE);
}
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / ; if (- == xioctl (fd, VIDIOC_QUERYCAP, ∩)) {
if (EINVAL == errno) {
fprintf (stderr, "%s is no V4L2 device/n",dev_name);
exit (EXIT_FAILURE);
} else {
errno_exit ("VIDIOC_QUERYCAP");
}
} if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf (stderr, "%s is no video capture device/n",dev_name);
exit (EXIT_FAILURE);
} if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
fprintf (stderr, "%s does not support streaming i/o/n",dev_name);
exit (EXIT_FAILURE);
} CLEAR (cropcap); cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if ( == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) {
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c = cropcap.defrect; if (- == xioctl (fd, VIDIOC_S_CROP, &crop)) {
switch (errno) {
case EINVAL:
break;
default:
break;
}
}
}else { } CLEAR (fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = ;
fmt.fmt.pix.height = ;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (- == xioctl (fd, VIDIOC_S_FMT, &fmt))
errno_exit ("VIDIOC_S_FMT"); init_mmap (); } static void close_device (void)
{
if (- == close (fd))
errno_exit ("close");
fd = -;
close(fbfd);
} static void open_device (void)
{
struct stat st; if (- == stat (dev_name, &st)) {
fprintf (stderr, "Cannot identify '%s': %d, %s/n",dev_name, errno, strerror (errno));
exit (EXIT_FAILURE);
} if (!S_ISCHR (st.st_mode)) {
fprintf (stderr, "%s is no device/n", dev_name);
exit (EXIT_FAILURE);
} //open framebuffer
fbfd = open("/dev/fb0", O_RDWR);
if (fbfd==-) {
printf("Error: cannot open framebuffer device./n");
exit (EXIT_FAILURE);
} //open camera
fd = open (dev_name, O_RDWR| O_NONBLOCK, ); if (- == fd) {
fprintf (stderr, "Cannot open '%s': %d, %s/n",dev_name, errno, strerror (errno));
exit (EXIT_FAILURE);
}
} static void usage (FILE * fp,int argc,char ** argv)
{
fprintf (fp,
"Usage: %s [options]/n/n"
"Options:/n"
"-d | --device name Video device name [/dev/video]/n"
"-h | --help Print this message/n"
"-t | --how long will display in seconds/n"
"",
argv[]);
} static const char short_options [] = "d:ht:";
static const struct option long_options [] = {
{ "device", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "time", no_argument, NULL, 't' },
{ , , , }
}; int main (int argc,char ** argv)
{
dev_name = "/dev/video0"; for (;;)
{
int index;
int c; c = getopt_long (argc, argv,short_options, long_options,&index);
if (- == c)
break; switch (c) {
case :
break; case 'd':
dev_name = optarg;
break; case 'h':
usage (stdout, argc, argv);
exit (EXIT_SUCCESS);
case 't':
time_in_sec_capture = atoi(optarg);
break; default:
usage (stderr, argc, argv);
exit (EXIT_FAILURE);
}
} open_device (); init_device (); start_capturing (); run (); stop_capturing (); uninit_device (); close_device (); exit (EXIT_SUCCESS); return ;
} 这个测试程序是根据vivi驱动hard code的, 并不一定适合其他的camera驱动
比如,我手头上的logitech stv06xx usb camera, 因为不支持640x480模式,参见代码59 60行,
代码348行 if (- == xioctl (fd, VIDIOC_S_FMT, &fmt)) 应该是个协商的过程,
fmt.fmt.pix.width = ;
fmt.fmt.pix.height = ;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
这几行只是应用的期望格式,驱动会根据这个格式选择一个相近的格式返回,应用最后的显示处理要根据返回的格式进行处理,即process_image要做相应修改
V4L2 camera 驱动 capture测试程序【转】的更多相关文章
- v4l2 Camera详细设置【转】
转自:http://blog.csdn.net/smilefyx/article/details/39555289 转载自:http://blog.sina.com.cn/s/blog_602f877 ...
- camera驱动框架分析(下)
sensor的驱动 v4l2_i2c_new_subdev_board先用client = i2c_new_device(adapter, info);创建info对应的i2c_client对象(代表 ...
- 【转】android camera(四):camera 驱动 GT2005
关键词:android camera CMM 模组 camera参数 GT2005 摄像头常见问题 平台信息: 内核:linux系统:android 平台:S5PV310(samsung exyn ...
- DAVINCI DM6446 开发攻略——V4L2视频驱动和应用分析
针对DAVINCI DM6446平台,网络上也有很多网友写了V4L2的驱动,但只是解析Montavista linux-2.6.10 V4L2的原理.结构和函数,深度不够.本文决定把Montavis ...
- MTK6577+Android之Camera驱动
MTK6577+Android之Camera驱动 <MTK安卓平台的Camera效果在线调试> 1. Camera拍照相关概念 1.1 ISP isp--(Image Signa ...
- camera驱动框架分析(上)【转】
转自:https://www.cnblogs.com/rongpmcu/p/7662738.html 前言 camera驱动框架涉及到的知识点比较多,特别是camera本身的接口就有很多,有些是直接连 ...
- camera驱动框架分析(上)
前言 camera驱动框架涉及到的知识点比较多,特别是camera本身的接口就有很多,有些是直接连接到soc的camif口上的,有些是通过usb接口导出的,如usb camera.我这里主要讨论前者, ...
- (转)FS_S5PC100平台上Linux Camera驱动开发详解(二)
4-3 摄像头的初始化流程及v4l2子设备驱动 这个问题弄清楚了以后下面就来看获得Camera信息以后如何做后续的处理: 在fimc_init_global调用结束之后我们获得了OV9650的信息,之 ...
- Android高通平台调试Camera驱动全纪录
项目比较紧,3周内把一个带有外置ISP,MIPI数据通信,800万像素的camera从无驱动到实现客户全部需求. 1日 搭平台,建环境,编译内核,烧写代码. 我是一直在Window下搭个虚拟机登服务器 ...
随机推荐
- [Codeforces375D]Tree and Queries(莫队算法)
题意:给定一棵树,每个节点有颜色,对于每个询问(u,k)询问以u为根节点的子树下有多少种颜色出现次数>=k 因为是子树,跟dfs序有关,转化为一段区间,可以用莫队算法求解 直接用一个数组统计出现 ...
- 15、python之导入模块
一.什么是模块? 模块本质是一个py文件,我们可以通过关键字import将py文件对象导入到当前名称空间. 二.导入模块 1.import module 2.from module import ob ...
- WPF仿酷狗页面
原文:WPF仿酷狗页面 版权声明:本文为博主原创文章,如需转载请标明转载地址 http://blog.csdn.net/u013981858 https://blog.csdn.net/u013981 ...
- 3226: [Sdoi2008]校门外的区间
链接 思路 bug漫天飞... 维护一颗线段树,支持区间赋值,和区间异或.因为会处理到一些方括号还是圆括号的问题,所以对于每一个下标都乘2,假设中间有一个.5即可,都变成了方括号,输出在处理一下. U ...
- python语法root=Tkinter.Tk()
1. Tkinter 是一个python模块,是一个调用Tcl/Tk的接口,它是一个跨平台的脚本图形界面接口.Tkinter不是唯一的python图形编程接口,但是是 其中比较流行的一个.最大的特点是 ...
- 《Cracking the Coding Interview》——第18章:难题——题目2
2014-04-29 00:59 题目:设计一个洗牌算法,效率尽量快点,必须等概率. 解法:每次随机抽一张牌出来,最后都抽完了,也就洗好了.时间复杂度O(n^2),请看代码. 代码: // 18.2 ...
- webstrom11 vue插件配置
直接上图 1. 安装vue插件 2.添加模板 3.指定模板类型 最新的是插件 是 vue.js 创建完 Vue File 文件后 需要在 下面这里关联一下
- selenium + python之元素定位
selenium对web各元素的操作首先就要先定位元素,定位元素的方法主要有以下几种:通过id定位元素:find_element_by_id("id_vaule")通过name定位 ...
- apt-get阿里源
备份原有配置文件 mv /etc/apt/sources.list /etc/apt/sources.list.bak 新建一个文件 vi /etc/apt/sources.list 复制以下内容到新 ...
- C 语言 进阶
清单狂魔,只挖坑不填坑.. 前言 最近经常被询问 C 语言 相关的问题,突然便也觉得需要思考一下 C 语言的进阶了. 我用 C 语言写过的最大的一个项目,也只是那个贪吃蛇,后来就断断续续地用 Pyth ...