下面将给出Hi3559AV100外接UVC/MJPEG相机实时采图设计的整体流程,主要实现是通过V4L2接口将UVC/MJPEG相机采集的数据送入至MPP平台,经过VDEC、VPSS、VO最后通过HDMI的输出,给出(二)V4L2接口的实现。
可以先参照前面随笔介绍(一)Linux USB摄像头驱动加载与分析:https://www.cnblogs.com/iFrank/p/14399421.html
板载平台:BOXER-8410AI
芯片型号:Hi3559AV100
相机型号:Logitch c270
开发环境:VM15.5+ubuntu16.04+Hilinux
1、V4L2接口说明
V4L2是Video for linux2的简称,为linux中关于视频设备的内核驱动。在Linux中,视频设备是设备文件,可以像访问普通文件一样对其进行读写,摄像头在/dev/video*下,如果只有一个视频设备,通常为/dev/video0。V4L2是内核提供给应用程序访问音、视频驱动的统一接口。V4L2 的相关定义包含在头文件<linux/videodev2.h> 中。
IOCTL的实现V4L2的控制
1:分配内存
2 VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
3 VIDIOC_QUERYCAP:查询驱动功能
4 VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
5 VIDIOC_S_FMT:设置当前驱动的频捕获格式
6 VIDIOC_G_FMT:读取当前驱动的频捕获格式
7 VIDIOC_TRY_FMT:验证当前驱动的显示格式
8 VIDIOC_CROPCAP:查询驱动的修剪能力
9 VIDIOC_S_CROP:设置视频信号的边框
10 VIDIOC_G_CROP:读取视频信号的边框
11 VIDIOC_QBUF:把数据放回缓存队列
12 VIDIOC_DQBUF:把数据从缓存中读取出来
13 VIDIOC_STREAMON:开始视频显示函数
14 VIDIOC_STREAMOFF:结束视频显示函数
15 VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。
这些IO调用,有些是必须的,有些是可选择的,其命令标志符在在头文件<linux/videodev2.h> 定义,具体如下:
1 #define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability)
2 #define VIDIOC_RESERVED _IO('V', 1)
3 #define VIDIOC_ENUM_FMT _IOWR('V', 2, struct v4l2_fmtdesc)
4 #define VIDIOC_G_FMT _IOWR('V', 4, struct v4l2_format)
5 #define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format)
6 #define VIDIOC_REQBUFS _IOWR('V', 8, struct v4l2_requestbuffers)
Logitch c270支持的像素格式有两种:
1 YUYV 4:2:2 2 Motion-JPEG
2、V4L2的实现流程
动态视频采集流程:
部分代码实现:
1 /*打开视频*/
2 if ((fd = open(FILE_VIDEO, O_RDWR)) == -1)
3 {
4 printf("Error opening V4L interface\n");
5 return (FALSE);
6 }
7
8 /*读video_capability中信息。
9 通过调用IOCTL函数和接口命令VIDIOC_QUERYCAP查询
10 摄像头的信息*/
11 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1)
12 {
13 printf("Error opening device %s: unable to query device.\n",FILE_VIDEO);
14 return (FALSE);
15 }
16 else
17 {
18 printf("driver:\t\t%s\n",cap.driver);
19 printf("card:\t\t%s\n",cap.card);
20 printf("bus_info:\t%s\n",cap.bus_info);
21 printf("version:\t%d\n",cap.version);
22 printf("capabilities:\t%x\n",cap.capabilities);
23
24 /*其中capabilities: 4000001通过与各种宏位与,
25 可以获得物理设备的功能属性*/
26 if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE)
27 {
28 printf("Device %s: supports capture.\n",FILE_VIDEO);
29 }
30
31 if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING)
32 {
33 printf("Device %s: supports streaming.\n",FILE_VIDEO);
34 }
35 } //VIDIOC_QUERYCAP对应唯一结构体
3、V4L2测试(640×480像素一帧图片输出)
我板载上装的是Logitch c270摄像头,从摄像头支持的图像像素输出的信息可以看出,在Hi3559板载上可以支持2种像素格式,这里选用的是V4L2_PIX_FMT_YUV422 格式。从生成image的大小可以判断出是正确的(YUV422数据大小 = 长 * 宽 * 1.5 = 640 * 480 * 2 = 614400 bytes = 600k)可以将image文件拷出来,使用pYUV 软件查看YUV图片。这里需要注意,使用pYUV 查看YUV图片的时候,需要正确设置图片格式,按我上面代码采集的数据格式,最后一帧图片输出结果如下:
之后随笔将推出结合MPP平台实现视频流的输出。
问题:
在虚拟机上,脚本运行正常,但是会卡在视频采集处,个人认为是虚拟机的缓存问题,而板载缓存比较充足,所以能够很好实现。