MJPG简介:
MJPG是MJPEG的缩写,但是MJPEG还可以表示文件格式扩展名.
MJPEG
全名为 “Motion Joint Photographic Experts Group”,是一种视频编码格式,
Motion JPEG技术常用与闭合电路的电视摄像机的模拟视频信号“翻译”成视频流,并存储在硬盘上。典型的应用如数字视频记录器等。MJPEG不像MPEG,不使用帧间编码,因此用一个非线性编辑器就很容易编辑。MJPEG的压缩算法与MPEG一脉相承,功能很强大,能发送高质图片,生成完全动画视频等。但相应地,MJPEG对带宽的要求也很高,相当于T-1,MJPEG信息是存储在数字媒体中的庞然大物,需要大量的存储空间以满足如今多数用户的需求。因此从另一个角度说,在某些条件下,MJPEG也许是效率最低的编码/解码器之一。
MJPEG 是 24-bit 的 “true-color” 影像标准,MJPEG 的工作是将 RGB 格式的影像转换成 YCrCB 格式,目的是为了减少档案大小,一般约可减少 1/3 ~ 1/2 左右。
MJPEG与MJPG的区别:
1、mjpeg是视频,就是由系列jpg图片组成的视频。
2、MJPG是MJPEG的缩写,但是MJPEG还可以表示文件格式扩展名.
一、环境
主机环境:ubuntu 12.04.4 LTS
目标机:ok6410
主机工具链:gcc-4.3.2
交叉工具链:arm-linux-gcc-4.3.2
摄像头:ZC301 ,uvc摄像头
二、移植过程
1、配置内核是内核支持芯片为ZC301的摄像头
Make menuconfig
Device Drivers —>
<*> Multimedia support —>
<*> Video For Linux
[*] Enable Video For Linux API 1 (DEPRECATED) (NEW)
[*] Video capture adapters (NEW) —>
[*] V4L USB devices (NEW) —>
<*> USB Video Class (UVC)
[*] UVC input events device support (NEW)
<*> USB ZC0301[P] webcam support (DEPRECATED)
2、重新编译内核
make zImage
通过上面两个步骤就可以驱动我们的摄像头了。但是这个驱动是基于V4l2的。以前基于V4L的一些上层应用就不能用了,或需要做大量的修改!这里我们要实现网络视频的功能,以前都是用servfox这个网络视频服务器,但是这个服务器就是基于V4L的,我们如果想用的话就得对servfox的源码进行修改。这里我们选用另外一种方案mjpg-stream。
3、mjpg-stream的移植
关于mjpg-stream的资料大家可以在下面这个网址查看:http://sourceforge.net/apps/mediawiki/mjpg-streamer/index.php?title=Main_Page
source code的网址是:http://mjpg-streamer.svn.sourceforge.net/viewvc/mjpg-streamer/
mjpg-stream的移植需要jpeg的库,所以我们先移植jpeg的库
(1)jpeg库的移植
1)jpeg源码包通过下面这个网址下载
http://www.ijg.org/files/jpegsrc.v8b.tar.gz
2)解压源码包
tar xvf jpegsrc.v8b.tar.gz
3)配置源码
cd jpeg-8b
./configure --prefix=/home/mjpg/jpeg-8b/jpeg--host=arm-none-linux-gnueabi
./configure CC=arm-linux-gcc --prefix=/home/mjpg_and_jpeg6/jpeg-6b/jpeg --host=arm-none-linux-gnueabi
4)编译
make
5)安装
make install
6)拷贝库到文件系统中
cp /home/mjpg/jpeg-8b/jpeg/lib/libjpeg.so.8 /source/rootfs/lib
第二步、移植mjpg-streamer
1、下载源码,在https://sourceforge.net/projects/mjpg-streamer/下载的源码(mjpg-streamer-r63)有点老了,最新的版本使用以下命令下载,
svn cohttps://mjpg-streamer.svn.sourceforge.net/svnroot/mjpg-streamermjpg-streamer
解压,并进入目录一共有 这么多目录
doc mjpg-streamer udp_client
mjpeg-client mjpg-streamer-experimental uvc-streamer
mjpg-streamer :目录下提供了 的执行程序和各个输入输出设备组件
uvc-streamer : 目录下提供了 uvc-streamer的可执行目录
mjpeg-client:: 分别有 linux和windows 的客户端
其中windows的客户端viewer.exe,我们首先测试
2、进入其目录
cd /home/mjpg/mjpg-streamer-code-182/mjpg-streamer
3、修改源码
修改/home/mjpg/mjpg-streamer-code-182/mjpg-streamer/plugins/input_uvc/Makfile,
修改
CFLAGS += -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC
为
CFLAGS += -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I /home/mjpg/jpeg-8b/jpeg/include
修改
# (CC) (CFLAGS) -o @inputuvc.cv4l2uvc.lojpegutils.lodynctrl.lo (LFLAGS)
为
(CC) (CFLAGS) -L /home/mjpg/jpeg-8b/jpeg/lib -o @inputuvc.cv4l2uvc.lojpegutils.lodynctrl.lo (LFLAGS)
注:/home/mjpg/jpeg-8b/jpeg/lib 就是上面移植jpeg库后安装的目录
4、编译:make CC=arm-linux-gcc 在mjpg-streamer生成了
input*.so output*.so 和 mjpg_streamr 可执行文件
5、在开发板建立mjpg-streamer安装目录
mkdir /nfs/rootfs/usr/local/mjpg-streamer
cp *.so /nfs/rootfs/usr/local/mjpg-streamer
cp mjpg-stream /nfs/rootfs/usr/local/mjpg-streamer
将源码目录中的start.sh和目录www拷贝到/nfs/rootfs/mjpg-streamer目录下,然后就可以测试啦
6、测试:
./mjpg_streamer -i “./input_uvc.so -d /dev/video2 -yuv” -o “./output_http.so -w ./www”
修改start.sh文件,然后运行start.sh;在PC机打开一个网页,输入http://192.168.1.1:8080/?action=stream就可以看到图像。
7、获得帮助
获得帮助的方法在start.sh里有说明,以下举一个例子,运行./mjpg_streamer –help它会打印出以下帮助,可根据需要设置参数
The following parameters can be passed to this plugin:
[-d | –device ]…….: video device to open (your camera)
[-r | –resolution ]…: the resolution of the video device,
can be one of the following strings
QSIF QCIF CGA QVGA CIF VGA
SVGA XGA SXGA
or a custom value like the following
example: 640x480
[-f | –fps ]……….: frames per second
[-y | –yuv ]……….: enable YUYV format and disable MJPEG mode
[-q | –quality ]……: JPEG compression quality in percent
(activates YUYV format, disables MJPEG)
[-m | –minimum_size ].: drop frames smaller then this limit, useful
if the webcam produces small-sized garbage frames
may happen under low light conditions
[-n | –no_dynctrl ]…: do not initalize dynctrls of Linux-UVC driver
[-l | –led ]……….: switch the LED “on”, “off”, let it “blink” or leave
it up to the driver using the value “auto”
以上是mjpg-streamer的移植全过程,下面说说在这过程可能出现的错误以及解决方法。
1、当编译mjpg-stream-mini2440-read-only时出错
[root@wu mjpg-streamer-mini2440-read-only]# make CC=arm-linux-gcc
arm-linux-gcc -O3 -DLINUX -D_GNU_SOURCE -Wall -c -o mjpg_streamer.o mjpg_streamer.c
mjpg_streamer.c:27:28: fatal error: linux/videodev.h: No such file or directory
compilation terminated.
make: * [mjpg_streamer.o] 错误 1
[root@wu mjpg-streamer-mini2440-read-only]#
原因:这是因为内核2.6.38和以后的版本已经移除了对 v4l1 的支持,这个东西可能比较老旧了。新的头文件是 video4linux2.h;相比v4l1很多接口都变化
解决办法:可以选择以前低版本内核,或者用新版本的mjpg-streamer,下载地址在开始讲移植mjpg-streamer时讲到。
2、当编译成功,怀着兴奋的心情运行时突然打印出以下错误时
MJPG-streamer [703]: starting application
MJPG Streamer Version: svn rev: 3:154M
MJPG-streamer [703]: MJPG Streamer Version: svn rev: 3:154M
……….
Inconsistency detected by ld.so: dl-deps.c: 622: _dl_map_object_deps: Assertion `nlist > 1’ failed!
…………
或者以下的错误时
VCIOC_CTRL_MAP - Error: Invalid argument
mapping control for LED1 Frequency
UVCIOC_CTRL_MAP - Error: Invalid argument
mapping control for Disable video processing
UVCIOC_CTRL_MAP - Error: Invalid argument
mapping control for Raw bits per pixel
UVCIOC_CTRL_MAP - Error: Invalid argument
o: www-folder-path…: ./www/
o: HTTP TCP port…..: 8080
o: username:password.: disabled
o: commands……….: enabled
Wrong JPEG library version: library is 62, caller expects 80
原因:这是jpeg库文件版本不对应导致的,现在运行使用的是80,但是它实际需要的是62版本,高版本jpeg库与低版本mjpg-streamer冲突。
解决方法:去下载62版本的jpeg库文件,从头开始再编译一次jpeg和mjpeg-streamer。
3、使用摄像头出现如下信息
………………..
Init v4L2 failed !! exit fatal
init_VideoIn failed
………………..
原因:市面上大部分摄像头都是支持YUV的,而不是JPEG的。
解决方法:由于mjpg-stream支持JPEG和YUV两种格式,所以只需修改start.sh,在输入中加入 ” - y “
假如原来是./mjpg_streamer -i “./input_uvc.so ” -o “./output_http.so -w ./www”,则改为
./mjpg_streamer -i “./input_uvc.so -y” -o “./output_http.so -w ./www”即可。
总结:经过一轮的谷歌+百度后终于可以在firefox看了摄像头采集的图像
(2)其他的mjpg-stream的移植
1)mjpg-stream源码包通过下面这个网址下载
http://sourceforge.net/projects/mjpg-streamer/
2)解压源码
tar xvf mjpg-streamer-r63.tar.gz
3)修改源码
cd mjpg-streamer-r63
修改顶层makefile及plugins目录中的各级makefile将所有
CC=gcc
修改为
CC=arm-none-linux-gnueabi-gcc
修改plugins/input_uvc/Makfile
修改
CFLAGS += -O2 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC
为
CFLAGS += -O2 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I/home/linux/s3c2410-2.6.35/video/jpeg/include
修改
$(CC) $(CFLAGS) -ljpeg -o $@ input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo
为
$(CC) $(CFLAGS) -ljpeg -L/home/linux/s3c2410-2.6.35/video/jpeg/lib -o $@ input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo
jpeg_utils.c:27: fatal error: jpeglib.h: No such file or directory
4)编译
make 或者 make CC=arm-linux-gcc
5)测试
mkdir /source/rootfs/mjpg
cp *.so /source/rootfs/mjpg
cp mjpg-stream /source/rootfs/bin
打开开发板运行
mjpg_streamer -i "/mnt/input_uvc.so -d /dev/video2 -yuv " -o "/mnt/output_http.so -w ./www"
// mjpg_streamer -i "/mjpg/input_uvc.so" -o "/mjpg/output_http.so -w /www"
在源码目录下有start.sh,这个脚本里有一些mjpg-stream的使用方法及说明
打开一个网页输入下面地址就能够看到一个视频(开发板的IP为192.168.1.202):
http://192.168.1.202:8080/?action=stream
打开一个网页输入下面地址就能够看到一个静态图片:
http://192.168.1.202:8080/?action=snapshot
6)在mjpg源码下有一个www的目录,这个一个网络使用mjpg的实例,结合web服务器(boa)可以实现一些其他相关功能。
问题一
遵从这篇文章去修改http://lexandros.blog.163.com/blog/static/185566588201272813640474/
因为要指定 libjpeg 的include 路径和 lib路径,自己偷懒,索性在Makefile 中定义了一个变量PATH。
每次执行到uvc_input 里的Makefile时候,总是说CC 或者 arm-linux-gcc 的命令找不到,command not found.
自己也是一头雾水。不过后来别人提点才发现,自己的PATH吧环境变量中的PATH 给替换了,所以才找不到命令。
解决方法也比较简单,将PATH的名字稍微改一下,不要和系统环境变量重名就可以了。
问题二,爆出的错误就是如下
plugins/input_uvc all
make[1]: Entering directory /home/swchen/code/tools/mjpeg/mjpg-streamer/plugins/input_uvc'
/home/swchen/code/tools/mjpeg/mjpg-streamer/plugins/input_uvc’
arm-linux-gcc -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I /home/swchen/code/tools/libjpeg/jpeg-install/include -o input_uvc.so input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo -ljpeg -L /home/swchen/code/tools/libjpeg/jpeg-install/lib
/home/swchen/enviroment/4.1.2/bin/../lib/gcc/arm-angstrom-linux-gnueabi/4.1.2/../../../../arm-angstrom-linux-gnueabi/bin/ld: v4l2uvc.lo: Relocations in generic ELF (EM: 3)
/home/swchen/enviroment/4.1.2/bin/../lib/gcc/arm-angstrom-linux-gnueabi/4.1.2/../../../../arm-angstrom-linux-gnueabi/bin/ld: v4l2uvc.lo: Relocations in generic ELF (EM: 3)
v4l2uvc.lo: could not read symbols: File in wrong format
collect2: ld returned 1 exit status
make[1]: *** [input_uvc.so] Error 1
make[1]: Leaving directory
make: * [input_uvc.so] Error 2
说的是错误的格式。 但是自己很确定自己在编译libjpeg的使用时交叉编译的,这么说的话libjpeg就不会有问题的。
是在mjpg-streamer这边出了问题,由于问题一的缘故,自己使用了make 和 make CC=arm-linux-gcc 重复了很多次。
所以有部分的生成的文件 是x86下的。 所以才导致了这个问题。
这个只要清空一下就好,make clean -w ,再重新编译,这个问题跳过了。
问题三
make[1]: Entering directory /home/swchen/code/tools/mjpeg/mjpg-streamer/plugins/input_uvc'
/home/swchen/code/tools/mjpeg/mjpg-streamer/plugins/input_uvc’
arm-linux-gcc -c -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I /home/swchen/code/tools/libjpeg/jpeg-install/include -o v4l2uvc.lo v4l2uvc.c
arm-linux-gcc -c -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I /home/swchen/code/tools/libjpeg/jpeg-install/include -o jpeg_utils.lo jpeg_utils.c
arm-linux-gcc -c -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I /home/swchen/code/tools/libjpeg/jpeg-install/include -o dynctrl.lo dynctrl.c
dynctrl.c:88: error: ‘V4L2_CID_PAN_RELATIVE’ undeclared here (not in a function)
dynctrl.c:98: error: ‘V4L2_CID_TILT_RELATIVE’ undeclared here (not in a function)
dynctrl.c:108: error: ‘V4L2_CID_PAN_RESET’ undeclared here (not in a function)
dynctrl.c:118: error: ‘V4L2_CID_TILT_RESET’ undeclared here (not in a function)
make[1]: *** [dynctrl.lo] Error 1
make[1]: Leaving directory
make: * [input_uvc.so] Error 2
好端端的又是参数没有定义,这个怎么回事?
后来才了解到时编译器的问题,我用的编译器是4.1.2,而其内部的头文件虽然也包含videodev2.h,内部却不包含这个宏定义。
观看另外一个编译器,4.5.1,里面的videodev2.h 就有包含上述的宏定义。看来得更换编译器了,要不然连编译都过不了。
哈,终于通过了,一个下午时间…..
不过随之而来的是另外一个麻烦,就是illegal instruction。
原先编译器自带的glibc 版本和 后来的glibc版本不对应,而板子上的buybox 等等都是通过4.1.2 编译的。
所以 觉得是交叉编译器混用导致的结果。 要改的东西就多了…..