Blog:
在嵌入式 Linux 系统使用摄像头

2016年7月28日星期四
Camera

Camera

引言

本博文介绍了在 计算机模块(COM) / 系统模块(SOM)上查看和记录视频的多种方法。本章使用的计算机模块是成本敏感产品的理想选择,其不带视频硬件编解码器。

在嵌入式 Linux 系统使用摄像头

俗话说“眼见为实”,这或许是为什么近年来摄像头在嵌入式系统上快速增长的原因。它们被用于不同的场景,如:

    • 远程监控:典型的例子是闭路电视,监控人员在监视环境(或许你所在的大楼就有)或者警察监控城市状况。
    • 安防录像:监视系统或许能够记录视频,并不是所有的监控系统都一直需要监视人员,它们只是在有情况发生时提供监控证据。
    • 嵌入式视觉系统:计算机监控系统处理图像从而获取更加复杂的信息。我们可以在雷达和城市交通监控系统中看到类似的应用。
    • 作为传感器:许多医疗诊断系统都是基于图像分析。另外一个应用是智能购物窗,鉴别用户的特征,提供针对性的营销。
所使用的硬件

我们将会使用 Colibri VF61 模块,其采用 NXP®/Freescale Vybrid 处理器,这是一个异构双核处理器(Arm® Cortex-A5 + Arm Cortex-M4)。除了处理器,模块还有 256MB RAM 和 512 MB Flash。这本博文中,我们将只用到 Cortex™-A5。尽管没有硬件视频加速器,你还是可以用该处理器完成许多视频相关的任务。更多关于 Colibri VF61 的信息和说明可以参考 Toroadex 网站的 开发者中心

摄像头是 Logitech HD 720p,一般的 mjpeg USB 模块和 D-Link DCS-930L IP 摄像头。

本为使用的 Linux 有 LXDE 桌面环境,这也是我们标准的镜像。我们的标准镜像可以在从 开发者中心网站。本次所使用的是 V2.4 版本镜像。我们将会使用在多媒体应用中广泛使用的 GStreamer 框架。GStreamer 提供了诸如视频编辑、媒体传输和播放等多媒体应用服务。一系列的插件使得 GStreamer 能够支持许多不同的媒体格式,如 MP3、ffmpeg 等。这些插件包括输入和输出组件、滤镜、编解码器等。

安装必要的软件

该指导基于我们的 V2.4 Linux 镜像所编写并测试。在写这篇文章时,V2.5 缺失一个 GStreamer 所依赖软件的源。目前我们正在调查这个问题。解决方案是,你可以从下面的链接中手动下载和安装缺失的依赖软件:
http://feeds.angstrom-distribution.org/feeds/v2015.06/ipk/glibc/armv7ahf-vfp-neon/base
这是安装 GStreamer、Video4Linux2 以及其他软件所需要的。在模块的终端里运行下面的命令:

opkg update
 
opkg install gst-plugins-base-meta gst-plugins-good-meta gst-ffmpeg

通过 gst-inspect 命令,你可以看到之前安装的插件和组件。下面是一些安装的插件和组件。


Plugins and elements installed
图1:装的插件和组件

Pipelines 和 Elements 简介

根据 GStreamer Application Development Manual第三章所述,element 是 GStreamer 中最重要的对象。通常你可以创建一个相互连接的 element 链,数据从 element 链上经过。每一个 element 都有特定的功能,例如读取文件、解码、显示等。element 组合成的链成为 pipeline,这可以用于执行特定的任务,如视频播放或者采集。GStreamer 默认包含了大量的 element,使其可以开发各种多媒体应用。在这篇文章中我们会使用一些 pipeline 为您介绍 element。

下面是典型的 Ogg 播放器 pipeline,其中使用一个 demuxer 和两个 branche, 分别用于视频和音频。我们可以看到一些 element 只有 src 输入,其他的只具有一个 sink 或者兼有两者。


Gstreamer pipeline for a simple ogg player
图2:Ogg 播放器 pipeline。图片引用 http://gstreamer.freedesktop.org

