使用 V4l2 进行视频捕获时出现丢帧/丢失帧

Seb*_*ian 5 c++ v4l2

我有一个科学应用程序,可以捕获 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.
        }
}
Run Code Online (Sandbox Code Playgroud)

我的运行 1 文件示例要点可以在 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不转发帧(不将它们放入其输出队列)的可能原因是什么?=> 我检测丢失帧的方法是否正确?还有其他选择或工具吗?

dgo*_*bbi 2

我在使用 bttv 驱动程序时遇到了类似的问题。所有以全分辨率捕获的尝试都会导致丢帧(通常是大约 10% 的帧,通常是突发)。以一半分辨率拍摄效果很好。

我找到的解决方案虽然远非理想,但却是向 Linux 调度程序施加负载。这是一个使用“tvtime”程序进行捕获的示例:

#! /bin/bash
# apply a load in the background
while true; do /bin/true; done &> /dev/null &
# do the video capture
/usr/bin/tvtime "$@"
# kill the loop running in the background
pkill -P $$
Run Code Online (Sandbox Code Playgroud)

这将创建一个在后台重复运行 /bin/true 的循环。几乎任何可执行文件都可以(我最初使用/bin/date)。该循环将产生较重的负载,但对于多核系统,仍然有足够的空间来执行其他任务。

这显然不是一个理想的解决方案,但就其价值而言,它允许我捕获全分辨率视频而不会丢帧。我不想在驱动程序/内核代码中寻找更好的解决方案。

仅供参考,这是我的系统的详细信息:

OS:  Ubuntu 20.04, kernel 5.4.0-42
MB:  Gigabyte AB350M-D3H
CPU: AMD Ryzen 5 2400G
GPU: AMD Raven Ridge

Driver name      : bttv
Card type        : BT878 video (Hauppauge (bt878))
Bus info         : PCI:0000:06:00.0
Driver version   : 5.4.44
Capabilities     : 0x85250015
Run Code Online (Sandbox Code Playgroud)