Andrew Huang 转载请注明作者及网址
1.设备性能查询
v4l设备里中,使用ioctl的VIDIOCGCAP来查询设备的,这里v4l规定必须实现的操作.
struct video_capability cap;
memset(&cap,0,sizeof(cap));
ret = ioctl(fd, VIDIOCGCAP, &cap);
其中struct video_capability定义在linux/videodevice.h.定义如下
struct video_capability
{
char name[32];
int type;
int channels; /* Num channels */
int audios; /* Num audio devices */
int maxwidth; /* Supported width */
int maxheight; /* And height */
int minwidth; /* Supported width */
int minheight; /* And height */
}; |
另外查询设备输入/输出通道,也是基本要求,用VIDIOCGCHAN命令
struct video_channel channel;
int i;
PRINT_V4L("channels\n");
for(i=0; i<count;i++)
{
memset(&channel,0,sizeof(channel));
channel.channel = i;
if (-1 == ioctl(fd,VIDIOCGCHAN,&channel)) {
continue;
}
} |
其中数据结构定义如下:
struct video_channel
{
int channel;
char name[32];
int tuners;
__u32 flags;
#define VIDEO_VC_TUNER 1 /* Channel has a tuner */
#define VIDEO_VC_AUDIO 2 /* Channel has audio */
__u16 type;
#define VIDEO_TYPE_TV 1
#define VIDEO_TYPE_CAMERA 2
__u16 norm; /* Norm set by channel */
}; |
2.实现代码
v4l设备里中,使用ioctl的VIDIOCGPICT来查询设备的支持视频格式
struct video_picture pic;
memset(&pic,0,sizeof(pic));
ret = ioctl(fd, VIDIOCGPICT, &pic);
其中video_picture的定义如下,plalette定义就是视频格式。
- struct video_picture
-
{
-
__u16 brightness;
-
__u16 hue;
-
__u16 colour;
-
__u16 contrast;
-
__u16 whiteness; /* Black and white only */
-
__u16 depth; /* Capture depth */
-
__u16 palette; /* Palette in use */
-
#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */
-
#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */
-
#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */
-
#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */
-
#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */
-
#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */
-
#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */
-
#define VIDEO_PALETTE_YUYV 8
-
#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */
-
#define VIDEO_PALETTE_YUV420 10
-
#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */
-
#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */
-
#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */
-
#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */
-
#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */
-
#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */
-
#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */
-
#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */
-
};
3.实现代码
- /*
-
* Author: Andrew Huang <bluedrum@163.com>
-
* query v4l1 device capabilities
-
* date: 2010/06/16
-
*/
-
#include <stdio.h>
-
#include <string.h>
-
#include <errno.h>
-
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
-
#include <linux/videodev.h>
-
-
#define PRINT_V4L printf
-
-
#define PRINT_IOCTL_CMD(cmd) printf(" %15s = (0x%x)\n",#cmd,cmd)
-
#define PRINT_IOCTL_CMD2(cmd,n) printf(" %-20s(%d) = (0x%x)\n",#cmd,n,cmd)
-
-
#define PRINT_V4L_MEMBER(m) printf(" %-20s:",#m);
-
#define PRINT_V4L_STRING(m) printf(" %-20s:\"%s\"\n",#m,m)
-
#define PRINT_V4L_INT(m) printf(" %-20s:%d\n",#m,m)
-
#define PRINT_V4L_INTX(m) printf(" %-20s:0x%x\n",#m,m)
-
-
/* 显示enum 值的之一*/
-
#define TEST_V4L_FLAG0(m,f) printf("%s",((m & f)==f)?#f:"")
-
-
/* 显示一个组合值的所有内容 */
-
#define PRINT_V4L_FLAGS(m) printf(" %-20s:0x%x [",#m,m) /* 组合值开始*/
-
#define TEST_V4L_FLAG(m,f) printf("%s",((m & f)==f)?#f",":"") /* 组合值中间值,可以有多个*/
-
#define PRINT_V4L_FLAGS2(m) printf("]\n") /* 组合值结束*/
-
-
-
#define PRINT_INT(e) printf("%s=%d\n",#e,e)
-
-
-
int v4l_get_channels(int fd,int count)
-
{
-
struct video_channel channel;
-
int i;
-
-
PRINT_V4L("channels\n");
-
-
-
for(i=0; i<count;i++)
-
{
-
memset(&channel,0,sizeof(channel));
-
channel.channel = i;
-
if (-1 == ioctl(fd,VIDIOCGCHAN,&channel)) {
-
-
continue;
-
}
-
-
PRINT_IOCTL_CMD2(VIDIOCGCAP,i);
-
-
PRINT_V4L_INT(channel.channel);
-
PRINT_V4L_STRING(channel.name);
-
PRINT_V4L_INT(channel.tuners);
-
-
-
PRINT_V4L_FLAGS(channel.flags);
-
TEST_V4L_FLAG(channel.flags,VIDEO_VC_TUNER);
-
TEST_V4L_FLAG(channel.flags,VIDEO_VC_AUDIO);
-
PRINT_V4L_FLAGS2(channel.flags);
-
-
-
PRINT_V4L_FLAGS(channel.type);
-
TEST_V4L_FLAG(channel.type,VIDEO_TYPE_TV);
-
TEST_V4L_FLAG(channel.type,VIDEO_TYPE_CAMERA);
-
PRINT_V4L_FLAGS2(channel.type);
-
-
PRINT_V4L_INT(channel.norm);
-
-
}
-
-
-
-
}
-
-
int v4l_query_video_cap(int fd)
-
{
-
int ret;
-
struct video_capability cap;
-
memset(&cap,0,sizeof(cap));
-
ret = ioctl(fd, VIDIOCGCAP, &cap);
-
if(ret < 0)
-
{
-
printf("get vidieo capability error,error code: %d \n", errno);
-
return ret;
-
}
-
PRINT_V4L("general info\n");
-
PRINT_IOCTL_CMD(VIDIOCGCAP);
-
-
PRINT_V4L_STRING(cap.name);
-
PRINT_V4L_INT(cap.channels);
-
PRINT_V4L_INT(cap.audios);
-
PRINT_V4L_INT(cap.maxwidth);
-
PRINT_V4L_INT(cap.maxheight);
-
PRINT_V4L_INT(cap.minwidth);
-
PRINT_V4L_INT(cap.minheight);
-
-
-
-
PRINT_V4L_FLAGS(cap.type);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_CAPTURE);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_TUNER);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_TELETEXT);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_OVERLAY);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_CHROMAKEY);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_CLIPPING);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_FRAMERAM);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_SCALES);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_MONOCHROME);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_SUBCAPTURE);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_MPEG_DECODER);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_MPEG_ENCODER);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_MJPEG_DECODER);
-
TEST_V4L_FLAG(cap.type,VID_TYPE_MJPEG_ENCODER);
-
-
-
PRINT_V4L_FLAGS2(cap.type);
-
-
v4l_get_channels(fd,cap.channels);
-
return 0;
-
-
}
-
-
-
-
int v4l_query_video_picture(int fd)
-
{
-
-
int ret;
-
struct video_picture pic;
-
memset(&pic,0,sizeof(pic));
-
-
ret = ioctl(fd, VIDIOCGPICT, &pic);
-
if(ret < 0)
-
{
-
printf("get vidieo picture error,error code: %d \n", errno);
-
return ret;
-
}
-
-
-
PRINT_IOCTL_CMD(VIDIOCGPICT);
-
PRINT_V4L_INT(pic.brightness);
-
PRINT_V4L_INT(pic.hue);
-
PRINT_V4L_INT(pic.colour);
-
PRINT_V4L_INT(pic.contrast);
-
PRINT_V4L_INT(pic.whiteness);
-
PRINT_V4L_INT(pic.depth);
-
-
PRINT_V4L_MEMBER(pic.palette);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_GREY);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_HI240);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_RGB565);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_RGB24);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_RGB32);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_RGB555);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_YUV422);;
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_YUYV);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_UYVY);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_YUV420);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_YUV411);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_RAW);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_YUV422P);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_YUV411P);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_YUV420P);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_YUV410P);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_PLANAR);
-
TEST_V4L_FLAG0(pic.palette,VIDEO_PALETTE_COMPONENT);
-
-
PRINT_V4L("\n");
-
-
return 0;
-
}
-
int main(int argc,char * argv[])
-
{
-
char dev_name[64] = "/dev/video2";
-
int cam_fd =-1;
-
-
if(argc>1)
-
{
-
strncpy(dev_name,argv[1],sizeof(dev_name)-1);
-
}
-
-
-
cam_fd = open(dev_name,O_RDWR|O_NONBLOCK);
-
-
if(cam_fd == -1)
-
{
-
printf("open failure \n");
-
return -1;
-
}
-
-
-
printf("### v4l device info [%s] ###\n",dev_name);
-
-
-
v4l_query_video_cap(cam_fd);
-
-
v4l_query_video_picture(cam_fd);
-
// get_supported_video_formats(cam_fd);
-
close(cam_fd);
-
-
return 0;
-
-
}
4.测试结果
使用mini6410,Linux 2.6.28.6,注意这里/dev/video0 ,/dev/video1,是CMOS摄像头,它们的驱动对于 V4l1,并且一运行某些V4L1的ioctl命令的就产生oops.
关于修正这一些BUG,可以参见我的博文
<信息的分析>>
http://blog.chinaunix.net/space.php?uid=20587912&do=blog&id=2163944
使用用
USB摄像头
,我使用的是
ZC301摄像头
.设备结点是
/dev/video2
三种测试结果如下
:
./test_v4l /dev/video2
### v4l device info [/dev/video2] ###
general info
VIDIOCGCAP = (0x803c7601)
cap.name :"PC Camera"
cap.channels :1
cap.audios :0
cap.maxwidth :640
cap.maxheight :480
cap.minwidth :48
cap.minheight :32
cap.type :0x1 [VID_TYPE_CAPTURE,]
channels
VIDIOCGCAP (0) = (0x803c7601)
channel.channel :0
channel.name :"zc3xx"
channel.tuners :0
channel.flags :0x0 []
channel.type :0x2 [VIDEO_TYPE_CAMERA,]
channel.norm :0
VIDIOCGPICT = (0x800e7606)
pic.brightness :32896
pic.hue :0
pic.colour :0
pic.contrast :32768
pic.whiteness :39321
pic.depth :8
pic.palette :
-----------------------------------------------------------------------
./test_v4l /dev/video0
### v4l device info [/dev/video0] ###
general info
VIDIOCGCAP = (0x803c7601)
cap.name :"s3c-fimc0"
cap.channels :2
cap.audios :0
cap.maxwidth :0
cap.maxheight :0
cap.minwidth :48
cap.minheight :32
cap.type :0x29 [VID_TYPE_CAPTURE,VID_TYPE_OVERLAY,VID_TYPE_CLIPPING,]
channels
VIDIOCGCAP (0) = (0x803c7601)
channel.channel :0
channel.name :"External Camera Input"
channel.tuners :0
channel.flags :0x0 []
channel.type :0x2 [VIDEO_TYPE_CAMERA,]
channel.norm :0
VIDIOCGCAP (1) = (0x803c7601)
channel.channel :1
channel.name :"Memory Input"
channel.tuners :0
channel.flags :0x0 []
channel.type :0x2 [VIDEO_TYPE_CAMERA,]
channel.norm :0
VIDIOCGPICT = (0x800e7606)
pic.brightness :0
pic.hue :0
pic.colour :0
pic.contrast :0
pic.whiteness :0
pic.depth :32
pic.palette :
[root@FriendlyARM 2]#
--------------------------------------------------------------------------------------------------------------------------
./test_v4l /dev/video1
### v4l device info [/dev/video1] ###
general info
VIDIOCGCAP = (0x803c7601)
cap.name :"s3c-fimc1"
cap.channels :2
cap.audios :0
cap.maxwidth :0
cap.maxheight :0
cap.minwidth :48
cap.minheight :32
cap.type :0x29 [VID_TYPE_CAPTURE,VID_TYPE_OVERLAY,VID_TYPE_CLIPPING,]
channels
VIDIOCGCAP (0) = (0x803c7601)
channel.channel :0
channel.name :"External Camera Input"
channel.tuners :0
channel.flags :0x0 []
channel.type :0x2 [VIDEO_TYPE_CAMERA,]
channel.norm :0
VIDIOCGCAP (1) = (0x803c7601)
channel.channel :1
channel.name :"Memory Input"
channel.tuners :0
channel.flags :0x0 []
channel.type :0x2 [VIDEO_TYPE_CAMERA,]
channel.norm :0
VIDIOCGPICT = (0x800e7606)
pic.brightness :0
pic.hue :0
pic.colour :0
pic.contrast :0
pic.whiteness :0
pic.depth :32
pic.palette :
[root@FriendlyARM 2]#
阅读(760) | 评论(0) | 转发(0) |