基于V4L2的视频远程监控

前面的一篇文章说到MINI2440 ARM开发板可以跑HTTP服务器,因此可以在上面开发一些web应用。甚至可以进行视频远程监控。

远程视频监控的原理和控制IO口类似,都是首先必须有一个web服务器。在视频监控方案中,程序读取linux底层的USB摄像头驱动获取视频数据,然后经由服务器通过TCP/IP协议传到网页上进行显示。传输的视频图像数据格式采用流媒体编码。这种流媒体编码格式适应于网络传输并进行实时显示,不像rmvb或者mp4这种格式必须全部下载完毕才能解码播放。它把视频分成更小的单元来进行压缩编码并传输。

现在有两种方案来实现远程视频监控:

1.基于开源项目MJPEG-Streamer,利用V4L2底层驱动,把MJPEG格式转换为流媒体进行传输,然后在浏览器中通过访问内建的网页来浏览视频。

2.接近真实的IP-camera方案,也是利用V4L2视频驱动,配合ffmpe,X264的软件解码,通过UDP上传至PC显示。USB摄像头得到的数据格式一般是YUV422,可以利用开源库进行编解码。


##MIPEG-Streamer方案## MIPEG-Streamer是一个开源项目,托管在github上[1]。它可以支持CMOS,USB摄像头。不支持MJPEG格式的USB摄像头也可以使用。笔者采用的安装步骤如下:

1.到网站https://code.google.com/p/mjpg-streamer-mini2440下载binary package compiled for mini2440 based on r9。也可以下载源码自己进行编译。

2.把下载的文件通过FTP或者NFS传到ARM开发板上。新建目录mkdir WebVideo并解压到此目录下。

3.由于自己使用的USB摄像头没有MJPG支持,运行脚本start_uvc_yuv.sh

4.查看arm开发板上的ip地址,在PC浏览器中输入ip:8080/?action=stream就可以看见摄像头的视频了。

终端显示如下:

图片


##IP-Camera方案## IP-Camera的方案像IP电话的IP包一样,获取视频数据后压缩传输,然后在客户端进行解码。里面最重要的部分是业务逻辑,语言和API调用只是基础。

笔者采用[3]中提到的方式进行编译调试,主要分为两部分。一个是ARM上的Server程序,一个是PC上的Shower程序。它们都需要使用库ffmpeg来进行视频编解码,Server是编码,Shower是解码。因此Server的ffmpeg需要交叉编译为arm版本,PC上的ffmpeg编译为PC版本。


##编译动态链接库.so## ARM上linux内核没有提供IP-Camera应用程序处理视频图像的函数库,可以选择直接把处理视频图像的源代码加入到应用程序中交叉编译。或者把这些库编译成动态链接库.so,直接拷贝到开发板里。

静态链接库和动态链接库主要有下面的区别:

