【RK平台USB摄像头常见问题解答】

(记录android9以后调试所遇到的常见问题,有错请批评指正)

        UVC全称为USB video(device) class,是微软与另外几家设备厂商联合推出的为usb视频捕获设备定义的协议标准;所以说UVC仅仅是usb规范协议中设备类规范的其中一种,是用作usb接口的视频设备的一个统一的数据交换规范。

        插入USB摄像头会生成对应的video节点,使用如下指令,可以列举出插入的usb设备:

rk3399:/ # grep -H '' /sys/class/video4linux/video*/name
grep -H '' /sys/class/video4linux/video*/name
/sys/class/video4linux/video0/name:rkisp1_mainpath
/sys/class/video4linux/video1/name:rkisp1_selfpath
/sys/class/video4linux/video10/name:YHX5M   //第一个usb摄像头
/sys/class/video4linux/video11/name:YHX5M
/sys/class/video4linux/video12/name:USB 2.0 PC Camera    //第二个usb摄像头
/sys/class/video4linux/video13/name:USB 2.0 PC Camera
.................

        USB摄像头支持的格式有这几种:mjpg格式、yuv格式和h264;usb摄像头能够支持多种不同的分辨率,而且640×480是非常常见的分辨率;可以使用如下指令查询USB摄像头支持的格式,分辨率及帧率。USB camera的相机帧率一般是会根据光照自动调节帧率的;你用手电筒照下,帧率应该就会高了;如果你们需要固定帧率,需要USB camera的厂商控制;

v4l2-ctl -d /dev/videoX --list-formats-ext   (videox 就是对应的usb设备节点)

        新的SDK都有支持usb摄像头的插拔,一般应用在正常退出时会release摄像头,如果没有释放,再去用相机app打开摄像头时,会导致摄像头的video节点后移,出现打开异常现象。

        一般这种插拔问题,会出现在旧版本的,可能是预览中间断开,没有执行正常退出,没有wakeup这个wait_event,所以一直休着;等待超时发现有冗余未释放camera资源,及时通知释放就好了。

常见摄像头打不开问题

        首先配置方面先确保如下几点,具体可以参考文档 USB_UVC_Integrated_Cameras;

(1)以下设置是否都为true?
      /device/rockchip/rk3xxx/BoardConfig.mk
      BOARD_CAMERA_SUPPORT := true
      BOARD_CAMERA_SUPPORT_EXT := true

(2)cat /vendor/etc/vintf/manifest.xml | grep external //确定是否有external信息
     如果没有,则进行添加 /device/rockchip/rk3399/manifest.xml
     <interface>
          <name>ICameraProvider</name>
          <instance>legacy/0</instance>
          <instance>external/0</instance>  //有该配置项吗? 
     </interface>
 (3) 其它型号的usb摄像头是否也打不开? 也有可能是摄像头的问题,所以试试usb camera 插电脑(PC)上,看是否能正常预览出图;可以下载一个usbcamera的apk去看看:adb install usbcamera的apk

        其次,dumpsys media.camera看下是否注册上摄像头;若注册上了,摄像头还打不开,则需要具体logcat进行分析;

将下面三个文件的LOG_NDEBUG宏定义注释去掉
hardware/interfaces/camera/device/3.4/default/ExternalCameraDevice.cpp
hardware/interfaces/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
hardware/interfaces/camera/device/3.4/default/ExternalCameraUtils.cpp
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0

        然后在hardware/interfaces/camera/device/3.4/default$ mm -j12 ;编译生成:camera.device@3.4-external-impl.so 在 vendor/lib目录下,所以修改库后,直接编译替换这个库即可!然后执行指令抓logcat

logcat -c && pkill camera* && pkill provider* && logcat
打开相机抓份logcat

        一般打不开时,很大概率是external_camera_config.xml 文件中没有添加usb camera的相关分辨率以及帧率;在xml中也可以修改旋转角度以及jpeg buffer。USB分辨率,例如预览想要3840×2160,拍照也想要3840×2160,那么需要在xml文件中将MaxJpegBufferSize改大一点,默认是3MB(1MB=1024KB,1KB=1024B, 1B=8bit),可以修改成4MB,5MB.

<Orientation  degree="90"/>
<MaxJpegBufferSize  bytes="3145728"/>  <!-- 3MB (~= 1080p YUV420) --> 
ps:3MB = 3*1024 KB = 3*1024*1024 B = 3145728 B

        查看内核log:表示usb设备已经识别到了;可以找到相关的video节点,用v4l2工具取流,看是否正常;

[ 194.108702] usb 1-1.3: new high-speed USB device number 5 using ehci-platform
[ 194.304772] usb 1-1.3: New USB device found, idVendor=046d, idProduct=082b, bcdDevice=28.25
[ 194.304899] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 194.304924] usb 1-1.3: Product: Webcam C170
[ 194.304946] usb 1-1.3: Manufacturer:
v4l2-ctl --verbose -d /dev/videox --set-fmt-video=width=640,height=480,pixelformat='MJPG' --stream-mmap=4 --set-selection=target=crop,flags=0,top=0,left=0,width=640,height=480

前后摄设置

        默认是后摄,前摄如下修改

hardware/interfaces/camera/device/3.4/default/ExternalCameraDevice.cpp

    const uint8_t facing = ANDROID_LENS_FACING_FRONT; //BACK
    UPDATE(ANDROID_LENS_FACING, &facing, 1);

前后摄切换

1.android9,android10如下修改

/hardware/interfaces/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -309,7 +309,15 @@ status_t ExternalCameraDevice::initDefaultCharsKeys(
     UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
            &opticalStabilizationMode, 1);
 
