-
mjpg-streamer简介
mjpg‐streamer是一个开源软件。MJPG streamer从Linux UVC兼容的网络摄像头、文件系统或其他输入插件获取JPG,并通过HTTP、RTSP、UDP等将其作为M-JPEG流式传输到WebBrowser、VLC和其他软件。它是uvc streamer的继承者。
mjpg-streamer 需要很少的CPU和内存资源就可以工作,大部分编码工作都是摄像头完成的,所以对于内存和性能都有限的嵌入式系统十分适用。
在移植Mjpg-streamer之前必须移植好libjpeg;因为在mjpg-streamer源码包下的README文件中有下面一句话:“the input plugin “input_uvc.so” depends on libjpeg, make sure it is installed.”
英文介绍和源码下载地址:
MJPG-streamer download | SourceForge.net
(进去后,点右上的“Download Snapshot”下载最新版的 mjpg-streamer-code-182,因为旧版编译时会出现缺少一个头文件的错误)
目录 mjpg-streamer-code-182 里内容如下:
doc/ 、mjpg-streamer/、udp_client/、mjpeg-client/、mjpg-streamer-experimental/、uvc-streamer/。
其中
mjpg-streamer:目录下提供了的执行程序和各个输入输出设备组件,支持输入有control、file、gspcav(早期摄像头)、testpicture、uvc(现在主流摄像头),正式发布的版本。我们采用这个版本。
mjpg-streamer-experimental:目录下提供实验性版本的组件,支持输入有control、file、http、ptp2、testpicture、uvc(现在主流摄像头)。对yuv的摄像头兼容性不行。若要兼容yuv摄像头,需要需改较多的地方。 可以查看
在64位ubuntu12.04中安装mjpg-streamer实现网络监控_comego1978的专栏-CSDN博客
该网站有该版本对YUV支持说明——未亲测过,网上说可能还要安装libv4l-dev。
uvc-streamer:目录下提供了uvc-streamer的可执行目录。
udp_client:udp输出的客户端。
mjpeg-client:分别有 linux和windows 的客户端。
(a)mjpg-streamer视频传输原理
mjpg-streamer程序的视频传输正向它名字描述的一样,它的原理是把视频镜头拍成的视频分解成一张张分离的jpg图像数据发送到客户端。当客户端不断显示图片,即可形成相应的图像。该方法的优点是实现简单,客户端实现简单,不会出现马赛克的情况。缺点就是占带宽比较大,因为是一帧一帧按图像来传输的。MJPG可以在多种传输协议上传输,比如TCP/UDP,最常见是在HTTP上采用传输。大部分的摄像头也是采用HTTP+MJPG的传输形式的。
(b)mjpg浏览器传输技术分析
mjpg的在http的mime type是”x-mixed-replace”,但mjpg 首先是要由客户发一个GET取一个特殊文件(不同摄像头有不同的定义)。如果ipcam返回200,表示已经接收的请求,并在返回的头里指明边界字符串,这是在context type的boundary子属性来指明的。然后ipcam开始发送JPG数据,首先是发送类型和长度。Content-Type= image/jpeg以及用Content-Length指向随后的长度。当一个图发送完毕后,以边界字符串来结束。
(c)mjpg-streamer的协议说明
首先是发送 GET /?action=stream\n\n。服务器响应200表示联接成功。并指明是multipart/x-mixed-replace的mjpg数据,边界字符串是“boundarydonotcross”。
(d)vgrabbj、spacview、Luvcview、mjpg-streamer评测对比
vgrabbj-0.9.6是基于v4l设计的,与v4l2的API差别很大,该软件已经没有使用或参考价值。
spcaview 也相当古老,并且调用了SDL库,不适合嵌入式系统,不建议研究。
什么是SDL?
SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。
luvcview 该程序需要调用V4L2接口以及SDL库,可以进行视频采集与显示,有一定的参考价值。
-
ubuntu搭建mjpg-streamer流媒体服务器
1,需要安装依赖库libjpeg cmake。
sudo apt-get install cmake libjpeg8-dev subversion
可能还要安装imagemagick
2,编译
cd mjpg-streamer
make clean
make all
3,运行
对于mjpg的摄像头直接运行
./start.sh
对于YUV的摄像头
./mjpg_streamer -i "./input_uvc.so -d /dev/video0 -y" -o "./output_http.so -w ./www -p 20002"
4,测试
-p参数端口号,不写时默认是8080端口。
本机查看输入 http://localhost:8080/
其它电脑查看输入: http://本机ip:8080/
5,其他功能
先看看自己编译出来的与官方的版本在input_uvc.so模块帮助上的区别
./mjpg_streamer -i "./input_uvc.so --help"
你可以把mjpg-streamer-experimental和mjpg-streamer两个版本的帮助打开会发现一下区别:
以下是mjpg-streamer的版本
以下是mjpg-streamer-experimental的版本
-i 输入协议选择,这里是uvc摄像头
-o 输出选择,这里是输出为http协议
-f 帧率的设置,这里是1秒30帧
-d 输入设备的选择,这里是摄像头0
-w 这里是web
-y” 表示输入格式为YUV,如果不加-y 表示 mjpg输入
-r 表示图片尺寸640x480
当网页需要添加账号密码,增加安全性能时
./mjpg_streamer -i “./input_uvc.so -d /dev/video0 -u -f 30” -o “./output_http.so -w ./www -c admin:admin”
最后添加的部分就是用户名和密码
-
嵌入式arm系统搭建mjpg-streamer流媒体服务器
1,mjpg-stream的移植需要jpeg的库,所以我们先移植jpeg的库。源码下载地址:http://www.ijg.org/files/ 。
cd ./jpeg-9d
mkdir –p /home/hevenwy/Desktop/work/jpegarm
./configure CC=arm-linux-gcc --prefix=/home/hevenwy/Desktop/work/jpegarm -host=arm-none-linux-gnueabi
Make && make install
在制定的目录下会生成包括bin、include、lib、share,红色这两个文件夹便是mjpg_streamer需要的。
拷贝上面的lib文件夹即jpeg库到文件系统中
cp /home/hevenwy/Desktop/work/jpegarm/lib/* /nfs/roofs/lib/ -ra
(/nfs/roofs/lib 此目录为自己的文件系统目录,arm板是挂载ubuntu中此目录作为根文件系统的)
2,移植mjpg-streamer
a)进入目录
cd mjpg-streamer
b)进入 /plugins/input_uvc/Makfile ,
修改
CFLAGS += -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC
为
CFLAGS += -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I /home/hevenwy/Desktop/work/jpegarm/include
修改
(CC)(CFLAGS) -o @inputuvc.cv4l2uvc.lojpegutils.lodynctrl.lo(LFLAGS)
为
(CC)(CFLAGS) -L /home/hevenwy/Desktop/work/jpegarm/lib -o @inputuvc.cv4l2uvc.lojpegutils.lodynctrl.lo(LFLAGS)
(注:/home/hevenwy/Desktop/work/jpegarm/lib 就是上面移植jpeg库后安装的目录,根据自己设置的目录来修改)
c)修改源码 顶层的Makefile及 plugins文件夹里面所有子层的Makefile中的CC参数为arm-linux-gcc,即将所有“ CC = gcc ”改为“ CC = arm-linux-gcc ”。
d)编译生成*.so文件和可执行文件mjpg_streamr
make
e)将前面编译生成文件,还有start.sh ./www/ 搬移到nfs根目录中
cp –raf *.so /home/hevenwy/Desktop/work/mjpg-streamer/
cp –raf mjpg-streamer /home/hevenwy/Desktop/work/mjpg-streamer/
cp –raf start.sh www/ /home/hevenwy/Desktop/work/mjpg-streamer/
f)按之前ubuntu下的测试一样。
3,功能扩展
拍照功能的实现
由于mjpg_stream中output-file.so能实现连续拍照的功能,不能实现单拍或连拍几张的功能所以需要对output_file原码进行修改。
# cd mjpg-streamer-rc63/plugins/output_file
# vim output_file.c
在96行 函数 void *worker_thread(void *arg) 体中加入以下代码:
char buf[10]; //用于存放从管道读取的命令
int flags = 0; //拍照标志,1:表示11张照片,2:表示1张照片
int fd_com = 0; //打开管道的文件描述符
stop_num = 0; //拍照计数
if ( access(“/tmp/webcom”,F_OK) < 0 ) //创建有名管道用于接收拍照命令
{
if ( mkfifo(“/tmp/webcom”,0666 ) < 0)
{
Printf(“ photo fifo create failed\n”);
}
}
fd_com = open (“/tmp/webcom”,O_RDONLY,0666);
if (fd_com < 0)
{
perror (“open the file webcom error”);
}
在while( ok >= 0 && !pglobal->stop){ 后加入
if (flags == 0)
{
while(1)
{
read(fd_com,buf,sizeof(buf));
if (strncmp(buf,”danger”,6) == 0) //拍11张照片
{
flags = 1;
bzero(buf,sizeof(buf));
break;
}
if (strncmp(buf,”one”,3) == 0) //拍1张照片
{
flags = 2;
bzero(buf,sizeof(buf));
break;
}
}
}
在if (delay > 0){
usleep(1000*delay);
}后加入
stop_num++
if (flags == 1) //判断拍照的数量
{
if ( stop_num > 9)
{
stop_num = 0;
flags = 0;
}
}
else if (flags == 2)
{
stop_num = 0;
flags = 0;
}
测试
所以只要向有名管道/tmp/webcom写入danger就能连拍11张照片,写入one就拍一张照片。
#echo one > tmp/webcom
#ls /pice/可以看到图片信息
注:拍照功能实现:
mjpg_streamer -i "/mjpg/input_uvc.so -y" -o "/mjpg/output_http.so -w /www" -o "/mjpg/output_file.so -f /pice -d 15000" &
-
mjpg-streamer简单代码以及框架解析
参考网站1:mjpeg-streamer分析 - 百度文库
参考网站2:基于Mjpeg-streamer的远程视频监控系统 - 道客巴巴
- 首先解析输入命令,利用dlopen,dlsym指令完成
当CTRL+C时,将调用dlclose。
- 数据采集(只分析input_uvc)
先调用input_init初始化:
进入init_videoIn(),通过init_v4l2对摄像头进行初始化。
然后在调用input_run,创建cam_thread线程
进入cam_thread线程,调用uvcGrab,对帧数据进行处理,存放在
pglobal->in[pcontext->id].buf
- 数据发送
同input_uvc。output_http也先调用output_init,在调用output_run.
进入server_thread线程.
在server_thread线程中进入client_thread.在client_thread发送数据。