1.静态链接库对函数库的链接是放在编译期间(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接并合成一个可执行文件(executable file)。程序在运行时,与函数库无关,所有需要的函数已拷贝到可执行文件中。所以这些函数库被成为静态库(static libaray),文件名为“libxxx.a”的形式

2.动态链接库(dynamic link library)技术可以把库函数的链接载入推迟到程序运行期间(runtime)。

现在需要交叉编译的动态链接库(依赖库)有3个:对其他软件底层支持的zlib.so,支持编译ffmpeg的x264.so,进行视频处理的ffmpeg.so。

编译zlib的步骤:

1.解压zlib-1.2.5.tar.gz tar -xzvf zlib-1.2.5.tar.gz

2.运行configure配置makefile ./configure /opt/WebVideo默认配置后会在当前目录下生成Makefile

3.修改Makefile以便能够用arm-linux-gcc编译,把gcc改成arm-linux-gcc,ar改成arm-linux-ar即可。

4.然后makemake install,在/opt/WebVideo目录下就能看见/lib /include /bin文件夹了。

编译好的zlib.so库可以用nm -D libz.so 命令查看支持哪些函数调用,如图所示:

图片

x264.so和ffmpeg.so的编译方法一样。


##编译Server## Makefile如下:

all:webcam_server 
  
CC=arm-linux-g++
LD=arm-linux-ld
CXXFLAGS=  -c -g -O0 -fPIC -I./ffmpeg/include -L./ffmpeg/lib  
    
OBJS_SERVER=  capture.o vcompress.o sender.o server.o
LIBS_SERVER=  -lavcodec -lswscale -lavutil -lx264 -lpthread -lz

.cpp.o:
       $(CC) $(CXXFLAGS) $<
    
webcam_server: $(OBJS_SERVER)
       $(CC) -o $@ $^ -L./ffmpeg/lib $(LIBS_SERVER)
  
clean:
       rm -f *.o
       rm -f webcam_server

##编译Shower## Shower的显示采用X11库,所以先下载依赖包

sudo apt-get intall libx11-dev

sudo apt-get install libxext-dev

libxext-dev对应于头文件X11/extensions/XShm.h,编译的时候还遇到很多问题,比如链接库找不到[10]等等。细节不在这里贴出。

Makefile如下:

all: webcam_shower
CC=g++
LD=ld
    
CXXFLAGS=  -c -g -O0 -fPIC -I./ffmpeg/include -L./ffmpeg/lib  

OBJS_SHOWER=  vshow.o shower.o
LIBS_SHOWER=  -lavcodec -lswscale -lavutil -lx11 -lXext
    
.cpp.o:
$(CC) $(CXXFLAGS) $<
    
webcam_shower: $(OBJS_SHOWER)
$(CC) -o $@ $^ -L./ffmpeg/lib $(LIBS_SHOWER)
    
clean:
rm -f *.o
rm -f webcam_shower

##视频采集方式## 操作系统一般把系统使用的内存分为用户空间和内核空间。而内核空间的数据用户空间是无法直接访问的。现在USB摄像头采集到的数据暂存在内核空间上,用户不能直接访问该段内存,必须通过某些手段来转换地址。一般有下列这几种方式:

1.read、write方式:在用户空间和内核空间不断拷贝数据,这种方式占用了大量用户内存空间,效率不高。

2.内存映射方式:把设备里的内存映射到应用程序中的内存空间,直接处理设备内存,这是一种有效的方式。mmap函数就是使用这种方式。mmap操作提供了一种机制,让用户程序直接访问设备内存,这种机制相比较在用户空间和内核空间互相拷贝数据效率更高。在要求高性能的应用中比较常用,比如在X window服务器中用mmap可以迅速而便捷地访问显卡内存。

3.用户指针模式:内存片段由应用程序自己分配。(? 这个的具体意思还没查到)


##结果分析## 在PC上可以看到ARM传送过来的视频图像,但是非常卡,远不如MIPEG-Streamer方案流畅。 图片

右边数据是在ARM上的编码结果,左边数据是PC上的显示结果。

整个IP-Camera的流程和业务逻辑如下:

图片

##Reference##

[1].https://github.com/vfonov/mjpg-streamer

[2].http://blog.chinaunix.net/uid-26696487-id-3076027.html

[3].http://blog.csdn.net/ghostyu/article/details/7371310

[4].http://blog.csdn.net/sunkwei/article/details/6530343

[5].https://code.google.com/p/mjpg-streamer-mini2440/

[6].http://blog.chinaunix.net/uid-26851094-id-3270803.html

[7].LDD. Page 417~419.

[8].http://blog.chinaunix.net/uid-25299072-id-3199359.html

[9].http://blog.chinaunix.net/uid-7396260-id-2056610.html

[10].http://blog.csdn.net/shaoyizhe2006/article/details/7958625

[11].http://blog.chinaunix.net/uid-26611383-id-3976154.html



Previous     Next
tuzhi /
Published under (CC) BY-NC-SA in categories arm  tagged with