在创建 pipeline 的时候,你需要使用 gst-inspect 检查所需的插件是否相互兼容。我们使用 ffmpegcolorspace 作为演示。在终端中运行下面的命令:

gst-inspect ffmpegcolorspace

然后,你可以看到如下关于插件的描述:

Factory Details:
  Long name: FFMPEG Colorspace converter
  Class: Filter/Converter/Video
  Description: Converts video from one colorspace to another
  Author(s): GStreamer maintainers 

以及插件所支持的 source 和 sink:

SRC template: 'src'
    Availability: Always
    Capabilities:
      video/x-raw-yuv
      video/x-raw-rgb
      video/x-raw-gray
 
SINK template: 'sink'
    Availability: Always
    Capabilities:
      video/x-raw-yuv
      video/x-raw-rgb
      video/x-raw-gray

另外一个例子是 v4l2src.。它只有 source 输入,可以读取源视频并发送到另外一个 element。查看 ximagesink element,我们发现其支持 rgb 格式 sink 输出。

参考下面的文档 http://gstreamer.freedesktop.org/documentation/plugins.html 并配合使用 gst-inspect,能够帮助你了解 element 的功能和他们的属性。


显示测试视频

通过下面命令显示测试视频:

gst-launch videotestsrc ! autovideosink

Video test pattern
图 3:视频测试

autovideosink \element 自动检测视频输出。videotestsrc 用于生产各种格式的测试视频,可以使用 pattern 参数进行设置。

gst-launch videotestsrc pattern=snow ! autovideosink

Vídeo test with snow pattern
图4: 雪花测试视频。

显示网络摄像头视频

连接的网络摄像头会在 /dev/videox 目录下显示,其中 x 可以是 0、1、2 等,这取决于连接到电脑的摄像头数量。


Connected capture devices
图5:连接的摄像头设备

使用下面命令全屏显示网络摄像头:

gst-launch v4l2src device=/dev/video0 ! ffmpegcolorspace ! ximagesink

Webcam in fullscreen mode
图6:全屏模式网络摄像头

下面的连接展示了全屏模式网络摄像头: video_webcam_fullscr.mp4

Video4Linux 是捕捉和播放的 API 以及驱动框架,支持多种类型的 USB 摄像头和设备。v4l2src 是 Video4Linux2 的一个插件,从 Video4Linux2 设备中读取数据帧,在我们的演示中这就是网络摄像头。

ffmpegcolorspace 是一个用于转化多种色彩格式的滤镜。摄像头一般输出 YUV 色彩格式,然而显示则使用 RGB 格式。

ximagesink 基于桌面 X 的标准 videosink。

我们可以使用 top 命令查看显示网络摄像头视频时 gstreamer 所使用的是 CPU 和内存资源。在第一个演示中,我们看到了 77.9% 的 CPU 负载。.

top - 16:32:37 up  4:36,  2 users,  load average: 0.83, 0.28, 0.13
Tasks:  72 total,   1 running,  70 sleeping,   0 stopped,   1 zombie
Cpu(s): 69.3%us, 7.1%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 23.6%si,0.0%st
Mem:  235188k total,   107688k used,   127500k free,       0k buffers
Swap:   0k total,       0k used,      0k free,     61232k cached
 
PID  USER  PR  NI VIRT  RES  SHR  S %CPU %MEM   TIME+   CoMMAND 
1509 root  20  0  39560 8688 6400 S 77.9  3.7   0:16.83 gst-launch-0.10 
663  root  20  0  17852 8552 4360 S 19.7  3.6   4:12.32 X 
1484 root  20  0  2116  1352 1144 R 1.3   0.6   0:00.80 top

也可以使用诸如 size 等其他参数的属性来显示视频。width、height 和 framerate 参数可以根据摄像头所支持进行配置。针对摄像头1、2、3 分别执行一下命令(这里连接了 3 个摄像头)显示 320x240 或者其他格式的视频。

