为什么 USB 视频在实时 Linux 中会丢帧?

为什么 USB 视频在实时 Linux 中会丢帧?

当四个 USB 摄像头连接到安装了 Realtime Linux 补丁的 Ubuntu 20.04 时,我们遇到了每 60 秒左右丢失一帧的问题。从用户代码ioctl(VIDIOC_DQBUF)调用级别我们看到v4l2_buffer.sequence跳过缓冲区,但没有报告错误。奇怪的是,一台摄像头不会跳过,但三台摄像头会跳过,即使它们都位于不同的 USB 端口上。

查看内核调试信息,我们看到如下信息:

Jan 21 08:48:52 kernel: [ 612.290354] uvcvideo: frame 1955 stats: 0/151/151 packets, 0/0/151 pts (!early initial), 0/151 scr, last pts/stc/sof 0/0/0
Jan 21 08:48:52 kernel: [ 612.291017] uvcvideo: frame 1940 stats: 0/151/151 packets, 0/0/151 pts (!early initial), 0/151 scr, last pts/stc/sof 0/0/0
Jan 21 08:48:52 kernel: [ 612.294264] uvcvideo: frame 1956 stats: 0/9/9 packets, 0/0/9 pts (!early initial), 0/9 scr, last pts/stc/sof 0/0/0
Jan 21 08:48:52 kernel: [ 612.294269] uvcvideo: Marking buffer as bad (error bit set).
Jan 21 08:48:52 kernel: [ 612.294270] uvcvideo: Frame complete (FID bit toggled).
Jan 21 08:48:52 kernel: [ 612.294270] uvcvideo: frame 1957 stats: 0/1/1 packets, 0/0/0 pts (!early !initial), 0/1 scr, last pts/stc/sof 0/1217480818/18547
Jan 21 08:48:52 kernel: [ 612.294272] uvcvideo: Marking buffer as bad (error bit set).
Jan 21 08:48:52 kernel: [ 612.294678] uvcvideo: frame 1958 stats: 0/2/2 packets, 0/0/0 pts (!early !initial), 0/1 scr, last pts/stc/sof 0/1217480818/18547
Jan 21 08:48:52 kernel: [ 612.294682] uvcvideo: Marking buffer as bad (error bit set).
Jan 21 08:48:52 kernel: [ 612.294682] uvcvideo: Frame complete (FID bit toggled).
Jan 21 08:48:52 kernel: [ 612.294683] uvcvideo: frame 1959 stats: 0/1/1 packets, 0/0/0 pts (!early !initial), 0/1 scr, last pts/stc/sof 0/1267616628/19316
Jan 21 08:48:52 kernel: [ 612.294685] uvcvideo: Marking buffer as bad (error bit set).
Jan 21 08:48:52 kernel: [ 612.294686] uvcvideo: Frame complete (EOF found).
Jan 21 08:48:52 kernel: [ 612.294888] uvcvideo: Dropping payload (out of sync).
Jan 21 08:48:52 kernel: [ 612.295094] uvcvideo: Marking buffer as bad (error bit set).
Jan 21 08:48:52 kernel: [ 612.295094] uvcvideo: Dropping payload (out of sync).
Jan 21 08:48:52 kernel: [ 612.295299] uvcvideo: Dropping payload (out of sync).
Jan 21 08:48:52 kernel: [ 612.295509] uvcvideo: Marking buffer as bad (error bit set).
Jan 21 08:48:52 kernel: [ 612.295510] uvcvideo: Dropping payload (out of sync).
Jan 21 08:48:52 kernel: [ 612.295715] uvcvideo: frame 1960 stats: 0/5/5 packets, 2/4/3 pts (!early !initial), 2/3 scr, last pts/stc/sof 1284525428/1284525171/19827

查看源代码,Frame complete (FID bit toggled)意味着 USB 驱动程序尚未发送完整的帧(否则我们会收到一条(EOF found)消息),该消息由显示的日志0/2/2 packets而不是0/151/151.

现在如何进行调试?我很难相信 USB 驱动程序有问题,但是堆栈中是否有一些不完全适合 RTLinux 的组件?

答案1

是否有可能更高优先级的任务或线程正在干扰您的 USB 摄像头/端口?

默认情况下,在 PREEMPT_RT 上(或在主线 linux 上使用线程中断时),所有 IRQ 线程都将以 50 prio 和 SCHED_FIFO 运行。因此,除非您将这些线程/任务设置为更高的优先级,否则它们很可能会被其他事物抢占。

例如,linux proaudio 用户总是将他们的音频接口设置为在系统上具有最高优先级,以避免它被其他任务/线程抢占或中断......您将需要为您的相机和重要任务执行类似的操作。

另一种可能性是,您的一个/一些 USB 端口上有共享中断 - 这也可能导致间歇性掉线。您应该能够通过查看 procfs 中的中断来判断。事实上,您在 3 个摄像头上都遇到了掉线问题,但在一个摄像头上却没有 - 这让我认为有些东西在后台共享/被戳了...

除此之外,您可以使用 ftrace 更好地了解正在发生的情况以及哪些功能导致延迟/可能是罪魁祸首。如果您发现某些东西确实不合适,也许 Latencytop 也可能会给出一些提示。

编辑:

这些“uvcvideo:将缓冲区标记为坏(错误位设置)”消息看起来很可疑。 -- 您可能需要为您的相机设置一些适当的值,如此处所述;

https://stackoverflow.com/questions/17155738/uvcvideo-marking-buffer-as-bad-error-bit-set

如果失败的话,我在这里找到了一个错误报告;https://bugzilla.kernel.org/show_bug.cgi?id=207045有一个链接的补丁应该可以解决这个问题......

它仍然适用于 linux-5.16.2;https://lore.kernel.org/lkml/[电子邮件受保护]/

如果您的硬件有此问题,可能会有所帮助。你永远不知道。

相关内容