當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > mjpg-streamer網(wǎng)絡(luò)視頻服務(wù)器移植
MJPG簡(jiǎn)介:
MJPG是MJPEG的縮寫(xiě),但是MJPEG還可以表示文件格式擴(kuò)展名.全名為 "Motion Joint Photographic Experts Group",是一種視頻編碼格式,Motion JPEG技術(shù)常用與閉合電路的電視攝像機(jī)的模擬視頻信號(hào)“翻譯”成視頻流,并存儲(chǔ)在硬盤(pán)上。
典型的應(yīng)用如數(shù)字視頻記錄器等。MJPEG不像MPEG,不使用幀間編碼,因此用一個(gè)非線性編輯器就很容易編輯。
MJPEG的壓縮算法與MPEG一脈相承,功能很強(qiáng)大,能發(fā)送高質(zhì)圖片,生成完全動(dòng)畫(huà)視頻等。
但相應(yīng)地,MJPEG對(duì)帶寬的要求也很高,相當(dāng)于T-1,MJPEG信息是存儲(chǔ)在數(shù)字媒體中的龐然大物,需要大量的存儲(chǔ)空間以滿足如今多數(shù)用戶的需求。
因此從另一個(gè)角度說(shuō),在某些條件下,MJPEG也許是效率低的編碼/解碼器之一。
MJPEG 是 24-bit 的 "true-color" 影像標(biāo)準(zhǔn),MJPEG 的工作是將 RGB 格式的影像轉(zhuǎn)換成 YCrCB 格式,目的是為了減少檔案大小,一般約可減少 1/3 ~ 1/2 左右。
MJPEG與MJPG的區(qū)別:
1、mjpeg是視頻,就是由系列jpg圖片組成的視頻。
2、MJPG是MJPEG的縮寫(xiě),但是MJPEG還可以表示文件格式擴(kuò)展名.
一、環(huán)境
主機(jī)環(huán)境:ubuntu 12.04.4 LTS
目標(biāo)機(jī):Cortex-A9
主機(jī)工具鏈:gcc-4.6.4
交叉工具鏈:arm-none-linux-gnueabi-
攝像頭:ZC301
二、移植過(guò)程
1、配置內(nèi)核是內(nèi)核支持芯片為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、重新編譯內(nèi)核
make uImage
通過(guò)上面兩個(gè)步驟就可以驅(qū)動(dòng)我們的攝像頭了。但是這個(gè)驅(qū)動(dòng)是基于V4l2的。以前基于V4L的一些上層應(yīng)用就不能用了,或需要做大量的修改!
這里我們要實(shí)現(xiàn)網(wǎng)絡(luò)視頻的功能,以前都是用servfox這個(gè)網(wǎng)絡(luò)視頻服務(wù)器,但是這個(gè)服務(wù)器就是基于V4L的,
我們?nèi)绻胗玫脑捑偷脤?duì)servfox的源碼進(jìn)行修改。這里我們選用另外一種方案mjpg-streamer。
(2)mjpg-stream的移植
1)mjpg-stream源碼包通過(guò)下面這個(gè)網(wǎng)址下載
https://sourceforge.net/projects/mjpg-streamer/ 打開(kāi)稍等一下,在Browse All Files上會(huì)出現(xiàn)源碼的下載
2)解壓源碼
tar xvf mjpg-streamer-r63.tar.gz
3)修改源碼
cd mjpg-streamer-r63
修改頂層makefile及plugins目錄中的各級(jí)makefile將所有
修改
CC = gcc
為
CC = arm-cortex_a8-linux-gnueabi
4)*/修改plugins/input_uvc/Makfile
在第 16 行添加編譯時(shí)需要的 jpeg 頭文件的路徑
CFLAGS += -I /home/david/Exynos4412/test/mjpg-streamer/jpeg /include
在第 24 行添加編譯時(shí)需要的 jpeg 庫(kù)的路徑
修改
$(CC) $(CFLAGS) -ljpeg -o $@ input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo
為
$(CC) $(CFLAGS) -ljpeg -L /home/david/Exynos4412/test/mjpg-streamer/jpeg /lib -o $@
input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo
5)修改 plugins/input_uvc/v4l2uvc.c
這個(gè)目錄是支持 uvc 攝像頭的,而我們的 FS4412 的攝像頭使用的 samsung 的 FIMC
架構(gòu),所有在應(yīng)用程序編程時(shí)有點(diǎn)細(xì)微差別,這里需要針對(duì)這些差別做一些改動(dòng):
修改 static int init_v4l2(struct vdIn *vd)函數(shù)
在
/*
* set format int
*/
前添加如下代碼
int input = 0;
ret = ioctl(vd->fd, VIDIOC_S_INPUT, &input);
if (ret < 0) {
perror(“Unable to set input”);
goto fatal;
}
在
/ *
* set framerate
*/
前添加
vd->fmt.type = 0x80;
ret = ioctl(vd->fd, VIDIOC_S_FMT, &vd->fmt);
if (ret < 0) {
perror(“Unable to set format”);
goto fatal;
}
注釋如下代碼
/*
* set framerate
*/
struct v4l2_streamparm *setfps;
setfps = (struct v4l2_streamparm *) calloc(1, sizeof(struct v4l2_streamparm));
memset(setfps, 0, sizeof(struct v4l2_streamparm));
setfps->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
setfps->parm.capture.timeperframe.numerator = 1;
setfps->parm.capture.timeperframe.denominator = vd->fps;
ret = ioctl(vd->fd, VIDIOC_S_PARM, setfps);
修改
vd->buf.length, PROT_READ, MAP_SHARED, vd->fd,
為
vd->buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, vd->fd,
修改 int uvcGrab(struct vdIn *vd)函數(shù)
修改
ret = ioctl(vd->fd, VODIOC_DQBUF, &vd->buf);
if (ret < 0) {
perror(“Unable to dequeue buffer”);
goto err;
}
為
retry:
ret = ioctl(vd->fd, VODIOC_DQBUF, &vd->buf);
if (ret < 0) {
usleep(10000);
goto retry;
}
修改
memcpy(vd->framebuffer, vd->mem[vd->buf.index], (size_t) vd->bytesused);
為
memcpy(vd->framebuffer, vd->mem[vd->buf.index], (size_t) vd->framesizeIn);
修改 static int video_enable(struct vdIn *vd)函數(shù)
在
vd->isstreaming = 1;
前添加
sleep(1);
c) 編譯 mjpg-streamer
make clean
make
6)錯(cuò)誤
plugins/input_uvc all
make[1]: Entering directory `/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 `/home/swchen/code/tools/mjpeg/mjpg-streamer/plugins/input_uvc'
make: *** [input_uvc.so] Error 2
說(shuō)的是錯(cuò)誤的格式。 但是自己很確定自己在編譯libjpeg的使用時(shí)交叉編譯的,這么說(shuō)的話libjpeg就不會(huì)有問(wèn)題的。
是在mjpg-streamer這邊出了問(wèn)題,由于問(wèn)題一的緣故,自己使用了make 和 make CC=arm-linux-gcc 重復(fù)了很多次。
所以有部分的生成的文件 是x86下的。 所以才導(dǎo)致了這個(gè)問(wèn)題。
這個(gè)只要清空一下就好,make clean -w ,再重新編譯,這個(gè)問(wèn)題跳過(guò)了。