【发布时间】:2017-11-14 11:29:57
【问题描述】:
我想通过 OpenCV 将视频叠加到传入的网络摄像头流上。作为第一步,我尝试将来自/dev/video0 的网络摄像头的传入视频流式传输到/dev/video1 的虚拟视频设备(v4l2loopback)。不幸的是,我无法将网络摄像头流转发到 v4l2loopback 设备。
我找到了这个帖子:How to write/pipe to a virtual webcam created by V4L2loopback module?,但那里的链接并没有真正帮助我。
使用来自 OpenCV 页面的一些小演示代码,从网络摄像头获取和观看视频流效果很好。以及来自 v4l2loopback 页面的示例代码,例如将静态视频文件播放到/dev/video1 效果很好。当我将 VLC 连接到/dev/video1 时,我可以观看视频
我已经读到 v4l2loopback 设备必须通过常规 Linux 驱动程序命令(open、ioctl、write 等)来控制。因此,OpenCV 中没有用于写入环回设备的包装类。我的网络摄像头以 640x480 和 MJPG 格式流式传输。有趣的是,我可以使用 VLC 连接到环回设备,当我按下播放时,我可以看到正确的分辨率、编解码器和 FPS。进度条上的时间计数器也开始运行。但是屏幕仍然是黑色的(带有 VLC 标志)。
我大致做的是这个(顺便说一句:代码可能无法编译......不想让这里的一切变得混乱......如果您需要更多详细信息,请告诉我):
int main ( int argc, char **argv ) {
cv::VideoCapture cap;
struct v4l2_format vid_format;
size_t framesize = 640 * 480 * 3; // 3 Bytes per pixel
__u8 *buffer = null;
int fd = null;
cap.open ( "/dev/video0" );
fd = open ( "/dev/video1", O_RDWR );
memset ( &vid_format, 0, sizeof(vid_format) );
vid_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
vid_format.fmt.pix.width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
vid_format.fmt.pix.height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
vid_format.fmt.pix.pixelformat = { 'M', 'J', 'P', 'G' };
vid_format.fmt.pix.sizeimage = framesize;
vid_format.fmt.pix.field = V4L2_FIELD_NONE;
vid_format.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
ioctl ( fd, VIDIOC_S_FMT, &vid_format );
buffer = (__u8*) malloc ( sizeof(__u8) *framesize );
memset ( buffer, 0, framesize );
for(;;) {
cv::Mat frame;
cap >> frame;
write ( fd, &frame.data, framesize );
}
}
如果有人能给我一个提示,我需要如何转换 wecam 数据以使其被 VLC 接受,那就太好了。
【问题讨论】:
-
我对V4L2一点也不熟悉,但是当您将像素格式设置为MJPEG时,您应该编写MJPEG编码帧,而不是原始BGR像素数据?
-
确实是个好问题。我对所有这些(相当混乱的)像素格式、色彩空间等东西也不是很熟悉。我试图深入一点,但这个杀了我:wiki.videolan.org/YUV
标签: linux opencv video v4l2loopback