LV11-03-MJPGstreamer-01-移植过程

本文主要是MJPG-streamer移植的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows windows11
Ubuntu Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
SecureCRT Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日
Linux开发板 华清远见 底板: FS4412_DEV_V5 核心板: FS4412 V2
u-boot 2013.01
linux内核 linuz-3.14
点击查看本文参考资料
参考方向参考原文
华清远见课程华清远见课程
MJPG-streamerMJPG-streamer download | SourceForge.net
jpeg库Independent JPEG Group (ijg.org)
点击查看相关文件下载
文件下载链接
------

一、mjpg-streamer简介

1. 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 左右。

2. 摄像头

免驱动摄像头,是一种遵循视频设备类(USB Video Class,简称 UVC )标准协议的摄像头产品。将符合标准的摄像头连接到符合标准的操作系统,系统就会自动为其安装驱动并进行设置,使摄像头实现真正意义上的即插即用。

UVC 是一种硬件的框架结构,只有当其是通过一种标准的设计使其实现了免驱;而 V4L2 是一种驱动程序,其是实现系统与 UVC 设备等的通信。

3. mjpg-streamer视频流服务器

mjpg-streamer简单来说就是一个jpeg文件的传输流服务器,它最常用的用途就是采集摄像头的数据,然后启动 http server,用户就可以通过浏览器查看图像数据了。

image-20220921125818332

UVC摄像头 + 驱动 + JPEG图库 + mjpeg-streamer + HTML 就完成了对用户远程提供视屏展示的服务。首先底层通过摄像头采集图片,通过驱动将数据流存储到JPEG图库,最终通过html交给用户的浏览器来解析,而mjpeg-streamer用来实现对这一流程的的控制。构成mjpeg-streamer视频流服务器。

当所有的工作完成后,启动mjpg-streamer视频流服务器,然后在打开这个网页:

1
http://<开发板IP>:8080/?action=stream

就可以看到我们采集到的视频流了,后边一直完成的测试会有演示。

二、文件准备

1. jpeg 库

1.1 源码获取途径

关于 jpeg 库的官方源码我们可以从这里获取:Directory Listing of /files (ijg.org)

1.2 获取源码文件

我下载的是 jpegsrc.v8b.tar.gz 这个压缩包并将其存放于 ubuntu 下的共享文件夹下,路径为:

1
/mnt/hgfs/Sharedfiles/jpegsrc.v8b.tar.gz

1.3 拷贝解压

然后我们可以将这个源码文件拷贝解压到 ubuntu 中,方便后边编译,我们可以在终端执行以下命令:

1
2
3
cp /mnt/hgfs/Sharedfiles/jpegsrc.v8b.tar.gz ~/5linux/    # 拷贝压缩包
cd ~/5linux/
tar xvf jpegsrc.v8b.tar.gz # 解压

然后我们可以得到下边这些文件(通过 ls 命令查看):

image-20220908195109650

还有很多文件,图中仅显示了一部分。

2. mjpg-stream

2.1 源码获取途径

关于 mjpg-stream 的官方源码我们可以从这里获取:MJPG-streamer-Code-r182 (sourceforge.net)

2.2 获取源码文件

我下载的是 182 版本的压缩包,并将其存放于 ubuntu 下的共享文件夹下,路径为:

1
/mnt/hgfs/Sharedfiles/mjpg-streamer-code-r182.zip

1.3 拷贝解压

然后我们可以将这个源码文件拷贝解压到 ubuntu 中,方便后边编译,我们可以在终端执行以下命令:

1
2
3
cp /mnt/hgfs/Sharedfiles/mjpg-streamer-code-r182.zip ~/5linux/    # 拷贝压缩包
cd ~/5linux/
unzip mjpg-streamer-code-r182.zip # 解压

然后我们可以得到下边这些文件(通过 ls 命令查看):

image-20220908195641133
点击查看部分文件说明
目录名说明
mjpg-streamer提供了执行程序和各个输入输出设备组件
uvc-streamer提供了 uvc-streamer的可执行目录
mjpeg-client分别有 linux和windows 的客户端

三、 USB 支持

我们后边要使用 USB 摄像头,就需要先添加 USB 驱动的支持,之前的时候我们已经移植了 USB 驱动,可以看这篇笔记:《LV10-06-USB驱动移植》,但是这里还需要一些其他的支持。

1. 已有配置

我们还是先来看一下之前做驱动移植的时候已经配置过的选项:

1.1 USB support

1
2
3
4
5
6
7
8
Device Drivers  --->
[*] USB support --->
<*> EHCI HCD (USB 2.0) support
<*> EHCI support for Samsung S5P/EXYNOS SoC Series
<*> USB Mass Storage support
<*> USB3503 HSIC to USB20 Driver
USB Physical Layer drivers --->
<*> Samsung USB 2.0 PHY controller Driver

