RK3288 android 6.0 同时打开两个摄像头
问题描述
- 平台: RK3288
- 系统: Android 6.0
- 需求: 同时打开两个摄像头
业务需求,要支持同时打开多个摄像头,期间遇到一些问题,在这里记录下。
问题分析
支持多摄像头
首先,Android系统默认只支持同时打开一个摄像头,并且最大只识别两个摄像头。所以,为了支持多摄像头,需要修改摄像头相关的 HAL
层。
这个我参考 [AndroidO] [RK3399] Support 4 way camera preview 解决了。patch 如下:
diff --git a/device/rockchip/common/ueventd.rockchip.rc b/device/rockchip/common/ueventd.rockchip.rc
index 7316ebf..e73da8d 100755
--- a/device/rockchip/common/ueventd.rockchip.rc
+++ b/device/rockchip/common/ueventd.rockchip.rc
@@ -19,6 +19,23 @@
/dev/video1 0660 media camera
/dev/video2 0660 media camera
/dev/video3 0660 media camera
+/dev/video4 0660 media camera
+/dev/video5 0660 media camera
+/dev/video6 0660 media camera
+/dev/video7 0660 media camera
+/dev/video8 0660 media camera
+/dev/video9 0660 media camera
+/dev/video10 0660 media camera
+/dev/video11 0660 media camera
+/dev/video12 0660 media camera
+/dev/video13 0660 media camera
+/dev/video14 0660 media camera
+/dev/video15 0660 media camera
+/dev/video16 0660 media camera
+/dev/video17 0660 media camera
+/dev/video18 0660 media camera
+/dev/video19 0660 media camera
+/dev/video20 0660 media camera
/dev/pmem_cam 0660 system camera
/dev/vpu 0660 system system
/dev/vpu_service 0666 media media
diff --git a/hardware/rockchip/camera/CameraHal/CameraHal_Module.cpp b/hardware/rockchip/camera/CameraHal/CameraHal_Module.cpp
index 3365339..012d14e 100755
--- a/hardware/rockchip/camera/CameraHal/CameraHal_Module.cpp
+++ b/hardware/rockchip/camera/CameraHal/CameraHal_Module.cpp
@@ -712,9 +712,10 @@ int usb_camera_hotplug(void)
(strcmp(usbcameraPlug, "remove") == 0);
return plugstate;
}
-
+//modify by fujianyong for [Supporting multiple cameras] start
int camera_get_number_of_cameras(void)
{
+ char cam_sys[40];
char cam_path[20];
char cam_num[3],i;
int cam_cnt=0,fd=-1,rk29_cam[CAMERAS_SUPPORT_MAX];
@@ -770,9 +771,11 @@ int camera_get_number_of_cameras(void)
delete camEngVerItf;
}
-
- memset(&camInfoTmp[0],0x00,sizeof(rk_cam_info_t));
- memset(&camInfoTmp[1],0x00,sizeof(rk_cam_info_t));
+ for(int i=0;i<CAMERAS_SUPPORT_MAX;i++){
+ memset(&camInfoTmp[i],0x00,sizeof(rk_cam_info_t));
+ }
+ //memset(&camInfoTmp[0],0x00,sizeof(rk_cam_info_t));
+ //memset(&camInfoTmp[1],0x00,sizeof(rk_cam_info_t));
profiles = camera_board_profiles::getInstance();
nCamDev = profiles->mDevieVector.size();
@@ -787,18 +790,18 @@ int camera_get_number_of_cameras(void)
if(profiles->mDevieVector[i]->mIsConnect==1){
rk_sensor_info *pSensorInfo = &(profiles->mDevieVector[i]->mHardInfo.mSensorInfo);
- camInfoTmp[cam_cnt&0x01].pcam_total_info = profiles->mDevieVector[i];
- strncpy(camInfoTmp[cam_cnt&0x01].device_path, pSensorInfo->mCamsysDevPath, sizeof(camInfoTmp[cam_cnt&0x01].device_path));
- strncpy(camInfoTmp[cam_cnt&0x01].driver, pSensorInfo->mSensorDriver, sizeof(camInfoTmp[cam_cnt&0x01].driver));
+ camInfoTmp[cam_cnt].pcam_total_info = profiles->mDevieVector[i];
+ strncpy(camInfoTmp[cam_cnt].device_path, pSensorInfo->mCamsysDevPath, sizeof(camInfoTmp[cam_cnt].device_path));
+ strncpy(camInfoTmp[cam_cnt].driver, pSensorInfo->mSensorDriver, sizeof(camInfoTmp[cam_cnt].driver));
unsigned int SensorDrvVersion = profiles->mDevieVector[i]->mLoadSensorInfo.mpI2cInfo->sensor_drv_version;
memset(version,0x00,sizeof(version));
sprintf(version,"%d.%d.%d",((SensorDrvVersion&0xff0000)>>16),
((SensorDrvVersion&0xff00)>>8),SensorDrvVersion&0xff);
if(pSensorInfo->mFacing == RK_CAM_FACING_FRONT){
- camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_FRONT;
+ camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_FRONT;
} else {
- camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_BACK;
+ camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_BACK;
}
memset(sensor_ver,0x00,sizeof(sensor_ver));
@@ -808,7 +811,7 @@ int camera_get_number_of_cameras(void)
sprintf(sensor_ver,"%s",pSensorInfo->mSensorName);
property_set(sensor_ver, version);
- camInfoTmp[cam_cnt&0x01].facing_info.orientation = pSensorInfo->mOrientation;
+ camInfoTmp[cam_cnt].facing_info.orientation = pSensorInfo->mOrientation;
cam_cnt++;
unsigned int CamsysDrvVersion = profiles->mDevieVector[i]->mCamsysVersion.drv_ver;
@@ -833,13 +836,34 @@ int camera_get_number_of_cameras(void)
i++;
}
- for (i=0; i<10; i++) {
+ for (i=0; i<20; i++) {
cam_path[0] = 0x00;
- unsigned int pix_format_tmp = V4L2_PIX_FMT_NV12;
- strcat(cam_path, CAMERA_DEVICE_NAME);
+ //unsigned int pix_format_tmp = V4L2_PIX_FMT_NV12;
+ //strcat(cam_path, CAMERA_DEVICE_NAME);
+ cam_sys[0] = 0x00;
+ strcat(cam_sys, CAM_SYS_NAME);
sprintf(cam_num, "%d", i);
+ strcat(cam_sys,cam_num);
+ strcat(cam_sys,"/index");
+ FILE* ifp;
+ ifp = fopen(cam_sys, "r");
+ if (ifp == NULL){
+ LOGD("fail to open sys file:%s",cam_sys);
+ continue;
+ }
+ unsigned char index;
+ fread(&index, sizeof(char),1, ifp);
+ fclose(ifp);
+ LOGD("open %s index %x",cam_sys,index);
+ if(index == 0x31){
+ LOGD("%s wrong index continue",cam_sys);
+ continue;
+ }
+ strcat(cam_path, CAMERA_DEVICE_NAME);
+
strcat(cam_path,cam_num);
fd = open(cam_path, O_RDONLY);
+ unsigned int pix_format_tmp = V4L2_PIX_FMT_NV12;
if (fd < 0) {
LOGE("Open %s failed! strr: %s",cam_path,strerror(errno));
break;
@@ -856,31 +880,31 @@ int camera_get_number_of_cameras(void)
LOGD("Video device(%s): video capture not supported.\n",cam_path);
} else {
rk_cam_total_info* pNewCamInfo = new rk_cam_total_info();
- memset(camInfoTmp[cam_cnt&0x01].device_path,0x00, sizeof(camInfoTmp[cam_cnt&0x01].device_path));
- strcat(camInfoTmp[cam_cnt&0x01].device_path,cam_path);
- memset(camInfoTmp[cam_cnt&0x01].fival_list,0x00, sizeof(camInfoTmp[cam_cnt&0x01].fival_list));
- memcpy(camInfoTmp[cam_cnt&0x01].driver,capability.driver, sizeof(camInfoTmp[cam_cnt&0x01].driver));
- camInfoTmp[cam_cnt&0x01].version = capability.version;
+ memset(camInfoTmp[cam_cnt].device_path,0x00, sizeof(camInfoTmp[cam_cnt].device_path));
+ strcat(camInfoTmp[cam_cnt].device_path,cam_path);
+ memset(camInfoTmp[cam_cnt].fival_list,0x00, sizeof(camInfoTmp[cam_cnt].fival_list));
+ memcpy(camInfoTmp[cam_cnt].driver,capability.driver, sizeof(camInfoTmp[cam_cnt].driver));
+ camInfoTmp[cam_cnt].version = capability.version;
if (strstr((char*)&capability.card[0], "front") != NULL) {
- camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_FRONT;
+ camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_FRONT;
#ifdef LAPTOP
} else if (strstr((char*)&capability.card[0], "HP HD") != NULL
|| strstr((char*)&capability.card[0], "HP IR")) {
- camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_FRONT;
+ camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_FRONT;
if (strstr((char*)&capability.card[0], "HP IR"))
gCamerasUnavailabled++;
- gUsbCameraNames[cam_cnt&0x01] = String8((char*)&capability.card[0]);
- LOGD("Camera %d name: %s", (cam_cnt&0x01), gUsbCameraNames[cam_cnt&0x01].string());
+ gUsbCameraNames[cam_cnt] = String8((char*)&capability.card[0]);
+ LOGD("Camera %d name: %s", (cam_cnt), gUsbCameraNames[cam_cnt].string());
#endif
} else {
- camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_BACK;
+ camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_BACK;
}
ptr = strstr((char*)&capability.card[0],"-");
if (ptr != NULL) {
ptr++;
- camInfoTmp[cam_cnt&0x01].facing_info.orientation = atoi(ptr);
+ camInfoTmp[cam_cnt].facing_info.orientation = atoi(ptr);
} else {
- camInfoTmp[cam_cnt&0x01].facing_info.orientation = 0;
+ camInfoTmp[cam_cnt].facing_info.orientation = 0;
}
memset(version,0x00,sizeof(version));
@@ -1168,7 +1192,7 @@ int camera_get_number_of_cameras(void)
camInfoTmp[cam_cnt].pcam_total_info = pNewCamInfo;
cam_cnt++;
if (cam_cnt >= CAMERAS_SUPPORT_MAX)
- i = 10;
+ i = 20;
}
loop_continue:
if (fd > 0) {
@@ -1215,8 +1239,11 @@ int camera_get_number_of_cameras(void)
}
#endif
- memcpy(&gCamInfos[0], &camInfoTmp[0], sizeof(rk_cam_info_t));
- memcpy(&gCamInfos[1], &camInfoTmp[1], sizeof(rk_cam_info_t));
+ //memcpy(&gCamInfos[0], &camInfoTmp[0], sizeof(rk_cam_info_t));
+ //memcpy(&gCamInfos[1], &camInfoTmp[1], sizeof(rk_cam_info_t));
+ for(int i=0;i<CAMERAS_SUPPORT_MAX;i++){
+ memcpy(&gCamInfos[i], &camInfoTmp[i], sizeof(rk_cam_info_t));
+ }
property_get("ro.sf.hwrotation", property, "0");
@@ -1240,7 +1267,7 @@ camera_get_number_of_cameras_end:
#else
return gCamerasNumber;
#endif
-}
+}//modify by fujianyong for [Supporting multiple cameras] end
#if 0
int camera_get_number_of_cameras(void)
diff --git a/hardware/rockchip/camera/CameraHal/CameraHal_Module.h b/hardware/rockchip/camera/CameraHal/CameraHal_Module.h
index 45c81ec..3927ddf 100755
--- a/hardware/rockchip/camera/CameraHal/CameraHal_Module.h
+++ b/hardware/rockchip/camera/CameraHal/CameraHal_Module.h
@@ -11,13 +11,14 @@ using namespace android;
#define CAMERA_DEFAULT_PREVIEW_FPS_MIN 8000 //8 fps
#define CAMERA_DEFAULT_PREVIEW_FPS_MAX 15000
#endif
-#define CAMERAS_SUPPORT_MAX 2
+#define CAMERAS_SUPPORT_MAX 4
#if defined(TARGET_RK3399)
- #define CAMERAS_SUPPORTED_SIMUL_MAX 2
+ #define CAMERAS_SUPPORTED_SIMUL_MAX 4
#else
#define CAMERAS_SUPPORTED_SIMUL_MAX 1
#endif
#define CAMERA_DEVICE_NAME "/dev/video"
+#define CAM_SYS_NAME "/sys/class/video4linux/video"
#define CAMERA_MODULE_NAME "RK29_ICS_CameraHal_Module"
typedef struct rk_cam_info_s {
通过该 patch
就支持了4个摄像头。
带宽不足
加入以上patch后,确实可以同时识别多个摄像头,但是同时预览不一定成功,我测试了多组摄像头,不同组合结果不一样,有成功的,也有失败的。
失败的时候,会报以下错误。
uvcvideo: Failed to submit URB 0 (-28).
错误码 28
说明空间不足,这个可以从头文件 errno.h
中查找到其定义。搜索发现与 USB 带宽分配相关。使用 lsusb
可以看到
Bus 001 Device 002: ID 1a40:0101
Bus 003 Device 002: ID 0bda:0179
Bus 001 Device 001: ID 1d6b:0002
Bus 002 Device 001: ID 1d6b:0002
Bus 003 Device 001: ID 1d6b:0002
Bus 001 Device 003: ID 058f:5608
Bus 001 Device 004: ID 058f:5608
最后两个对应摄像头,使用的是同一个usb bus,对应同一个usb控制器。
usb 2.0 速率为480Mbps,一个摄像头占用带宽可以粗略估算:
长(640)*宽(480)*帧率(30)*像素点数据长度(24) + 协议头部
调试许久,最后通过添加kernel调试代码,打印带宽信息,对比成功和失败的案例,最终确定是出错摄像头默认配置带宽过高导致的,解决方案如下:
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 669d81c..b1b381e 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1684,6 +1684,11 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
/* Isochronous endpoint, select the alternate setting. */
bandwidth = stream->ctrl.dwMaxPayloadTransferSize;
+ if (bandwidth > UVC_LIMITED_BANDWIDTH) {
+ printk(KERN_ERR "UVC_DBG: limit bandwidth from %d to %d \n",
+ bandwidth, UVC_LIMITED_BANDWIDTH);
+ bandwidth = UVC_LIMITED_BANDWIDTH;
+ }
if (bandwidth == 0) {
uvc_trace(UVC_TRACE_VIDEO, "Device requested null "
"bandwidth, defaulting to lowest.\n");
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 033c775..86d11f4 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -142,6 +142,9 @@
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
#define UVC_FMT_FLAG_STREAM 0x00000002
+/* Limit bandwith */
+#define UVC_LIMITED_BANDWIDTH 800
+
/* ------------------------------------------------------------------------
* Structures.
*/
以上 bandwidth
在出错情况下为 3072
, 不出错的摄像头对应 800
, 因此我将其限制在 800
, 重新编译后解决问题。
参考
版权声明:本博客所有文章除特殊声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明出处 litreily的博客!