ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

esp-iot-solution USB Stream 组件实战:基于 ESP32-S2/S3 的 UVC + UAC 主机多媒体流驱动

esp-iot-solution USB Stream 组件实战:基于 ESP32-S2/S3 的 UVC + UAC 主机多媒体流驱动 esp-iot-solution USB Stream 组件实战基于 ESP32-S2/S3 的 UVC UAC 主机多媒体流驱动【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution导读本文围绕 esp-iot-solution 仓库中的usb_stream组件关联文档展开系统讲解如何在 ESP32-S2/ESP32-S3 上以 USB 主机Host模式驱动 UVC 摄像头与 UAC 音频设备实现「1 路摄像头 1 路麦克风 1 路播放器」的多媒体数据流读取、写入与控制。读完本文你将掌握组件能力边界、设备选型约束、uvc_config_t/uac_config_t完整配置方法、核心 API 调用时序以及 ESP32-S2 ECO0 芯片 USB 污染 SPI 的已知 Bug 与软件规避方案。一、组件定位与核心能力usb_stream是 esp-iot-solution 提供的一个基于 ESP32-S2/ESP32-S3 USB-OTG 外设的UVC UAC 复合主机驱动源码位于 components/usb/usb_stream。它不再需要用户直接与usb_host底层句柄打交道而是把「设备枚举、描述符解析、协议协商、URB 调度、帧重组」等繁琐工作封装成一组简单的流式 API用户拿到的是「视频帧回调 音频帧回调 控制接口」。官方文档明确列出的特性见 usb_stream.rst通过UVC Stream接口获取视频流同时支持**批量Bulk与同步Isochronous**两种传输模式通过UAC Stream接口获取麦克风数据流、发送播放器数据流通过UAC Control接口控制麦克风/播放器的音量、静音等特性自动解析设备配置描述符用户无需手工指定接口号、端点地址支持对数据流的暂停Suspend与恢复Resume。从源码结构看整个组件由以下文件构成include/usb_stream.h对外 API 与配置结构体定义include/libuvc_def.hUVC 协议相关常量定义usb_stream.c核心实现约 4000 余行包含 USB 主机任务、流处理任务、样本处理任务usb_host_helpers.c 与 descriptor.c描述符解析与 USB 主机辅助逻辑Kconfig全部运行时可调参数任务优先级、URB 数量、补偿策略等。组件在内部创建了三个任务见 usb_stream.cusb_procUSB I/O 请求与控制传输处理建议高优先级、不可阻塞、usb_stream_proc音视频载荷轮询与 ringbuffer 收发、sample_procUVC 帧重组并在新帧就绪后调用用户回调。二、硬件与设备选型指南2.1 开发板要求可以使用任何带有 USB 接口的 ESP32-S2/ESP32-S3 开发板关键约束该 USB 接口必须能够向外供电USB 摄像头/耳机通常需要 5 V 供电。例如在usb_camera_mic_spk示例的 app_usb_host.c 中针对 ESP32-S3 开发板会通过 GPIO 使能 VBUS 电源路径GPIO_NUM_18使能 GPIO_NUM_17/12/13控制电源这正是因为 USB 口需要给外设供电。2.2 UVC 摄像头要求要求说明兼容 USB 1.1 全速Fullspeed模式必须满足自带 MJPEG 压缩组件默认以 MJPEG 格式协商视频流传输模式支持同步或批量批量带宽上限更高同步传输 MPS需支持将接口 MPSMax Packet Size设为 512对应USB_EP_ISOC_IN_MAX_MPS见 usb_stream.c同步模式带宽预算图像数据流 USB 传输总带宽应小于 4 Mbps500 KB/s批量模式带宽预算图像数据流 USB 传输总带宽应小于 8.8 Mbps1100 KB/s其它特殊相机要求请参考示例程序 README例如 usb_camera_mic_spk/README.md。2.3 UAC 音频设备要求音频功能必须兼容UAC 1.0协议用户需要通过uac_streaming_config函数手动指定 spk/mic 的采样率与位宽参数。2.4 UVC UAC 复合使用要求UVC 与 UAC 可以单独启用例如仅配置 UAC 来驱动一个 USB 耳机或仅配置 UVC 来驱动一个 USB 摄像头若要同时启用 UVC UAC当前驱动仅支持带摄像头和音频接口的复合设备Composite Device不支持同时连接两个独立设备。三、添加组件到工程usb_stream已发布到 ESP 组件注册中心idf_component.yml声明见 components/usb/usb_stream/idf_component.yml。使用组件管理器添加依赖见 README_CN.mdidf.py add-dependency espressif/usb_stream*CMake 执行期间该组件会被自动下载到工程目录。也可以直接从本仓库的 examples/usb/host 目录获取示例源码进行参考。重要提示IDF 版本相关对于ESP-IDF V5.3.3 及以上版本若使能 UVC请在Component config → USB-OTG → Hardware FIFO size biasing中使能Bias IN见 README_CN.md。这是因为 DWC2 控制器在使能 UVC 大批量 IN 传输时需要更大的 RX FIFO 余量否则可能出现端点分配失败或帧丢失。四、API 参考与配置参数详解4.1 配置结构体uvc_config_t 与 uac_config_t官方文档给出了完整的配置示例这里逐字段展开说明完整字段定义见 include/usb_stream.h 与 include/usb_stream.huvc_config_t uvc_config { .frame_width 320, // mjpeg 宽度像素例如 320也可用 FRAME_RESOLUTION_ANY 表示任意分辨率 .frame_height 240, // mjpeg 高度像素例如 240 .frame_interval FPS2INTERVAL(15), // 帧间隔100µs 单位例如 15fps .xfer_buffer_size 32 * 1024, // 单帧图像大小需根据实际测试确定320*240 一般小于 35KB .xfer_buffer_a pointer_buffer_a, // 内部传输缓冲 A .xfer_buffer_b pointer_buffer_b, // 内部传输缓冲 B双缓冲 .frame_buffer_size 32 * 1024, // 单帧图像大小需根据实际测试确定 .frame_buffer pointer_frame_buffer, // 图像帧缓冲 .frame_cb camera_frame_cb, // 摄像头回调可在其中阻塞 .frame_cb_arg NULL, // 摄像头回调参数 }; uac_config_t uac_config { .mic_bit_resolution 16, // 麦克风分辨率bit .mic_samples_frequence 16000, // 麦克风采样率Hz .spk_bit_resolution 16, // 播放器分辨率bit .spk_samples_frequence 16000, // 播放器采样率Hz .spk_buf_size 16000, // 播放器发送缓冲大小应为 spk_ep_mps 的整数倍 .mic_buf_size 0, // 麦克风接收缓冲大小不使用填 0否则应为 mic_min_bytes 的整数倍 .mic_cb mic_frame_cb, // 麦克风回调绝不能阻塞 .mic_cb_arg NULL, // 麦克风回调参数 };字段要点补充来自头文件注释FPS2INTERVAL(fps)宏定义为(10000000ul / fps)即 10⁷100ns 单位除以 fps。头文件还预定义了常用帧间隔宏FRAME_INTERVAL_FPS_5/10/15/20/30见 include/usb_stream.hframe_interval的合法范围在实现中被约束为 16666660fps到 20000005fps即 usb_stream.c 中的FRAME_MIN_INTERVAL/FRAME_MAX_INTERVAL传输缓冲为双缓冲设计xfer_buffer_a/bxfer_buffer_size必须大于单帧大小音频侧支持「任意值」通配UAC_FREQUENCY_ANY任意采样率、UAC_BITS_ANY任意位宽、UAC_CH_ANY任意声道数视频侧有FRAME_RESOLUTION_ANY任意分辨率适合对描述符做宽松匹配的场景见 include/usb_stream.h。可选字段与「快速启动」模式uvc_config_t中标注 (optional) 的字段xfer_type、format_index、frame_index、interface、interface_alt、ep_addr、ep_mps、flags以及uac_config_t中的mic_interface、mic_ep_addr、mic_ep_mps、spk_interface、spk_ep_addr、spk_ep_mps、ac_interface、mic_fu_id、spk_fu_id等在正常模式下可以全部填 0驱动会自动从设备描述符中找到正确值若开启 Kconfig 中的USB_STREAM_QUICK_START则需要全部手工指定以跳过「获取并解析描述符」步骤、加速启动见 include/usb_stream.h 与 Kconfig。4.2 流类型与控制类型typedef enum { STREAM_UVC 0, /*! usb video stream */ STREAM_UAC_SPK, /*! usb audio speaker stream */ STREAM_UAC_MIC, /*! usb audio microphone stream */ STREAM_MAX, /*! max stream id */ } usb_stream_t; typedef enum { CTRL_NONE 0, /*! None */ CTRL_SUSPEND, /*! 挂起流ctrl_data 传 NULL */ CTRL_RESUME, /*! 恢复流ctrl_data 传 NULL */ CTRL_UAC_MUTE, /*! 静音控制ctrl_data 传 (false/true) */ CTRL_UAC_VOLUME, /*! 音量控制ctrl_data 传 (0~100) */ CTRL_MAX, } stream_ctrl_t;两个枚举定义于 include/usb_stream.h。其中CTRL_UAC_MUTE/CTRL_UAC_VOLUME能否生效取决于设备是否支持 UAC Feature Unit特性单元——实现中通过USB_CTRL_UAC_SET_FU_MUTE/USB_CTRL_UAC_SET_FU_VOLUME构造标准 UAC 类请求见 usb_stream.c音量范围映射为 0~100UAC_SPK_VOLUME_MAX 0xfff0、UAC_SPK_VOLUME_MIN 0xe3a0见 usb_stream.c。4.3 核心 API 使用流程官方文档给出的调用顺序如下结合头文件注释补充各函数返回码配置 UVCuvc_streaming_config(uvc_config)—— 若设备同时支持音频再用uac_streaming_config(uac_config)配置 UAC。两者在流未运行时调用返回ESP_ERR_INVALID_STATE流正在运行需先 stop或ESP_ERR_INVALID_ARG参数非法启动流usb_streaming_start()—— 驱动创建内部任务开始响应设备连接并进行协议协商UVC 侧会执行 Probe/Commit 控制传输见 usb_stream.c 中的USB_CTRL_UVC_PROBE_SET_REQ/USB_CTRL_UVC_COMMIT_REQ宏设备匹配主机根据用户参数匹配已连接设备的描述符若设备无法满足配置要求驱动会以警告提示不会硬性失败接收数据若设备满足配置主机持续接收 IN 数据流UVC 视频与 UAC 麦克风并在新帧就绪后调用用户回调收到新的 MJPEG 图像后触发UVC 回调用户可在回调中阻塞它在独立任务上下文中工作收到mic_min_bytes字节后触发mic 回调但此回调绝不能以任何方式阻塞否则影响下一帧接收如需阻塞操作改用uac_mic_streaming_read轮询方式发送扬声器数据调用uac_spk_streaming_write(data, data_bytes, timeout_ms)将数据写入内部 ringbuffer主机在 USB 空闲时取出并发送 OUT 数据。返回ESP_ERR_TIMEOUT表示 spk ringbuf 已满、ESP_ERR_NOT_FOUND表示未找到 spk 接口暂停/恢复usb_streaming_control(stream, ctrl_type, ctrl_value)控制流挂起/恢复若 UAC 支持特性单元可分别控制麦克风和播放器的音量和静音返回ESP_ERR_NOT_SUPPORTED表示当前设备不支持该控制类型停止流usb_streaming_stop()—— 内部任务被删除USB 资源完全释放返回ESP_ERR_TIMEOUT表示等待停止超时。4.4 辅助 APIusb_streaming_connect_wait(timeout_ms)阻塞等待 USB 设备连接超时返回ESP_ERR_TIMEOUTusb_streaming_state_register(cb, user_ptr)注册连接状态回调STREAM_CONNECTED/STREAM_DISCONNECTED仅支持注册一个回调后注册的会覆盖先前的且必须在usb_streaming_start之前注册uac_mic_streaming_read(buf, buf_size, data_bytes, timeout_ms)从内部 mic 缓冲轮询读取数据实际读取长度通过data_bytes返回uvc_frame_size_list_get/uac_frame_size_list_get获取当前已连接设备的帧尺寸/音频参数列表可传 NULL 仅获取列表长度uvc_frame_size_reset/uac_frame_size_reset在流处于挂起状态时重置期望的分辨率/帧间隔或声道数/位宽/采样率新配置在 resume 后生效。uvc_frame_size_reset支持 width 和 height 同时传 0 表示帧尺寸不变、frame_interval传 0 表示不变见 include/usb_stream.h。五、Kconfig 运行时调优组件提供大量 Kconfig 选项用于适配不同设备与性能场景完整见 Kconfig常用项整理如下配置项默认值说明CTRL_TRANSFER_DATA_MAX_BYTES1024范围 64~2048控制传输最大数据长度USB_STREAM_QUICK_STARTn开启后跳过描述符获取/解析需在结构体中手工指定全部可选参数USB_PROC_TASK_PRIORITY/CORE/STACK_SIZE5 / 自动 / 3072USB 处理任务优先级、核绑定、栈大小USB_CTRL_XFER_TIMEOUT_MS1000USB 控制传输超时USB_WAITING_AFTER_CONN_MS50设备连接后的枚举等待时间USB_ENUM_FAILED_RETRY/COUNT/DELAY_MSy / 10 / 200枚举失败自动重试策略SAMPLE_PROC_TASK_PRIORITY2UVC 样本处理任务优先级UVC_PRINT_DESC/UVC_PRINT_DESC_VERBOSEy / n打印描述符信息详细模式UVC_CHECK_HEADER_EOF/UVC_DROP_NO_EOF_FRAMEy / n校验载荷头 EOF 位 / 丢弃无 EOF 的帧UVC_DROP_OVERFLOW_FRAMEy丢弃溢出帧NUM_BULK_STREAM_URBS/NUM_BULK_BYTES_PER_URB2 / 2048批量传输 URB 数量与每 URB 分段大小NUM_ISOC_UVC_URBS/NUM_PACKETS_PER_URB3 / 4同步传输 URB 数量与每 URB 包数UAC_MIC_CB_MIN_MS_DEFAULT16范围 1~32mic 回调最小间隔msUAC_SPK_ST_MAX_MS_DEFAULT16范围 1~32spk 最大发送尺寸msUAC_MIC_PACKET_COMPENSATIONn麦克风丢包时补数据UAC_SPK_PACKET_COMPENSATION含CONTINUOUS/TIMEOUT_MS/SIZE_MSy / y / 80 / 10播放器缓冲空时补零避免 USB 端点停摆其中UAC_MIC_PACKET_COMPENSATION与UAC_SPK_PACKET_COMPENSATION对应源码中的CONFIG_UAC_*_PACKET_COMPENSATION宏见 usb_stream.c麦克风丢包时填充数据、扬声器缓冲为空时补零并持续按超时间隔补偿用于保证等时传输不被中断。六、源码级实现原理6.1 设备枚举状态机组件实现了完整的 USB 设备枚举状态机_device_state_t与_enum_stage_t见 usb_stream.c枚举阶段依次为复位设备 → 获取短设备描述符8 字节取bMaxPacketSize0→ SET_ADDRESS → 获取完整设备描述符 → 获取短配置描述符取wTotalLength→ 获取完整配置描述符 → SET_CONFIGURATION。每个阶段都有独立的CHECK阶段校验结果失败时按USB_ENUM_FAILED_RETRY_*策略重试。6.2 内部事件与动作机制实现采用「事件位 动作位」的调度模型事件位USB_HOST_INIT_DONE、USB_UVC_STREAM_RUNNING、UAC_SPK_STREAM_RUNNING、UAC_MIC_STREAM_RUNNING等记录各流运行状态动作位ACTION_DEVICE_CONNECT、ACTION_DEVICE_ENUM、ACTION_PIPE_XFER_DONE、ACTION_PORT_RECOVER等驱动 USB 主机事件循环处理连接/断开/传输完成/错误恢复见 usb_stream.c。这也是usb_streaming_control能实现挂起/恢复的基础——挂起时不再向端点提交 URB恢复时重新发起。6.3 回调语义与任务上下文UVC 回调运行于sample_proc任务帧重组任务可以安全地阻塞例如把帧投递给解码任务测试用例中即在该回调中打印帧格式、序号、宽高与数据长度见 test_apps/main/test_usb_stream.cmic 回调运行于流处理任务禁止阻塞否则会拖慢后续帧接收需要阻塞消费时使用uac_mic_streaming_read轮询状态回调usb_streaming_state_register用于感知设备热插拔测试用例中用它来唤醒等待连接的任务见 test_apps/main/test_usb_stream.c。七、已知 Bug 与规避方案ESP32-S2 ECO0现象在最早版本的ESP32-S2 ECO0芯片上SPI 屏幕与 USB 同时启用时USB 可能污染 SPI 数据导致屏幕抖动。ESP32-S2 新版本≥ECO1和 ESP32-S3 均不存在该 Bug。官方文档给出软件规避方案核心思路是在 SPI 发送新事务前等待 TX FIFO 计数从 0 变为非 0确保 DMA 已真正把数据送入 FIFO从而避开 USB 对 SPI 数据的干扰窗口。第一步在components/hal/esp32s2/include/hal/spi_ll.h添加读取 FIFO 计数的接口static inline uint32_t spi_ll_tx_get_fifo_cnt(spi_dev_t *hw) { return hw-dma_out_status.out_fifo_cnt; }第二步在spi_new_trans函数中该函数在 ISR 或任务中发送新事务负责设置寄存器与 DMA 链表在启动传输前加入等待检查static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_t *trans_buf) { //................... spi_hal_setup_trans(hal, hal_dev, hal_trans); spi_hal_prepare_data(hal, hal_dev, hal_trans); //Call pre-transmission callback, if any if (dev-cfg.pre_cb) dev-cfg.pre_cb(trans); #if 1 //USB Bug workaround while (trans-length spi_ll_tx_get_fifo_cnt(SPI_LL_GET_HW(host-id)) 0) { __asm__ __volatile__(nop); __asm__ __volatile__(nop); __asm__ __volatile__(nop); } #endif //Kick off transfer spi_hal_user_start(hal); }该补丁仅供在 ESP32-S2 ECO0 芯片上遇到此问题时参考新版芯片无需应用。八、示例程序官方文档列出三个示例均位于 examples/usb/hostusb_camera_mic_spkREADME基于浏览器的 USB AV 综合演示支持 UAC 麦克风/扬声器检测、静音/音量/格式选择、麦克风实时回放含电平表、扬声器测试音与本地音频文件播放以及 UVC 摄像头检测、MJPEG 分辨率选择与实时预览示例通过 SoftAPSSIDUSB-AV-DEMO无密码访问http://192.168.4.1提供 Web 控制台并带 Captive Portal 自动跳转usb_camera_lcd_display源码见 components/usb/usb_stream/examples/usb_stream_lcd_displayUSB 摄像头本地刷屏将 MJPEG 流解码后直接显示在 LCD 上usb_audio_playerUSB 音频播放器。实战排障提示usb_camera_mic_spk的 README 记录了典型问题——当日志出现EP MPS (288) exceeds supported limit (264)与USBH: EP Alloc error: ESP_ERR_NOT_SUPPORTED时说明所选音频端点 MPS 超过了当前 DWC FIFO 配置上限。示例通过自定义fifo_settings_customnptx_fifo_lines56, ptx_fifo_lines72, rx_fifo_lines72扩大周期 TX/RX FIFO见 app_usb_host.c若仍不够需要为设备与流方向调整该配置或在 Web 控制台选择更低带宽的 UAC 格式。九、测试与验证组件自带测试工程 components/usb/usb_stream/test_apps包含 Unity 测试用例test_usb_stream.c、wave_1ch_16bits.c测试音频数据以及 CI 配置pytest_usb_stream.py、sdkconfig.ci.160mhz/240mhz/quick。测试覆盖内存泄漏阈值检查TEST_MEMORY_LEAK_THRESHOLD、DMA 缓冲分配MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT以及设备热插拔状态回调等场景可作为接入组件后功能验证的参考模板。结语usb_stream将 ESP32-S2/S3 的 UVC/UAC 主机协议栈封装为面向应用的流式 API屏蔽了描述符解析与 URB 调度的复杂度是构建 USB 摄像头图传、USB 音频采集/播放、摄像头麦克风扬声器复合应用的高效起点。接入时请务必核对三条硬约束摄像头需为全速 MJPEG 设备且注意传输模式带宽预算、音频设备需兼容 UAC 1.0、复合设备场景需单设备同时含摄像头与音频接口同时留意 IDF 版本相关的Bias INFIFO 配置与 ESP32-S2 ECO0 的 SPI/USB 干扰规避补丁。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表