【发布时间】:2020-04-09 07:59:34
【问题描述】:
我有一个捕获 video4Linux 视频流的科学应用程序。至关重要的是,我们捕捉每一帧并且没有人迷路。不幸的是,到处都缺少框架,我不知道为什么。
为了检测丢帧,我在读取一帧后直接将 v4l2_buffer 的序列号与我自己的计数器进行比较:
void detectDroppedFrame(v4l2_buffer* buffer) {
_frameCounter++;
auto isLastFrame = buffer->sequence == 0 && _frameCounter > 1;
if (!isLastFrame && _frameCounter != buffer->sequence+1)
{
std::cout << "\n####### WARNING! Missing frame detected!" << std::endl;
_frameCounter = buffer->sequence+1; // re-sync our counter with correct frame number from driver.
}
}
我的运行 1-file 示例 gist 可以在 github 找到(基于官方 V4L2 捕获示例):https://gist.github.com/SebastianMartens/7d63f8300a0bcf0c7072a674b3ea4817
在笔记本硬件(uvcvideo 驱动程序)上使用 Ubuntu 18.04 虚拟机上的网络摄像头以及在本机运行 ubuntu 18.04 的嵌入式硬件上使用 CSI 摄像头进行测试。帧没有被处理并且缓冲区似乎被抓取得足够快(使用 VIDIOC_QUERYBUF 检查的缓冲区状态显示所有缓冲区都在驱动程序的传入队列中,并且未设置 V4L2_BUF_FLAG_DONE 标志)。我使用 MMAP 和 UserPtr 方法丢失了帧。而且它似乎与像素格式、图像大小和帧速率无关!
在我看来,如果相机/v4l2 驱动程序无法足够快地填充可用缓冲区,而且使用 VIDIOC_S_PRIORITY 命令增加文件描述符优先级也无济于事(仍然可能是线程调度问题?)。
=> V4L2 不转发帧(不将它们放入其传出队列)的可能原因是什么? => 我检测丢失帧的方法是否正确?是否有其他选择或工具?
【问题讨论】:
-
嗨,我认为您在第 382 行有一个错误。使用 MMAP 时,缓冲区由驱动程序分配,用户空间应使用 mmap 将内存映射到他的内存空间。在您的代码中,缓冲区分配在用户空间而不是 mmap 中。我认为您最好使用 v4l2 开发人员编写的 v4l-utils 包来测试相机
-
谢谢。但据我了解,ln382 中的“缓冲区”仅保存缓冲区的地址和长度,分配和 mmap 发生在下方(ln 403)。您知道如何利用 v4l2-utils(或任何其他工具)来测试丢失帧吗?
-
对,我的错。在
v4l-utils中,您可以使用 --verbose 选项进行流式传输,然后它会显示每个缓冲区的序列,或者您可以修补源代码并添加检查 -
问题在 V4l2 中重现:
v4l2-ctl --stream-mmap --stream-count=1000 --verbose 2>&1 >/dev/null | grep Sequence显示序列号列表。最后的计数将告诉您丢失了多少帧。