一个程序在读取摄像头时,如果另一个程序读取这个摄像头,会提示“设备繁忙”的错误,本文使用v4l2loopback将一个真实摄像头虚拟成两个,实现两个程序读取同一个摄像头拍摄的视频。

v4l-utils

v4l-utils使用来管理媒体设备的一系列工具,首先安装v4l-utils工具

1
sudo apt install v4l-utils

将媒体设备与开发板连接(USB摄像头),若连接成功,在/dev/目录下会出现video设备

1
ls /dev/video*

使用v4l-utils中的v4l-ctl命令工具查看设备信息

1
2
3
v4l2-ctl --list-devices #查看连接的v4l2设备
v4l2-ctl --list-formats #查看设备支持的拍摄格式
v4l2-ctl -d /dev/video0 --all #查看设备的详细信息

需要注意的是,如果摄像头不支持h264格式录制(例如本博客使用的摄像头支持MJPG与YUYV),那传输视频流的时候只能使用rtsp或rtmp。http+flv、hls等格式无法使用,因为他们只支持h264格式的视频流。

v4l2rtspserver

RTSP协议

Real-Time Messaging Protocol(RTMP)和The Real-Time Streaming Protocol (RTSP)是目前使用较广泛的流媒体协议之一。

RTSP传输一般需要2-3个通道,命令和数据通道分离,HTTP和RTMP一般在TCP一个通道上传输命令和数据。RTSP 本身不传输数据流,而是配合 RTP/RTCP 一起使用,RTSP 负责控制传输。

由于 Flash 的普及度降低,chrome与firefox均停止了对Flash的支持,RTMP 的使用也在逐渐减少,被如 HLS(HTTP Live Streaming)和 DASH(Dynamic Adaptive Streaming over HTTP)等其他流媒体传输协议替代。

编译安装

v4l2rtspserver是一个v4l2设备的rtsp服务器,首先下载v4l2rtpserver源码

1
git clone --recursive https://github.com/mpromonet/v4l2rtspserver.git 

v4l2rtspsever的依赖库如下:

  • liblivemedia-dev:会在编译的时候自动下载
  • libv4l2cpp:已作为子模块包含在源码中
  • liblog4cpp5-dev :可选项,增强日志功能
  • libasound2-dev :可选项,增加音频传输功能

开始编译

1
2
cd v4l2rtspserver
cmake . && make

编译完成后,开始运行

1
./videortspserver -v -W 640 -H 480 /dev/video0

运行该命令后会输出直播url,可以输入至VLC播放器或者IP摄像头app进行远程查看。

./ffmpeg -f v4l2 -input_format mjpeg -i /dev/video0 -c:v mjpeg -f v4l2 /dev/video2

v4l2loopback

v4l2loopback可以创建多个虚拟的媒体设备,我们可以把虚拟设备当作摄像头来使用,下载v4l2源码并进行编译

1
2
3
git clone https://github.com/umlaeute/v4l2loopback.git
cd v4l2loopback
make

以下命令可以不执行,不影响使用,执行的话可以使用modprobe命令更方便地实现内核模块安装,但是本文在这一步出现了问题,因此放弃了。

1
sudo make install 

在v4l2loopback目录中执行以下命令,安装v4l2loopback内核模块,一下命令将

1
sudo insmod v4l2loopback.ko devices=2 exclusive_caps=1,1 video_nr=2,3 card_label="IP Camera","OpenCV Camera"

也可以使用v4l2loopback-ctl来动态管理虚拟设备,但是还没有测试过

Mplayer

可以使用mplayer来测试虚拟设备,使用包管理器自带的mplayer会报错

1
mplayer: symbol lookup error: mplayer: undefined symbol: av_alloc_vdpaucontext, version LIBAVCODEC_58

重新编译mplayer可以解决这个问题

1
2
3
4
5
6
7
sudo apt remove mplayer
wget https://mplayerhq.hu/MPlayer/releases/MPlayer-1.5.tar.gz
tar -xzvf MPlayer-1.5.tar.gz
cd MPlayer-1.5/
./configure
make -j6
sudo make install

开始播放

1
mplayer tv:// -tv driver=v4l2:device=/dev/video0

ffmpeg

使用ffmpeg把视频流/真实摄像头输入虚拟设备中

1
2
ffmpeg -f v4l2 -i /dev/video0 -f v4l2 /dev/video2
ffplay /dev/video2

使用ffmpeg将摄像头的内容复制到/dev/video2/dev/video3两个虚拟设备中

1
./ffmpeg -f v4l2 -input_format mjpeg -i /dev/video0 -c:v copy -f v4l2 /dev/video2 -c:v copy -f v4l2 /dev/video3

此时就可以使用v4l2rtspserver读取/dev/video2中的内容,使用opencv读取/dev/video3中的内容了

v4l2tools

v4l2tools是一个可以压缩、复制v4l2设备的工具,本文中使用ffmpeg代替了这个工具

1
2
3
4
sudo apt install libtool autoconf
git clone --recursive https://github.com/mpromonet/v4l2tools
make
make install