本文属于《IP摄像头技术纵览》系列文章之一:
Author: chad
Mail: [email protected]
vgrabbj-0.9.6是基于v4l1设计的,与v4l2的API差别很大,该软件已经没有使用或参考价值。
spcaview 也相当古老,并且调用了SDL库,不适合嵌入式系统,不建议研究。
什么是SDL?
SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。
luvcview 该程序需要调用V4L2接口以及SDL库,可以进行视频采集与显示,有一定的参考价值。
我在ubuntu下测试情况如下:
摄像头格式为MJPEG,而luvcview默认格式为yuv,所以,在ubuntu上运行时使用命令:
./luvcview -f jpg
注:luvcview 编译时需要调用SDL库与pthread库。
强烈推荐:mjpg_streamer。
mjpg‐streamer是一个开源软件,用于从webcam摄像头采集图像,把它们以流的形式通过基于ip的网络传输到浏览器,关于它的介绍网上有一大堆,读者可自行了解;
mjpg-streamer 需要很少的CPU和内存资源就可以工作,大部分编码工作都是摄像头完成的,所以对于内存和性能都有限的嵌入式系统十分适用。网上关于它的移植也很多,下面给出移植的过程与在编译过程中出现的一些问题与解决方法。
在移植Mjpg-streamer之前必须移植好libjpeg;因为在mjpg-streamer源码包下的README文件中有下面一句话:
the input plugin “input_uvc.so” depends on libjpeg, make sure it is installed.
jpegsrc.v6b.tar.gz
mjpg-streamer-r63.tar.gz
把libjpeg库移植到mini2440arm板上步骤如下:
第一步:下载libjpeg源码
第二步:解压
第三步:切换到解压的目录执行:
./configure –prefix=安装目录 CC=arm-linux-gcc –host=arm-linux –enable-shared –enable-static
第四步:
make && make install
第五步:库的使用
在你的源代码中加入
#include "jpeglib.h"
另外编译的时候请一定使用下面的方法:
arm-linux-gcc -o 你的输出 你的程序 -L/安装目录 -l:libjpeg.so.62
要移植到arm上需要修改mjpg-streamer-r63/plugins/input_uvc目录下的Makefile文件,将ljpeg库的路径修改为移植好的jpeg库的路径:
设置CC=arm-linux-gcc重新编译:
make CC=arm-linux-gcc
将libjpeg.so.62.0.0库文件下载到目标板的lib目录下,并创建链接:
ln -s /lib/libjpeg.so.62.0.0 /lib/libjpeg.so.62
同时,安装好mjpg-streamer相关文件:
start.sh文件修改如下:
./mjpg_streamer -i “input_uvc.so -d /dev/video1 -y -r QVGA” -o “output_http.so -w www -p 20002”
然后在电脑浏览器上输入:
http://192.168.0.252:20002/javascript.html
要实现外网远程监控,第一步:需要一个静态IP地址,如果是局域网则需要设置端口转发,如下是我的路由设置:
第二步则是要正确配置嵌入式系统的ip、网关等参数,网关设置命令如下:
#route add default gw 192.168.0.1
第三步,首先查询本的网络的外网IP的(180.175.93.247),由于系统监控的是20002端口,在浏览器中输入:
http://180.175.93.247:20002/javascript.html
*说明:上面的方法只适合固定ip且路由器端口映射可配置的情况,对于动态ip以及没有路由器配置权限这类情况的解决方法将在后续章节讲解。这里先剧透下解决方法:
(1)DNS动态域名。
(2)NAT内网穿透。
(3)VPN*。
mjpg-streamer通过插件机制进行功能组合,程序扩展性非常好。目录结构如下:
➜ mjpg-streamer-r63 (下面的目录已经删除很多内容)
.
├── CHANGELOG
├── LICENSE
├── Makefile
├── mjpg_streamer.c //主函数文件
├── mjpg_streamer.h
├── plugins //插件目录
│ ├── input_file //文件输入插件
│ │ └── input_file.c
│ ├── input_gspcav1 //gspcav摄像头输入插件
│ ├── input.h
│ ├── input_testpicture //图片输入源插件
│ ├── input_uvc //uvc摄像头输入源插件
│ │ ├── dynctrl.c
│ │ ├── dynctrl.h
│ │ ├── huffman.h
│ │ ├── input_uvc.c
│ │ ├── jpeg_utils.c
│ │ ├── jpeg_utils.h
│ │ ├── Makefile
│ │ ├── uvc_compat.h
│ │ ├── uvcvideo.h
│ │ ├── v4l2uvc.c
│ │ └── v4l2uvc.h
│ ├── output_autofocus //autofocus输出控制插件
│ ├── output_file //插件–输出到文件
│ ├── output.h
│ └── output_http //通过http协议输出
│ ├── httpd.c
│ ├── httpd.h
│ ├── Makefile
│ └── output_http.c
├── README
├── start.sh //启动控制脚本
├── utils.c
├── utils.h
└── www //html页面资源文件,使用http输出插件时调用
├── bodybg.gif
├── cambozola.jar
。。。。。
└── style.css
input-plugin负责产生图片并把这些复制到内存中去。相应的output-plugin则负责把这些内存中的图片取出来以便后续的处理。最常用的是webserver-output-plugin,他允许将图片传送到网络浏览器上。mjpg-streamer充当粘合剂的角色,把这单一的input-plugin和众多的output-plugin给连在一起,而几乎所有的工作都交给了这些个插件。
input_testpicture.so
这个模块编译的时候已经加入了图片(正如其名:test),就是说你没摄像头也能进行测试工作(你编译的对不对)。他也为你提供了一个模板,一个你想写自己的input-plugin的模板,因为他被实现的尽可能的简单易懂。它的作用就是把由testpictures模块得到的JPEG-files文件转变成一个头文件,这个头文件包含了一些被编译进testpictures模块的图片(前面说过了)。当被激活时就会不停的往复上面的那个动作:获得->转变。
input_uvc.so
如其名它从兼容Linux-UVC V4L2标准的设备中抓取图片。
output_http.so
这绝对是个全版本的符合HTTP1.0标准的webserver。通过访问www文件夹内的html等资源文件可以实现复杂的网页功能,入css,javascript,java等。并可接收浏览器客户端的命令实现摄像头参数调整。
mjpg-streamer程序的视频传输正向它名字描述的一样,它的原理是把视频镜头拍成的视频分解成一张张分离的jpg图像数据发送到客户端。当客户端不断显示图片,即可形成相应的图像。
该方法的优点是实现简单,客户端实现简单,不会出现马赛克的情况。缺点就是占带宽比较大,因为是一帧一帧按图像来传输的。
MJPG可以在多种传输协议上传输,比如TCP/UDP,最常见是在HTTP上采用传输。大部分的摄像头也是采用HTTP+MJPG的传输形式的。
mjpg的在http的mime type是”x-mixed-replace”,但mjpg 首先是要由客户发一个GET取一个特殊文件(不同摄像头有不同的定义)。如果ipcam返回200,表示已经接收的请求,并在返回的头里指明边界字符串,这是在context type的boundary子属性来指明的。
然后ipcam开始发送JPG数据,首先是发送类型和长度。Content-Type= image/jpeg以及用Content-Length指向随后的长度。当一个图发送完毕后,以边界字符串来结束。
首先是发送 GET /?action=stream\n\n
服务器响应200表示联接成功。并指明是multipart/x-mixed-replace的mjpg数据,边界字符串是“boundarydonotcross”
HTTP/1.0 200 OK
Connection: close
Server: MJPG-Streamer/0.2
Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0
Pragma: no-cache
Expires: Mon, 3 Jan 2000 12:34:56 GMT
Content-Type: multipart/x-mixed-replace;boundary=boundarydonotcross
--boundarydonotcross
接下是开发发送JPG数据
Content-Type: image/jpeg
Content-Length: 19454
<中间19454字节就是一个JPG完整的图像>
--boundarydonotcross
当连续不断发送这个数据,在客户端即可显示视频