-    const uint8_t facing = ANDROID_LENS_FACING_BACK;
+    const char* dev = mCameraId.c_str();
+    int index = (int) (*(dev + (strlen(dev) - 1)) - '0');
+    ALOGE("dev:%s index:%d", dev, index);
+    const uint8_t facing = (index / 2) % 2 ? ANDROID_LENS_FACING_FRONT : ANDROID_LENS_FACING_BACK;
     UPDATE(ANDROID_LENS_FACING, &facing, 1);

2.android11及12如下修改

/hardware/interfaces/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -309,7 +309,15 @@ status_t ExternalCameraDevice::initDefaultCharsKeys(
     UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
            &opticalStabilizationMode, 1);
 
-    const uint8_t facing = ANDROID_LENS_FACING_BACK;
+    const char* dev = mCameraId.c_str();
+    int index = atoi(dev);
+    ALOGE("dev:%s index:%d", dev, index);
+    const uint8_t facing = (index / 2) % 2 ? ANDROID_LENS_FACING_FRONT : ANDROID_LENS_FACING_BACK;
     UPDATE(ANDROID_LENS_FACING, &facing, 1);

录像问题

        录像分辨率及帧率在/device/rocchip/下的media_profiles_defaults.xml 里配置,编译时会拷到 /vendor/etc/media_profiles_V1_0.xml

        xml中通过id来识别摄像头即,根据实际情况可以添加或删除分辨率

## 录像问题

​		录像分辨率及帧率在/device/rocchip/下的media_profiles_defaults.xml 
里配置,编译时会拷到      /vendor/etc/media_profiles_V1_0.xml 

​		xml中通过id来识别摄像头即,根据实际情况可以添加或删除分辨率
<CamcorderProfiles cameraId="0">
<CamcorderProfiles cameraId="1">
		..........
		<EncoderProfile quality="480p" fileFormat="mp4" duration="30">
            <Video codec="h264"
                bitRate="3000000"     //录像模糊时,可以增大bitRate
                   width="640"
                   height="480"
                   frameRate="25" />
         ..........
        </EncoderProfile>

        例如usb摄像头是480p的,但是你录像时默认打开的分辨率为1080p,因此切换到录像时,会出现Can't connect to the camera报错,此时可以在xml中将对应sensor模块的1080p分辨率去除。

         USB摄像头拍照是正常的,但是录像的时候会提示报错;这种有可能是帧率不对,不支持导致的,具体可以看logcat。例如:device/rockchip里的media_profiles_default.xml 里framerate 改成25就解决了(dumpsys media.camera 里 可以看到支持帧率有25 但是没30帧)

镜像问题

Hardware/interfaces/camera/device/3.4/default/ExternalCameraDeviceSession.cpp ​ Hardware/interfaces/camera/device/3.4/default/ExternalCameraDevice.cpp

可以试下ExternalCameraDevice.cpp里 facing 改为BACK 后,看下预览是否会镜像了;

预览、拍照、录像这三种情况都会有镜像相关的问题(有相关patch)

1)预览镜像问题,在代码中修改成前置或后置就可以解决;

2)拍照镜像问题,libyuv::I420Scale 和 libyuv::I420MIrror 这段代码才是控制拍照镜像和翻转的

3)录像镜像问题:这是控制录像视频的mirror,即把 rga_nv12_scale_crop 里的 false 改成 (halBuf.usage & BufferUsage::VIDEO_ENCODER)

拉伸问题

        USB摄像头预览变形,换其他型号的USB摄像头也一样;看log picturesize:1920×1080,previewBuffer:1920×1080 预览分辨率为1080P,整体屏幕也是1080P,为什么会拉伸收缩变形?

需要注意的是摄像头成像长边要跟显示屏长边平行摆放;

默认竖屏设备 前摄 orientation 要为270,后摄为90;

默认横屏设备 前后摄 orientation都为0;

因此在xml中修改下orientation即可。

video节点权限问题

抓取logat后,关键字查询 E/CAM 发现没有权限

06-21 18:19:17.164 E/CamPvdr@2.4-external(  256): deviceAdded open v4l2 device /dev/video12 failed:Permission denied
06-21 18:19:17.165 E/CamPvdr@2.4-external(  256): deviceAdded open v4l2 device /dev/video13 failed:Permission denied

ls -l /dev/video* 查看下权限

crw-rw---- 1 media camera 81, 10 2022-06-22 09:47 /dev/video10
crw-rw---- 1 media camera 81, 11 2022-06-22 09:47 /dev/video11
crw------- 1 root root 81, 16 2022-06-22 09:47 /dev/video12
crw------- 1 root root 81, 17 2022-06-22 09:47 /dev/video13

如下修改后即可

/device/rockchip/common/ueventd.rockchip.rc
#for external camera
/dev/video10         0660   media      camera
/dev/video11         0660   media      camera
+ /dev/video12         0660   media      camera
+ /dev/video13         0660   media      camera

dqbuf卡住问题

        主要是针对usb摄像头插拔导致的一系列问题,例如插拔usb摄像头时,导致camera服务卡死,画面卡着不动;正常情况下插拔摄像头后预览画面可以恢复的。这种可能是预览中间断开,没有执行正常退出,没有wakeup这个wait_event,所以一直休着;等待超时发现有冗余未释放camera资源,应及时通知释放。(3588更新代码,会有这个补丁的)

        此外还有可能要加上0001-DQBUF-add-select.patch,一般拔掉usb摄像头后,apk会弹窗报错自动退出;如果没有弹框报错,说明dqbuf还是被卡住了,线程得不到释放,导致apk出现anr;要检查下补丁是否有打进去,是否生效了。  

        后面有空介绍这些:

 

物联沃分享整理
物联沃-IOTWORD物联网 » 【RK平台USB摄像头常见问题解答】

发表评论