使用v4l2loopback实现一个摄像头同时实现IP摄像头和OpenCV视频处理
一个程序在读取摄像头时,如果另一个程序读取这个摄像头,会提示“设备繁忙”的错误,本文使用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 | v4l2-ctl --list-devices #查看连接的v4l2设备 |
需要注意的是,如果摄像头不支持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 | cd v4l2rtspserver |
编译完成后,开始运行
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 | git clone https://github.com/umlaeute/v4l2loopback.git |
以下命令可以不执行,不影响使用,执行的话可以使用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 | sudo apt remove mplayer |
开始播放
1 | mplayer tv:// -tv driver=v4l2:device=/dev/video0 |
ffmpeg
使用ffmpeg把视频流/真实摄像头输入虚拟设备中
1 | ffmpeg -f v4l2 -i /dev/video0 -f v4l2 /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 | sudo apt install libtool autoconf |