gst-launch v4l2src device=/dev/video0 ! 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace ! ximagesink 
gst-launch v4l2src device=/dev/video1 ! 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace ! ximagesink
gst-launch v4l2src device=/dev/video2 ! 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace ! ximagesink

Displaying the webcam video on a 320x240 screen
图7:显示 320x240 网络摄像头视频。

本次,CPU 负荷为 28.2%。


同时显示两个摄像头

你可以同时显示两个摄像头。我们使用下面的 Logitech HD 720p 摄像头和一般的 MJPEG USB 摄像头模组测试下面的 pipeline 。

gst-launch v4l2src device=/dev/video0 !
 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace 
 ! ximagesink v4l2src device=/dev/video1 
 'video/x-raw-yuv,width=320,height=240,framerate=30/1' ! ffmpegcolorspace ! 
 ximagesink

Two screens playing simultaneously
图8:双摄像头同时显示

下面的链接是双网络摄像头同时显示的视频: video_duas_webcams.mp4

这个测试中 CPU 负荷为 64.8%。


录制视频

使用下面 pipeline 录制 MP4 格式的视频:

gst-launch --eos-on-shutdown v4l2src device=/dev/video0 ! ffmux_mp4 ! filesink location=video.mp4

命令 --eos-on-shutdown 用于正确关闭文件。ffenc_mjpeg 是 MJPEG 格式编码器参数。 ffmux_mp4 MP4 格式混合器。filesink 表明来自 v4l2 的数据需要存储在一个文件中,而不是在 ximagesink 中显示。你也可以指定目标目录。

您可以观看下面链接的视频: recording_video1.mp4来查看模块所录制视频的质量。

录制以上视频大致需要 8% 的 CPU 负载。


视频播放

使用下面的 pipeline 播放方才录制的视频:

gst-launch filesrc location=video.mp4 ! qtdemux name=demux demux.video_00 ! queue ! ffdec_mjpeg ! ffmpegcolorspace ! ximagesink 

这时,视频源来自于 filesrc,例如视频来自一个文件,而不是网络摄像头视频设备。这个视频之前使用 mjepg 编码,所以需要使用 ffdec_mjpeg 解码。

由于之前网络摄像头使用最大分辨率录制的视频,CPU 负载在 95% 左右。


使用 HTTP 播放视频

我们使用下面的 pipeline 查看之前录制的视频:

gst-launch souphttpsrc location=http://upload.wikimedia.org/wikipedia/commons/4/4b/MS_Diana_genom_Bergs_slussar_16_maj_2014.webm ! matroskademux name=demux demux.video_00 ! queue ! ffdec_vp8 ! ffmpegcolorspace ! ximagesink 

souphttpsrc 使用 HTTP 通过网络作为客户端接收数据。在这个应用中,location 参数使用包含视频文件的 URL,而不是文件。注意,ffdec_vp8 被用于解码 webm 格式。

这时,CPU 负载大致为 40%。


使用 TCP 从网络摄像头传输视频

我们也可以从 VF61 模块上向运行 Ubuntu Linux 的电脑传输视频。
         IP VF61 = 192.168.0.8
         IP Ubuntu = 192.168.0.7
在 VF61 终端上运行下面的 pipeline:

gst-launch v4l2src device=/dev/video1 ! video/x-raw-yuv,width=320,height=240 ! ffmpegcolorspace ! ffenc_mjpeg ! tcpserversink host=192.168.0.7 port=5000

同时在电脑主机上运行下面 pipeline 查看传输的视频:

gst-launch tcpclientsrc host=192.168.0.8 port=5000 ! jpegdec ! autovideosink

注意,IP 地址需要根据您的配置情况调整。在终端中运行 ifconfig 查看您的 IP 地址。

下面的链接是上面演示的视频: video_streaming_webcam.mp4
这里使用 Logitech HD 720p 摄像头,CPU 负载大约 65%。

D-Link 网络摄像头和 VF61 模块
显示网络摄像头的视频

