在raspberry上使用USB摄像头做视频采集

以前看过国嵌的H.264视频采集程序,想在树莓派上试一试,现在记录一下自己尝试的过程。

检查是否支持USB摄像头

插入USB摄像头前

pi@raspberrypi:~$ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. 

插入USB摄像头后

pi@raspberrypi:~$ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. 
Bus 001 Device 004: ID 1e4e:0109 

可以看到raspberry已经识别了USB摄像头。

要想拍摄照片,你要先安装fswebcam,这是一款小型摄像头程序。可以直接通过Raspbian的仓库来安装fswebcam。
$ sudo apt-get install fswebcam
fswebcam安装完成后,在终端中运行下面的命令来抓一张来自摄像头的照片:

$ fswebcam --no-banner -r 640x480 image.jpg
pi@raspberrypi:~$ fswebcam --no-banner -r 640x480 image.jpg
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
--- Capturing frame...
Captured frame in 0.00 seconds.
--- Processing captured image...
Disabling banner.
Writing JPEG image to 'image.jpg'.

V4L(Video for Linux 标准,按照统一的公共接口去使用不同种类的USB摄像头)
驱动程序与应用程序之间的统一接口,双方都必须遵守该接口的定义。

在宿主机上进行编译,然后将可执行文件放到树莓派上,执行server_arm程序后报错:

pi@raspberrypi:~/H264$ ./server_arm 
start 2.0...
Can't get device information: VIDIOCGCAP
Device name:
Width:0 ~ 0
Height:0 ~ 0
ERROR:VIDIOCGWIN
ERROR:VIDIOCSWIN
ERROR:VIDIOCGPICT
ERROR: VIDIOCSPICT,Can't set video_picture format
ERROR:VIDIOCGMBUF,Can't get video_mbuf
Frames:0
ERROR:mmap
Buffer size:0
Offset:0
ERROR: VIDIOCMCAPTURE
ERROR: VIDIOCSYNC
Segmentation fault

发现是由于获取摄像头基本信息失败造成的,如下所示:

ret = ioctl( cam_fd,VIDIOCGCAP,&cam_cap );  /* 获取摄像头的基本信息 */
if( ret<0 ) {
    printf("Can't get device information: VIDIOCGCAP\n");
}

查证后,发现在V4L2中,规定必须实现 VIDIOC_QUERYCAP命令,而V4L则规定必须实现VIDIOCGCAP,决定尝试改为V4L2的命令,重新编译、运行,有人遇到过该问题v4l(video for Linux)使用摄像头实验的一点小感慨。关于V4L2与V4L的关系可以参考V4L简介及其与V4L2区别。

可以看出raspberry已经安装了V4L2的内核模块,如下:

pi@raspberrypi:~/H264$ lsmod | grep v4l
v4l2_common 3777  1 videobuf2_core
videodev  121307  3 uvcvideo,v4l2_common,videobuf2_core

在宿主机上安装V4L的库

zfchen@zfchen-E440:/$ sudo apt-get install libv4l-dev

查看库文件的安装路径

zfchen@zfchen-E440:/usr/lib$ dpkg -L libv4l-dev
/.
/usr
/usr/include
/usr/include/libv4l1-videodev.h
/usr/include/libv4l1.h
/usr/include/libv4l2.h
/usr/include/libv4lconvert.h
/usr/lib
/usr/lib/i386-linux-gnu
/usr/lib/i386-linux-gnu/pkgconfig
/usr/lib/i386-linux-gnu/pkgconfig/libv4l1.pc
/usr/lib/i386-linux-gnu/pkgconfig/libv4l2.pc
/usr/lib/i386-linux-gnu/pkgconfig/libv4lconvert.pc
/usr/share
/usr/share/doc
/usr/lib/i386-linux-gnu/libv4l1.so
/usr/lib/i386-linux-gnu/libv4l2.so
/usr/lib/i386-linux-gnu/libv4lconvert.so
/usr/share/doc/libv4l-dev

从Linux内核中找到了V4L2的头文件,添加到H264/app/目录下。 头文件路径为:include/linux/videodev2.h头文件,实际上指向/include/uapi/linux/videodev2.h头文件(该路径下面还有v4l2-common.hv4l2-common.h文件)。
编译,make 输出信息如下,包含一些警告信息:

zfchen@zfchen-E440:~/my_repository/H264/app$ make
arm-bcm2708hardfp-linux-gnueabi-cc-c -o server_arm.o server_arm.c
server_arm.c: In function 'init_encoder':
server_arm.c:265:14: warning: assignment makes pointer from integer without a cast [enabled by default]
server_arm.c: In function 'main':
server_arm.c:337:3: warning: passing argument 1 of 'printf' from incompatible pointer type [enabled by default]
In file included from server_arm.c:7:0:
/home/zfchen/my_repository/tools/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/../arm-bcm2708hardfp-linux-gnueabi/sysroot/usr/include/stdio.h:359:12: note: expected 'const char * __restrict__' but argument is of type 'struct _IO_FILE *'

编译通过后,发现执行还是有错,错误信息如下:

pi@raspberrypi:~$ ./server_arm fastspeed.txt 
start 2.0...
Device name:uvcvideo
Width:0 ~ 943285811
Height:761426805 ~ 808464432
ERROR:VIDIOCGWIN
ERROR:VIDIOCSWIN
ERROR:VIDIOCGPICT
ERROR: VIDIOCSPICT,Can't set video_picture format
ERROR:VIDIOCGMBUF,Can't get video_mbuf
Frames:0
ERROR:mmap
Buffer size:0
Offset:0
ERROR: VIDIOCMCAPTURE
ERROR: VIDIOCSYNC
Segmentation fault

修改 VIDIOCGWIN 指令之后仍然报错,没弄明白。
然后找到一篇根据国嵌的程序改的v4l2程序 ,使用这个代码后发现,服务器端可以执行,但是客户端(PC)的上位机显示为花屏。

你可能感兴趣的:(嵌入式与Linux)