关于后副摄像头模组的方向问题
最近的一个新的项目需求,因为软件已经实现了背景虚化的效果,所以需要上面添加一个可以打开后副摄的功能。本文介绍两类方案仅供参考。
最初的方案:
硬件与驱动
先来说说硬件上的设计,虽说新加了个摄像头本例中为sp2509模组,其安装在后摄像头旁边,作为后副摄使用,但是硬件设计上却是与前摄像头共用ISP,走前摄像头的所有流程。本例中,对于三个摄像头的安装角度定义如下:
SensorOrientation_T const&
getSensorOrientation()
{
static SensorOrientation_T const inst = {
u4Degree_0 : 90, // main sensor in degree (0, 90, 180, 270)
u4Degree_1 : 270, // sub sensor in degree (0, 90, 180, 270)
u4Degree_2 : 270, // main2 sensor in degree (0, 90, 180, 270)
};
return inst;
}
最初,为了考虑Camera360等第三方APP打开main2摄像头有镜像问题,所以将寄存器写入一个write_cmos_sensor(0x3f,0x01);,使其有一个Horizontal mirror的效果。
驱动在使用MTK的方案点亮main2摄像头,通过getCameraInfo给上层传递facing,orientation,通过getNumOfCamera给上层提供cameraId,其main2摄像头对应的cameraId=2。
这里,在Hal层中通过如下,控制main2的facing,orientation值。
if(deviceId==2){
rInfo.facing = 1;
rInfo.orientation = 270;
}
else{
rInfo.facing = pEnumInfo->iFacing;
rInfo.orientation = pEnumInfo->iWantedOrientation;
}
自开发APP与第三方APP的方向问题
先说第三方APP的方向,上面已陈述:考虑镜像问题,将寄存器写入一个write_cmos_sensor(0x3f,0x01);,使其有一个Horizontal mirror的效果。这样,可以保证camera360等一系列可以打开后副摄像头的第三方APP的预览方向是正常的。类似于Google Duo与Camera360系列APP,只会根据当前facing值,去读取驱动中的寄存器配置,其余修改对其无效。
而自开发APP是走的camera API1的标准流程,所以在cameraClient.cpp文件中获得的getOrientation()角度,会直接影响到预览的方向。因此,我们针对main2 id 对其进行同mirror一样的配置。
没错,将其方向按照前摄(即mirror为true)的模式进行处理。当然,APP本身在处理预览setDisplayOrientation里面的方向,以及录制视频的setOrientationHint(rotation);
等方向均需按照如下处理:
int rotation = 0;
if (mOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
Characteristics info = mActivity.getCameraProvider().getCharacteristics(mCameraId);
if (isCameraFrontFacing()) {
rotation = (info.getSensorOrientation() - mOrientation 360) % 360;
} else if (isCameraBackFacing()) {
rotation = (info.getSensorOrientation() +mOrientation) % 360;
} else if (mActivity.getCurrentCameraId() == 2) {
rotation = (info.getSensorOrientation() - mOrientation 360) % 360; } }
按照上面所述配置,main2摄像头,自开发相机与第三方APP的预览方向均为正常,但拍照出现镜像,不过,这个在应用层可以利用现有前摄拍照镜像的代码来解决。
方案二
后来发现,灾难来了,腾讯系列软件,WeChat,QQ视频时,因为上述
if(deviceId==2){
rInfo.facing = 1;
rInfo.orientation = 270;
}
的修改,切换出现了问题;除此之外,自开发相机的录像播放有镜像的问题也迟迟不好处理。
于是痛定思痛,驱动中将寄存器写值write_cmos_sensor(0x3f,0x00);,即不考虑第三方的预览方向问题,不从底层先设置一个Horizontal mirror镜像,当然,CameraClient.cpp文件中getOrientation()恢复原来代码,不做修改。根据SensorOrientation与当前旋转方向依次调整完预览的方向,拍照的方向,这样,正常拍好方向,全景,连拍也不会出现拍照方向倒置的问题了。
现在考虑第三方问题,首先微信,QQ等不会根据getNumberOfCameras来判断当前打开几个摄像头,它们只认facing值0和1,改为其他的facing值,则不会打开main2,于是这里仍旧写为2。
if(deviceId==2){
rInfo.facing = 2;
rInfo.orientation = 270;
}
其余,第三方包括DUO和camera360则会打开main2,按照目前这种方案就肯定有问题,所以索性在cameraService.cpp里面,通过进程控制if (cameraId == 2 && 0 != strcmp("com.xxx.camera", String8(clientPackageName).string()))打开camera id为1即目前前摄。所遇到的问题,暂时解决。
如有更好方案,欢迎随时讨论。