
简介这份补丁面向MTK平台Android系统开发与Camera HAL调试人员解决USB摄像头无法像MIPI摄像头一样被原生API直接调用的问题。基于MT8163实现无需libuvc支持Google相机可直接打开USB摄像头应用层可按常规Camera流程处理其他平台可参考移植。资源包共155个文件约3.61MB以cpp与h源码为主辅以mk编译脚本、zbak备份文件、java与rc配置及说明文档覆盖Camera参数管理、HAL层、单拍与队列线程等模块便于对照修改与集成。已有547人学习下载。借助补丁源码与前后对比文件开发者可快速理解USB摄像头接入Android原生框架的改造点掌握参数配置、线程调度与HAL适配思路降低移植与调试成本适合具备一定Android Camera开发基础的中高级工程师学习参考。1. MTK 平台 USB 摄像头原生 API 补丁从 Camera2 打不通到 UVC 出图MTK 平台接 USB 摄像头这件事坑不在「能不能识别」而在「Android 原生 Camera2 API 能不能直接打开它」。很多做平板、会议一体机、自助终端的兄弟都遇到过UVC 摄像头插上后/dev/video0有了系统相机 App 也能预览但自己写的CameraManager.openCamera()一调就抛CAMERA_DISCONNECTED或者干脆找不到这个 ID。原因通常不是硬件而是 MTK 的 Camera HAL 默认只把 MIPI/DVP 这类内置 sensor 注册进 frameworkUSB 摄像头走的是另一条路。这篇就把「MTK 平台支持 Android 原生 API 打开 USB 摄像头补丁」拆开讲清楚补丁改的是哪几层、参数怎么配、编译怎么过、出图后怎么验证适合正在 MTK 方案上做多摄扩展的驱动和应用工程师。2. 先搞清楚 MTK 相机链路里 USB 摄像头卡在哪一层2.1 从 App 到 sensor 的四段链路USB 断在第二段Android 相机栈从上到下大致是四段App 调 Camera2 API → CameraService 管理设备 → Camera Provider/HAL 提供实现 → kernel driver 出流。MTK 平台上前两段是 AOSP 标准逻辑第三段是 MTK 自己的mtkcam体系第四段对 USB 摄像头来说是标准的uvcvideo。问题就出在第三段。MTK 的 HAL 在初始化时会去读一份 sensor 列表常见是camera_custom_sensorlist.cpp或sensor_list.cpp这类文件只有列在里面的 sensor 才会被枚举成 framework 可见的 camera id。USB 摄像头不在这个列表里所以 CameraService 拿到的设备数永远是内置的那几个getCameraIdList()里根本没有 UVC 的条目。补丁的本质就是让 MTK HAL 在枚举阶段把 UVC 设备也当成一个合法 camera 注册进去并且给它分配一套能跑通的 pipeline。这里要区分两种做法一种是走 MTK 的 external camera 通道另一种是直接改 sensor list 硬塞。前者干净但依赖平台是否已支持 external provider后者粗暴但兼容性好很多量产补丁走的是后者。2.2 判断你的平台该走哪条路三个先决条件动手前先确认三件事不然补丁打了也白打。第一kernel 层 UVC 是否正常。插上摄像头执行ls /dev/video*再用v4l2-ctl --list-formats-ext -d /dev/video0看有没有 MJPEG 或 YUYV 格式。如果这里就没有节点先解决 kernel config 里的CONFIG_USB_VIDEO_CLASS跟 HAL 补丁无关。第二平台是否带 external camera provider。在vendor/mediatek/proprietary/hardware/mtkcam下搜external关键字或者看manifest.xml里有没有android.hardware.camera.provider2.4-external这类实例。有的话优先走 external 路线改动小、升级友好。第三Android 版本决定 HAL 接口形态。Android 10 以后 MTK 普遍用 Camera Provider 2.4/2.5 HIDL/AIDLAndroid 8 以前是 Camera HAL3 直连。接口不一样补丁落点也不一样。下面以最常见的 Android 11/12 MTK 天玑系列为例其他版本按同样思路找对应文件。提示改 HAL 前先把原始文件备份MTK 的相机代码耦合度高改错一个枚举值可能导致内置摄像头一起打不开留好后悔药。3. 补丁落地改 sensor 枚举、配 pipeline、过编译3.1 把 UVC 设备注册进 sensor list 的最小改动先找到平台的 sensor 列表文件。MTK 常见路径是vendor/mediatek/proprietary/custom/platform/hal/imgsensor/src/camera_custom_sensorlist.cpp不同平台目录名有差异用find . -name *sensorlist*定位。核心是往列表里加一个 UVC 条目。下面是一段示意代码字段名要按你平台的实际结构体对齐不要照抄字段// camera_custom_sensorlist.cpp // 在原有 sensor 列表后追加 UVC 条目 SensorInfo gUvcSensorInfo { .name uvc_camera, // 逻辑名framework 不直接看这个 .type SENSOR_TYPE_USB, // 关键标记为 USB 类型触发 UVC 分支 .devNode /dev/video0, // 对应 kernel 出的节点 .maxWidth 1920, // 按摄像头实际能力填填大了会协商失败 .maxHeight 1080, .fmt V4L2_PIX_FMT_MJPEG, // UVC 常用 MJPEG带宽比 YUYV 省 .fps 30, }; // 注册到全局列表注意顺序影响 camera id 分配 void getSensorList(SensorInfo** ppList, uint32_t* pCount) { static SensorInfo* list[] { gMainSensorInfo, // 内置主摄保持原样 gUvcSensorInfo, // 新增 UVC }; *ppList (SensorInfo*)list; *pCount sizeof(list) / sizeof(list[0]); }逻辑说明type字段是整段补丁的开关MTK HAL 靠它决定走 MIPI pipeline 还是 UVC pipeline。devNode必须和 kernel 实际节点一致多摄像头时/dev/video0和/dev/video1要分别对应。fmt选 MJPEG 是因为 UVC 在 USB 2.0 带宽下 YUYV 跑 1080p 基本没戏MJPEG 压缩后才够用。参数说明maxWidth/maxHeight不要贪大填成摄像头不支持的分辨率HAL 协商时会直接失败表现为打开黑屏。fps同理30 是稳妥值60 要看 USB 控制器带宽。3.2 pipeline 配置让 UVC 流能接到 MTK 的 ISP 后处理光注册还不够MTK 的 pipeline 默认假设数据来自 ISPUVC 的数据是已经成帧的需要绕过 ISP 直接送 buffer。这一步改的是 pipeline 配置常见在vendor/mediatek/proprietary/hardware/mtkcam3/pipeline/hwnode/下的 P1Node 或类似节点。思路是给 UVC 类型加一个分支不走 sensor→ISP→P1 的常规路径而是直接把 V4L2 的 buffer 拷进 MTK 的IImageBuffer。示意如下// P1Node 里根据 sensor type 分流 if (sensorType SENSOR_TYPE_USB) { // UVC 路径直接从 v4l2 dequeue 拿帧 struct v4l2_buffer buf; ioctl(fd, VIDIOC_DQBUF, buf); // 把 buf 数据映射到 MTK buffer注意 stride 对齐 memcpy(dstBuffer-getBufVA(0), uvcMmap[buf.index], buf.bytesused); ioctl(fd, VIDIOC_QBUF, buf); } else { // 原有 ISP 路径不动 ... }逻辑说明关键是 stride 对齐。UVC 出来的 MJPEG 解码后是紧凑排列MTK 的 buffer 往往有 16 或 32 字节对齐要求直接 memcpy 会出现画面斜纹或花屏。稳妥做法是按dstBuffer-getBufStridesInBytes(0)逐行拷贝。参数说明VIDIOC_DQBUF/QBUF是 V4L2 的标准出队入队buffer 数量建议申请 4 个以上太少会丢帧。bytesused是这一帧的实际字节数MJPEG 每帧大小不一样不能按固定值拷。3.3 编译与权限两个容易漏的收尾动作改完代码要过编译。MTK 相机模块通常单独编# 在 Android 源码根目录 source build/envsetup.sh lunch your_product-userdebug # 单独编相机 HAL比整编快 mmm vendor/mediatek/proprietary/hardware/mtkcam3/ # 推送到设备验证 adb remount adb push out/target/product/product/vendor/lib64/hw/camera.mt6893.so /vendor/lib64/hw/ adb reboot逻辑说明mmm只编改动模块省时间。推 so 后必须重启因为 Camera Provider 在开机时加载热替换不生效。权限方面UVC 节点默认属主是 rootApp 通过 CameraService 访问没问题但 HAL 直接 open/dev/video0需要确保 SELinux 放行。常见报错是avc: denied { read } for ... video0在device/mediatek/sepolicy/basic/non_plat/file_contexts和对应.te文件里给 camera 域加video_device权限。注意SELinux 用 permissive 能临时验证但量产必须补 policy否则 user 版本直接挂。4. 避坑与排查USB 摄像头补丁最常见的五个翻车点4.1 现象getCameraIdList 里没有 UVC但 /dev/video0 存在原因sensor list 改了但没生效或者type字段没被 HAL 识别。MTK 有些平台对 sensor type 有白名单校验非法值会被静默丢弃。解决加日志确认getSensorList被调用且返回数量对。在 HAL 初始化处打ALOGD看枚举阶段实际拿到几个 sensor。如果数量对但 framework 看不到检查 CameraProvider 的manifest.xml是否限制了 camera id 范围。4.2 现象能打开但预览黑屏log 里全是 dequeue timeout原因pipeline 分流没配对UVC 数据没送进 buffer或者格式协商失败。MJPEG 需要 HAL 侧解码如果平台没接解码器拿到的是压缩数据当原始帧用自然黑屏。解决先用v4l2-ctl --stream-mmap --stream-count10 -d /dev/video0确认 kernel 能出流。再确认 HAL 里 MJPEG 是否走了jpeg decoder没有的话要么改用 YUYV降分辨率要么补解码环节。4.3 现象画面斜纹、颜色错乱原因stride 没对齐或者 pixel format 搞混了。UVC 的 YUYV 和 MTK 期望的 NV12/YV12 排列不同直接拷会错位。解决确认fmt和 buffer 格式一致。YUYV 转 NV12 需要做色彩空间转换不能只 memcpy。MJPEG 解码后通常是 YUV420注意 UV 平面顺序。4.4 现象内置摄像头也打不开了原因改 sensor list 时破坏了原有条目或者 camera id 分配顺序变了App 按固定 id 打开就错位。解决新增条目放在列表末尾不要插在中间。camera id 是按列表顺序分配的插中间会让所有 id 偏移。改完用dumpsys media.camera看 id 映射。4.5 现象user 版本正常userdebug 正常量产签名后失败原因SELinux policy 没进量产配置或者 so 没签进 vendor 分区。解决确认 policy 编进了vendor/etc/selinux用adb shell dmesg | grep avc抓拒绝日志。量产前务必在 user 版本上完整验证一遍。5. 进阶多路 UVC 同时出流与热插拔的验证手法单路跑通后实际项目往往要接两路甚至四路 USB 摄像头。这时候瓶颈从 HAL 转到 USB 带宽和供电。两路 1080p MJPEG 在 USB 2.0 上基本到顶再往上必须上 USB 3.0 控制器且每路要独立分配/dev/videoN。sensor list 里对应加多个条目devNode分别指向不同节点pipeline 侧要保证每路有独立的 buffer 队列不能共用。热插拔是另一个高频需求。UVC 拔掉再插上/dev/video0可能变成/dev/video2写死节点就会失效。稳妥做法是在 HAL 里监听uevent节点变化时重新枚举并更新 sensor list。验证手法上我一般用三段式先v4l2-ctl确认 kernel 层再写个最小 App 只调openCameracreateCaptureSession确认 framework 层最后跑完整业务确认稳定性。这样出问题能快速定位是哪一层。验证阶段命令/手段通过标准kernelv4l2-ctl --list-formats-ext能看到 MJPEG/YUYV 及分辨率HALdumpsys media.cameracamera id 列表含 UVCframework最小 Camera2 Demo能出预览帧业务连续跑 2 小时无掉流、无 timeout最后说个血泪经验MTK 不同芯片平台天玑 700 到 9000的相机代码差异比想象中大同一份补丁换平台经常要重找文件路径。我现在的习惯是每接一个新平台先花半天把 sensor list、pipeline、sepolicy 三个落点摸清楚再动手比上来就改省事得多。这套补丁值不值得做取决于你的产品是否真的需要原生 API 而非厂商私有接口——如果 App 是自研的走私有通道可能更省事如果要用第三方相机应用或标准 Camera2 生态那这个补丁就是绕不过去的。希望帮到你。本文还有配套的精品资源点击获取