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下搭个虚拟机登服务器 ...
随机推荐
- DFS初级剪枝及心得
关于DFS心得: 1.利用结构体,记录mark和题目要求的基本属性. 2.用到递归,使用递归时注意要设置出口,即符合要求时return,注意对递归的理解,对于不同情况可能要传递不同的参数,但出口都是一 ...
- 笔记-Python-language reference-5.the import system
笔记-Python-language reference-5.the import system 前言 经常用到import,module,对其中的机制及原理有一定的了解,但没有将各种信息前后连通起来 ...
- Git-历史穿梭
图形工具:gitk gitk是最早实现的一个图形化的Git版本库浏览器软件,基于tcl/tk实现,因此gitk非常简洁,本身就是一个1万多行的tcl脚本写成的.gitk的代码已经和Git的代码放在同一 ...
- idea 项目jar包出错
找到jar包所在文件目录,删除下面的所有文件,刷新maven项目,重新引入jar包
- Android 本应用数据清除管理器DataCleanManager
1.整体分析 1.1.源代码先给出了,可以直接Copy. /** * 本应用数据清除管理器 */ public class DataCleanManager { /** * * 清除本应用内部缓存(/ ...
- NC-瑞士军刀NetCat
NC——Telnet/Banner 连接之后可以命令互动,比如POP3\SMTP\HTTP等协议命令 root@kali:/# nc -v pop3..com //-v详细显示 DNS fwd/rev ...
- 减少Android staido 占用C 盘
1.gradle 更换文件夹: 设置GRADLE_USER_HOME环境变量 在/etc/profile或~/.bash_profile增加如下: export GRADLE_USER_HOME=D: ...
- jQuery的Ajax初识
1. 什么是Ajax? Ajax是“Asynchronous Javascript And XML(异步Javascript和XML)”的缩写, 是指一种创建交互式网页应用的网站开发技术. Ajax不 ...
- imageX.exe
imageX 编辑ImageX 是一个命令行工具,原始设备制造商 (OEM) 和公司可以使用它来捕获.修改和应用基于文件的磁盘映像以进行快速部署.ImageX 可以使用 Windows 映像 (.wi ...
- Http状态码枚举(摘自 Microsoft 程序集 System.dll)
// 摘要: // 包含为 HTTP 定义的状态代码的值. public enum HttpStatusCode { // 摘要: // 等效于 HTTP 状态 100. System.Net.Htt ...