Video4linux2(简称V4L2),是linux中关于视频设备的内核驱动。
V4L2较V4L有较大的改动,并已成为2.6的标准接口,函盖video\dvb\FM...,多数驱动都在向V4l2迁移。更好地了解V4L2先从应用入手,然后再深入到内核中结合物理设备/接口的规范实现相应的驱动。V4L2采用流水线的方式,操作更简单直观,基本遵循打开视频设备、设置格式、处理数据、关闭设备,更多的具体操作通过ioctl函数来实现。
在Linux中,视频设备是设备文件,可以像访问普通文件一样对其进行读写,摄像头在/dev/video0下。
操作系统一般把系统使用的内存划分成用户空间和内核空间,分别由应用程序管理和操作系统管理。应用程序可以直接访问内存的地址,而内核空间存放的是供内核访问的代码和数据,用户不能直接访问。v4l2捕获的数据,最初是存放在内核空间的,这意味着用户不能直接访问该段内存,必须通过某些手段来转换地址。
v4l2一共有三种视频采集方式:使用read、write方式;内存映射方式和用户指针模式。
read、write方式,在用户空间和内核空间不断拷贝数据,占用了大量用户内存空间,效率不高。
内存映射方式:把设备里的内存映射到应用程序中的内存控件,直接处理设备内存,这是一种有效的方式。上面的mmap函数就是使用这种方式。
用户指针模式:内存片段由应用程序自己分配。这点需要在v4l2_requestbuffers里将memory字段设置成V4L2_MEMORY_USERPTR。
注意:
利用v4l2采集时,ARM上的采集卡支持3种模式,普通usb摄像头不支持直接读取模式;
采集卡支持V4L2_PIX_FMT_YUYV和V4L2_PIX_FMT_YUV420;
但是普通usb摄像头不支持V4L2_PIX_FMT_YUV420
captrue(直接读取方式):
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <malloc.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> /* for videodev2.h */
#include <linux/videodev2.h>
#define CODEC_NODE "/dev/video0"
#define LCD_WIDTH 320
#define LCD_HEIGHT 240
#define YUV_FRAME_BUFFER_SIZE (LCD_WIDTH*LCD_HEIGHT)+(LCD_WIDTH*LCD_HEIGHT)/2 /* YCBCR 420 */
static int cam_c_init(void);
static void exit_from_app() ;
static int cam_c_fp = -1;
static void exit_from_app()