这例子中,我们使用 D-Link DCS-930L 网络摄像头。该摄像头被配置成传输 320x240,15fps 的一般质量 JPEG 格式视频。CPU 的负载会根据网络摄像头设置的不同而变换。

Camera D-Link DCS-930L
图9:D-Link DCS-930L 网络摄像头

Setup screen for D-Link IP Camera
图10:D-Link 网络摄像头设置

在模块的终端上,使用下面的 pipeline 查看网络摄像头视频:

gst-launch -v souphttpsrc location='http://192.168.0.200/video.cgi' is-live=true ! multipartdemux ! decodebin2 ! ffmpegcolorspace ! ximagesink 

IP Camera streaming on module’s screen
图11:模块屏幕上网络摄像头视频传输

下面的链接是以上演示视频: video_streaming_ipcam.mp4


网络摄像头录制

您也可以在 VF61 上使用下面 pipeline:

gst-launch --eos-on-shutdown –v souphttpsrc location='http://192.168.0.200/video.cgi' is-live=true ! multipartdemux ! decodebin2 ! ffmpegcolorspace ! ffenc_mjpeg ! ffmux_mp4 ! filesink location=stream.mp4

您可以观看下面的视频来分析录像的质量: video_gravacao_ipcam.mp4
摄像头分辨率 320x240, 15fps,一般 JPEG 质量, CPU 复杂大约为 40%。


不同 IP 间 TCP 视频传输

这次我们将从一个网络摄像头传输视频到 VF61 模块,并且同时向另外一个 IP 传输视频。

在 VF61 模块终端上执行下面命令:

gst-launch --eos-on-shutdown –v souphttpsrc location='http://192.168.0.200/video.cgi' is-live=true ! multipartdemux ! decodebin2 ! ffmpegcolorspace ! ffenc_mjpeg ! Tcpserversink host=192.168.0.12 port 5000

此时,CPU 负载为 95%。

使用下面命令在 Linux 电脑上查看来自模块的视频:

gst-launch tcpclientsrc host=192.168.0.8 port=5000 ! jpegdec ! autovideosink
下面是上述性能测试中 CPU 和 RAM 对比表
Test performed
%CPU %MEM
Displaying Video From a Webcam 28.2 2.7
Displaying Two Cameras Simultaneously 64.8 3.1
Recording Video 8.0 4.9
Video Playback 95.0 3.9
Video Playback Using HTTP 41.9 4.1
Video Streaming Using TCP 66.0 3.6
Displaying Video from IP camera 25.2 3.3
IP camera recording 40.1 3.9
TCP streaming IP to IP 95.2 4.8

结论

文章涉及到的内容,包括 GStreamer 各种变量的理论研究和学习,需要花费几天时间。掌握 plugins 和 使用 gst-inspect,你可以查看每个 plugin 的属性,组建各个 elements 之间相互兼容的 pipeline。同时,在网上也有大量例子,可以帮助你组建 pipeline。读者或许也需要向本文一样进行研究。安装和检查 plugin 属性对于组建 pipeline 以及找到于文中所用设置兼容的 GStreamer element 十分有必要。

NXP/Freescale Vybrid VF61 处理器能满足多种媒体和视频处理的要求,即使没有针对这些任务的特定硬件加速器。该处理器在执行视频和图形相关任务时所表现的性能,我们对此感到十分惊讶。

VF61 Vybrid 是不需要太多视频处理需求的成本敏感型嵌入式设备的理想选择。但是对于需要以更好的性能处理视频时,例如嵌入式视觉系统,我们建议使用同样来自 NXP/Freescale 的 iMX6,其带有专门的视频处理器。


参考

本博文最初以葡萄牙语在 Embarcados.com 发表. 请查看这里

作者: Giovanni Bauermeister, Toradex Brasil

1 comments

KIms - 7 years 7 months | Reply

It would be neat to see a sister-article to this, that looks at a front+rear facing car dash-cam with GPS and text overlay on the recordings, with a focus on file management and handling continuous recordings.

评论

Please login to leave a comment!
Have a Question?