当前位置:首页>Linux>Linux下QV4L2无法选择UVC帧格式的问题分享

Linux下QV4L2无法选择UVC帧格式的问题分享

  • 2026-09-27 01:34:13
Linux下QV4L2无法选择UVC帧格式的问题分享

一. 前言

本文分享Linux下QV4L2无法选择UVC帧格式的问题,问题本身不复杂,主要分享调试分析方法和过程。 问题是在Linux下使用QV4L2无法选择对应的帧格式:选择不同的格式,总是变为默认的格式(这里默认格式是MJPG)

二. 前置知识

基于WSL修改驱动增加打印信息,替换内核进行调试。

见WSL中支持UVC参考公众号文章

WSL2中配置支持UVC

三. 分析过程

3.1 尝试查看UVC驱动层LOG

先使能UVC的dbg信息(必须切换到su再修改,直接sudo修改会提示权限问题)

sudo su

echo 0x01FFF > /sys/module/uvcvideo/parameters/trace

查看设置值

cat /sys/module/uvcvideo/parameters/trace

然后清除dmesg

sudo dmesg -c

确认清除

dmesg

然后运行qv4l2后,dmesg查看log

看到打印信息如下

root@qinyunti:/home/qinyunti# dmesg[ 1361.655464] usb 1-1: uvc_v4l2_open[ 1361.724433] usb 1-1: Resuming interface 0[ 1361.724442] usb 1-1: Resuming interface 1[ 1361.724446] usb 1-1: Resuming interface 2[ 1361.724449] usb 1-1: Resuming interface 3[ 1361.876293] usb 1-1: uvc_v4l2_release[ 1361.876383] usb 1-1: uvc_v4l2_open[ 1361.877772] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1361.877778] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1361.882461] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1361.882470] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1361.886490] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1361.886501] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1361.890596] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1361.890605] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1361.894375] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1361.894384] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1361.898814] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1361.898824] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1361.902613] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1361.902623] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1361.906474] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1361.906482] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1361.910249] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1361.910257] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1361.916444] usb 1-1: Control 0x00980900 not found[ 1361.923695] usb 1-1: uvc_v4l2_poll

选择NV12格式,查看打印信息如下

[ 1462.642038] usb 1-1: uvc_v4l2_poll[ 1462.643073] usb 1-1: Trying format 0x3231564e (NV12): 1280x720[ 1462.643081] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.648836] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.648848] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.654511] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.654522] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.660700] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.660709] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.666833] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.666842] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.672974] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.672984] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.677502] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.677513] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.681863] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.681872] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.687086] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.687162] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.691518] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.691526] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.695737] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.695745] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.699750] usb 1-1: Trying format 0x47504a4d (MJPG): 1280x720[ 1462.699758] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)[ 1462.705050] usb 1-1: uvc_v4l2_poll[ 1462.707470] usb 1-1: uvc_v4l2_poll[ 1462.707485] usb 1-1: uvc_v4l2_poll[ 1462.889325] usb 1-1: uvc_v4l2_poll

可以看到先是开始try NV12格式的但是最后又选择了默认的mjpeg

3.2 分析代码

那么我们根据前面的打印信息找到

[ 1462.643073] usb 1-1: Trying format 0x3231564e (NV12): 1280x720

的位置

搜索Trying format

位于

drivers/media/usb/uvc/uvc_v4l2.c的

staticintuvc_v4l2_try_format(struct uvc_streaming *stream,    struct v4l2_format *fmt, struct uvc_streaming_control *probe,    const struct uvc_format **uvc_format,    const struct uvc_frame **uvc_frame){    const struct uvc_format *format = NULL;    const struct uvc_frame *frame = NULL;    u16 rw, rh;    unsigned int d, maxd;    unsigned int i;    u32 interval;    int ret = 0;    u8 *fcc;    if (fmt->type != stream->type)        return -EINVAL;    fcc = (u8 *)&fmt->fmt.pix.pixelformat;    uvc_dbg(stream->dev, FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u\n",        fmt->fmt.pix.pixelformat,        fcc[0], fcc[1], fcc[2], fcc[3],        fmt->fmt.pix.width, fmt->fmt.pix.height);

3.3 定位大概位置

猜测这个函数选择NV12时返回失败了,那么我们手动加一些打印信息

我们看到打印

[ 1462.643073] usb 1-1: Trying format 0x3231564e (NV12): 1280x720

[ 1462.643081] usb 1-1: Using default frame interval 40000.0 us (25.0 fps)

所以至少跑到了如下位置以后

所以在后面加打印

但是如下位置后面没有打印,所以猜测是不是ret = uvc_probe_video(stream, probe);

返回了失败

增加打印确认

   /* Probe the device. */    ret = uvc_probe_video(stream, probe);    mutex_unlock(&stream->mutex);    if (ret < 0){        uvc_dbg(stream->dev, FORMAT,"uvc_probe_video err ret %d\r\n", ret);        return ret;    }

查看实际这里也没有打印,说明上述猜测错误,即

uvc_v4l2_try_format是成功的

没有报错。

3.4 增加打印确认状态

上述地方没有报错,那么就继续增加一些打印信息,打印一些状态

首先看代码,这里有说明

没有probe到需要的格式,也不会返回错误,而是最终设备响应啥格式就是啥格式

   /*     * After the probe, update fmt with the values returned from     * negotiation with the device. Some devices return invalid bFormatIndex     * and bFrameIndex values, in which case we can only assume they have     * accepted the requested format as-is.     */    for (i = 0; i < stream->nformats; ++i) {        if (probe->bFormatIndex == stream->formats[i].index) {            format = &stream->formats[i];            break;        }    }

所以我们就来看这里实际选择的是什么格式

在uvc_v4l2_try_format中如下位置最后增加打印

 uvc_dbg(stream->dev, FORMAT,"format %d frame %d\r\n", probe->bFormatIndex,probe->bFrameIndex);

看到选择不同格式都是打印信息如下,即设备返回的格式总是不变的。

即设备对probe的响应错误。

四. 原因

既然上述确认是设备返回不对,就看设备的代码

原来设备端代码中对于SET处理笔误写错了,SET信息没有更新,所以一直返回默认格式,所以这里qv4l2获取的格式就一直是固定的,无法修改。

SET时,SET的信息存储到了s_probe_cur_tmp

应该是要存到s_probe_cur的

因为GET时是从s_probe_cur获取值返回给HOST的

所以代码中SET CUR之后没有更新记录,之后GET CUR的格式索引不对,返回不是SET的值而一直是默认值。

修改之后,此时就可以看到按照指定更新了

这里顺便提一下,windows下上述设备返回固定值时,potplayer中GUI显示的还是选择的指定格式的,哪怕设备返回的是固定的格式,所以windows的处理还是有一点差异,windows下一般来说能更多的容忍一些小错误,看起来就是兼容性会更好。

五. 总结

问题本身很简单就是一个笔误导致的问题,主要分享遇到类似问题如何去分析调试。也进一步说明基于WSL进行linux开发调试真的很方便。

最新文章

随机文章