1.2 SCSI device support

1
2
3
4
5
Device Drivers  --->
SCSI device support --->
<*> SCSI device support
<*> SCSI disk support
<*> SCSI generic support

2. 新增配置

2.1 Multimedia support

我们首先进入 Multimedia support 选项中:

image-20220908200205038

然后开始进行自选项的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Device Drivers  --->
<*> Multimedia support --->
[*] Cameras/video grabbers support
[*] Media Controller API
[*] V4L2 sub-device userspace API
[*] Media USB Adapters --->
<*> USB Video Class (UVC)
[*] UVC input events device support
<*> GSPCA based webcams --->
<*> ZC3XX USB Camera Driver
<*> CPiA2 Video For Linux
[*] V4L platform devices --->
<*> Support for timberdale Video In/LogiWIN
<*> SoC camera support
<*> platform camera support

3. 编译内核

配置完成后我们重新编译内核:

1
2
cd ~/5linux/linux-3.14/
make uImage

最后将重新生成的 uImage 拷贝到 tftp 服务器中:

1
cp ~/5linux/linux-3.14/arch/arm/boot/uImage ~/3tftp/fs4412/

4. 重启测试

我们重启开发板,让其重新加载内核,然后我们插上 USB 摄像头,若有以下信息输出,说明摄像头已被开发板识别:

1
2
3
[root@farsight]#[  293.180000] usb 1-3.1: new high-speed USB device number 5 using exynos-ehci
[ 293.365000] uvcvideo: Found UVC 1.00 device USB2.0 PC CAMERA (1908:2311)
[ 293.375000] input: USB2.0 PC CAMERA as /devices/12580000.ehci/usb1/1-3/1-3.1/1-3.1:1.0/input/input3

摄像头的设备节点一般是 video 开头,我们查看一下 /dev/ 下是否有这样的设备:

1
2
[root@farsight]#ls /dev/video*
/dev/video0

四、jpeg 库移植

我们移植 mjpg-stream 的时候需要用到 jpeg 的库,所以需要先移植 jpeg 的库。我们首先进入刚才解压的目录:

1
cd ~/5linux/jpeg-8b/

1. 创建一个目录

我们首先创建一个目录用于存放最终生成的文件:

1
mkdir jpegarm

应该是创建在哪都可以,我比较懒,直接创建到解压的目录下了,所以这个新建的目录路径为(后边有用):

1
/home/hk/5linux/jpeg-8b/jpegarm

老师给的文档中说这个目录建议自己创建一个在 mjpeg-streamer (后边移植它的时候就会看到这个目录了)的上一级目录下。

2. 配置源码

我们在 jpeg 源码目录下执行以下命令:

1
./configure --prefix=/home/hk/5linux/jpeg-8b/jpegarm --host=arm-none-linux-gnueabi
  • –prefix 表示最终生成的库和头文件等存放的目录,自己指定一个存在的路径就可以,后面编译 mjpeg-streamer 的时候会用到,此处必须使用绝对路径。
  • –host=arm-none-linux-gnueabi 中 –host 表示生成的库的运行平台,注意是两个 - ,末尾不能加 - 。

【注意】 ./configure 之后为一行命令。

3. 编译源码

我们在 jpeg 源码目录下执行:

1
2
cd ~/5linux/jpeg-8b/
make

这样便会完成 jpeg 源码的编译了。

4. 安装到创建的目录

我们在 jpeg 源码目录下执行:

1
2
cd ~/5linux/jpeg-8b/
make install

然后我们查看一下我们刚才创建的目录(使用 ls 命令),将会生成以下文件:

1
2
hk@vm:~/5linux/jpeg-8b$ ls jpegarm
bin include lib share

5. 拷贝库文件到系统

这里我们需要把生成的 jpegarm/lib 目录下的所有文件拷贝到根文件系统的 /lib 目录下:

1
sudo cp -v ~/5linux/jpeg-8b/jpegarm/lib/* ~/4nfs/rootfs/lib/

五、mjpg-streamer 移植

前边我们已经解压好了文件,我们可以进入解压后的目录:

1
cd ~/5linux/mjpg-streamer-code-r182/

1. 源码修改

这里我们主要是修改 Makefile 文件,我们进入 mjpg-streamer 目录,并打开 plugins/input_uvc/Makfile 文件:

1
2
cd ~/5linux/mjpg-streamer-code-r182/mjpg-streamer
plugins/input_uvc/Makfile

(1)我们找到如下语句:

1
CFLAGS += -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC

将其修改为:

1
CFLAGS += -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I /home/hk/5linux/jpeg-8b/jpegarm/include

其实就是添加了 -I 参数,后边的路径记得换成自己上一步在 jpeg 库移植部分创建的那个目录中的 include 目录。

(2)我们找到如下语句:

1
2
input_uvc.so: $(OTHER_HEADERS) input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo
$(CC) $(CFLAGS) -o $@ input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo $(LFLAGS)

将其修改为:

1
2
input_uvc.so: $(OTHER_HEADERS) input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo
$(CC) $(CFLAGS) -L /home/hk/5linux/jpeg-8b/jpegarm/lib -o $@ input_uvc.c v4l2uvc.lo jpeg_utils.lo dynctrl.lo $(LFLAGS)

其实就是添加了 -L 参数,后边的路径记得换成自己上一步在 jpeg 库移植部分创建的那个目录中的 lib 目录。

2. 编译源码

然后我们到 mjpg-streamer 目录,编译源码:

1
2
cd ~/5linux/mjpg-streamer-code-r182/mjpg-streamer
make CC=arm-linux-gcc
点击查看可能出现的问题

我们编译的时候可能会报以下问题:

1
make: svnversion: Command not found

我们执行以下命令安装 subversion 即可:

1
2
3
sudo apt-get update             # 更新软件源
sudo apt-get -f install # 更新依赖
sudo apt-get install subversion

编译完成后会生成一些库和可执行文件:

1
2
3
4
hk@vm:~/5linux/mjpg-streamer-code-r182/mjpg-streamer$ ls *.so
input_file.so input_testpicture.so input_uvc.so output_file.so output_http.so output_udp.so
hk@vm:~/5linux/mjpg-streamer-code-r182/mjpg-streamer$ ls mjpg_streamer
mjpg_streamer
文件名 说明
input_testpicture.so 这是一个图像测试插件,它将预设好的图像编译成一个头文件,可以在没有摄像头的情况下传输图像,从而方便调试程序。
input_uvc.so 此文件调用USB摄像头驱动程序V4L2,从摄像头读取视频数据。
output_http.so 这是一个功能齐全的网站服务器,它不仅可以从单一文件夹中处理文件,还可以执行一定的命令,它可以从输入插件中处理一幅图像,也可以将输入插件的视频文件根据现有M-JPEG标准以HTTP视频数据服务流形式输出。
output_file.so 这个插件的功能是将输入插件的JPEG图像存储到特定的文件夹下,它可以用来抓取图像。

3. 修改 start.sh

mjpg-stream 支持 JPEG 和 YUV 两种格式的输出,默认输出格式为 JPEG ,而后边经过实验证明我使用的这款摄像头是 YUV 输出的,所以就需要修改 start.sh 啦(不修改的话可能就是可以正常启动摄像头,但是没有视频输出),我们打开 start.sh 文件:

1
vim /home/hk/5linux/mjpg-streamer-code-r182/mjpg-streamer/start.sh 

然后找到如下语句:

1
./mjpg_streamer -i "./input_uvc.so" -o "./output_http.so -w ./www"

我们修改为以下内容,就可以指定输出格式为 YUV 啦:

1
./mjpg_streamer -i "./input_uvc.so -y" -o "./output_http.so -w ./www"

【注意】这里需要我们提前确认好摄像头的图像输出格式。

4. 安装到开发板

  • 创建相关目录

我们在开发板的根文件系统创建文件夹用于存放 mjpg_streamer 所需要的文件:

1
sudo mkdir /home/hk/4nfs/rootfs/mjpg-streamer
  • 拷贝文件

接下来向根文件系统中的 mjpg-streamer 目录中添加文件:

1
2
3
4
5
6
7
cd /home/hk/5linux/mjpg-streamer-code-r182/mjpg-streamer/

sudo cp -v ./*.so /home/hk/4nfs/rootfs/mjpg-streamer/

sudo cp -v mjpg_streamer /home/hk/4nfs/rootfs/mjpg-streamer/

sudo cp -rv start.sh www/ /home/hk/4nfs/rootfs/mjpg-streamer/

5. 启动测试

我们来到开发板根文件系统的 mjpg-streamer 目录,执行以下命令:

1
2
[root@farsight]#cd /mjpg-streamer/
[root@farsightmjpg-streamer]#./start.sh

这样便可以启动 mjpg-streamer 了,若是启动不报错,启动正常的话可能会出现下边的提示信息:

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
MJPG-streamer [1410]: starting application
MJPG Streamer Version: svn rev: 目录 未版本控制
MJPG-streamer [1410]: MJPG Streamer Version: svn rev: 目录 未版本控制

i: Using V4L2 device.: /dev/video0
MJPG-streamer [1410]: Using V4L2 device.: /dev/video0

i: Desired Resolution: 640 x 480
MJPG-streamer [1410]: Desired Resolution: 640 x 480

i: Frames Per Second.: 5
MJPG-streamer [1410]: Frames Per Second.: 5

i: Format............: YUV
MJPG-streamer [1410]: Format............: YUV

i: JPEG Quality......: 80
MJPG-streamer [1410]: JPEG Quality......: 80

Adding control for Pan (relative)
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Tilt (relative)
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Pan Reset
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Tilt Reset
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Pan/tilt Reset
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Focus (absolute)
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
mapping control for Pan (relative)
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Tilt (relative)
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Pan Reset
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Tilt Reset
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Pan/tilt Reset
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Focus (absolute)
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for LED1 Mode
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for LED1 Frequency
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Disable video processing
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Raw bits per pixel
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
o: www-folder-path...: ./www/
MJPG-streamer [1410]: www-folder-path...: ./www/

o: HTTP TCP port.....: 8080
MJPG-streamer [1410]: HTTP TCP port.....: 8080

o: username:password.: disabled
MJPG-streamer [1410]: username:password.: disabled

o: commands..........: enabled
MJPG-streamer [1410]: commands..........: enabled

MJPG-streamer [1410]: starting input plugin ./input_uvc.so
MJPG-streamer [1410]: starting output plugin: ./output_http.so (ID: 00)

上边的那些 error 可以忽略掉,并不影响我们采集图像。我们打开一个网页,在地址栏输入以下内容,便可以看到图像啦:

1
http://<开发板IP>:8080/?action=stream

若是一切正常的话,我们将会看到如下信息:

image-20220909071115108

一般来说 mjpg-streamer 默认使用的是 8080 端口。但是似乎并不会这么顺利的看到图像,可能会出现各种问题,出现的问题及解决方法笔记的第五章中。

六、问题解决

1. 问题一

MJPEG 格式错误的话可能会报以下问题:

1
2
3
4
ERROR opening V4L interface: No such file or directory
Init v4L2 failed !! exit fatal
i: init_VideoIn failed
MJPG-streamer [1296]: init_VideoIn failed

【解决方法】

一般来讲出现这个问题应该都是没有这个设备节点的,插上 USB 摄像头,查看设备节点,确认是否成功创建了设备节点

1
[root@farsight]#ls /dev/video0

没有设备节点的话说明我们的 USB 驱动很可能移植的有问题,这个时候我们需要重新看一下 USB 支持这一部分相关的笔记,看一下是不是有哪里忘记配置了,然后重新编译内核,重启开发板即可。

  • 《LV13-03-mjpg-stream移植——二、USB支持》
  • 《LV10-06-USB驱动移植》

2. 问题二

视频流格式错误可能会报以下问题:

1
cannot be displayed because it contains errors

【解决方法】

修改 start.sh 文件,加参数 -y ,然后运行 start.sh

1
./mjpg_streamer -i “./input_uvc.so -y” -o “./output_http.so -w ./www” 

3. 问题三

缺少相关库的支持,可能会报下边的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
MJPG-streamer [1308]: starting application
MJPG Streamer Version: svn rev:
MJPG-streamer [1308]: MJPG Streamer Version: svn rev:

ERROR: could not find input plugin
MJPG-streamer [1308]: ERROR: could not find input plugin

Perhaps you want to adjust the search path with:
MJPG-streamer [1308]: Perhaps you want to adjust the search path with:

# export LD_LIBRARY_PATH=/path/to/plugin/folder
MJPG-streamer [1308]: # export LD_LIBRARY_PATH=/path/to/plugin/folder

dlopen: libjpeg.so.8: cannot open shared object file: No such file or directory
MJPG-streamer [1308]: dlopen: libjpeg.so.8: cannot open shared object file: No such file or directory

【解决方法】

重新拷贝相关库:

1
2
3
4
5
6
sudo cp -v ~/5linux/jpeg-8b/jpegarm/lib/* ~/4nfs/rootfs/lib/

cd /home/hk/5linux/mjpg-streamer-code-r182/mjpg-streamer/
sudo cp -v ./*.so /home/hk/4nfs/rootfs/mjpg-streamer/
sudo cp -v mjpg_streamer /home/hk/4nfs/rootfs/mjpg-streamer/
sudo cp -rv start.sh www/ /home/hk/4nfs/rootfs/mjpg-streamer/

需要注意的是,要保证我们拷贝的库是 arm 格式的,我们可以用 file 命令确认,如

1
file libjpeg.so.8

4. 问题四

1
2
Init v4L2 failed !! exit fatal 
init_VideoIn failed

市面上大部分摄像头都是支持 YUV 的,而不是 JPEG 的,这个问题一般会出现在 ./start.sh 过程中。

【解决方法】

由于 mjpg-stream 支持 JPEG 和 YUV 两种格式,所以只需修改 start.sh ,在输入中加入 - y :

1
./mjpg_streamer -i “./input_uvc.so -y” -o “./output_http.so -w ./www”