我想通过 OpenCV 将视频叠加到传入的网络摄像头流上。作为第一步,我尝试将来自网络摄像头的传入视频流式传输到(v4l2loopback)/dev/video0
的虚拟视频设备。/dev/video1
不幸的是,我无法将网络摄像头流转发到 v4l2loopback 设备。
我找到了这个线程:如何写入/管道到由 V4L2loopback 模块创建的虚拟网络摄像头?但那里的链接并没有真正帮助我。
从网络摄像头获取和观看视频流与 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 接受,那就太好了。