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下搭个虚拟机登服务器 ...
随机推荐
- ABAP自定义截取字符串长度函数
SAP 中strlen()只能计算字符串的个数,不能计算含有中文字符串的长度,如字符串“SAP大波霸”,strlen('SAP大波霸') = 6,其实真实长度为3+3*2 = 9.我们可以通过cl_a ...
- ARC下还会存在内存泄露吗?
1.第三方框架不正当使用.2.block,delegate,NSTimer循环使用.3.非oc对象的内存处理.4.地图类处理.5.大次数循环内存暴涨. 非oc对象的释放: 例如使用CGImageRel ...
- 《Cracking the Coding Interview》——第3章:栈和队列——题目2
2014-03-18 05:08 题目:实现一个栈,除了能进行push和pop之外,还能在O(1)时间内返回栈中最小的元素. 解法:用另一个“最小栈”存放最小的元素,每当有不小于当前最小值的元素进栈时 ...
- Visual Studio使用技巧笔记(引用程序集自动复制dll到引用项目目录)
copy /y $(TargetPath) $(SolutionDir)\[您项目引用dll文件的目录]\$(TargetFileName) 例如:copy /y $(TargetPath) $(So ...
- XSS注入常用语句积累
<script>alert('hello,gaga!');</script> //经典语句,哈哈! >"'><img src="javas ...
- 每天一个Linux命令(5):rm命令
rm命令可以删除一个目录中的一个或多个文件或目录,也可以将某个目录及其下属的所有文件及其子目录均删除掉.对于链接文件,只是删除整个链接文件,而原有文件保持不变. 语法 rm (选项)(参数) 选项 - ...
- 基于vue 2.X和高德地图的vue-amap组件获取经纬度
今天我就讲了一下怎么通过vue和高德地图开发的vue-amap组件来获取经纬度. 这是vue-amap的官网文档:https://elemefe.github.io/vue-amap/#/ 这是我的码 ...
- 对于进程没杀死占用内存和cpu行为的方法
在跑机器学习或者深度学习的过程中有可能遇到没杀死进程的情况,但是程序的入口又没关掉,尤其是我使用jupyter从远程Linux映射到windows浏览器跑程序的时候 对于上面的问题, 首先运行 hto ...
- Linux下samba编译与安装(Ubuntu和嵌入式linux)
Ubuntu[i386-linux下安装过程] 1.安装samba $ sudo apt-get install samba $ sudo apt-get install smbfs (可选) $ s ...
- MyBatis:SQL语句中的foreach标签的详细介绍
foreach 也就是遍历迭代,在SQL中通常用在 in 这个关键词的后面 foreach元素的属性主要有 item,index,collection,open,separator,close. 分别 ...