【问题操作步骤】打开相机,拍照时,平滑缩放比例不正确,跳跃式的,x1.0 -> x1.3 -> x1.5....
【预期结果】平滑,是0.1,还是0.05看效果,手机上是0.1
先通过抓取log看看有没有什么信息;
经验可知mtk的camera是有日志开关的:
vendor\mediatek\proprietary\packages\apps\Camera2\common\src\com\mediatek\camera\common\debug\LogUtil.java
/**
* log tag check and log level check.
* @param tag the log tag.
* @param level log level.
* @return true if log tag and log level is OK.
*/
public static boolean isLoggable(Tag tag, int level) {
boolean checkLevelResult = false;
boolean checkResult = true;
int overrideLogLevel = getOverrideLevelFromProperty();
if (overrideLogLevel > -1
|| sPersistLogLevel > -1) {
// Self-defined log level are:
// MTKCAM_LOG_LEVEL_ERROR = 0;
// MTKCAM_LOG_LEVEL_WARNING = 1;
// MTKCAM_LOG_LEVEL_INFO = 2;
// MTKCAM_LOG_LEVEL_DEBUG = 3;
// MTKCAM_LOG_LEVEL_VERBOS = 4;
// Only loggable when current log level <= property's level.
// For example: when property's level is set to 2 by
// "adb shell setprop vendor.debug.mtkcam.loglevel 2",
// only ERROR, WARNING, INFO can loggable.
checkLevelResult = getLogLevelFromSystemLevel(level) <= overrideLogLevel;
checkLevelResult = checkLevelResult ||
(getLogLevelFromSystemLevel(level) <= sPersistLogLevel);
}
shouldLog(tag, level);
checkResult = checkLevelResult || shouldLog(tag, level) || isDebugOsBuild();
return checkResult;
}
将vendor.debug.mtkcam.loglevel属性设置为4方便抓取更多信息;
camera的缩放模块是zoom,找到Zoom.java
vendor\mediatek\proprietary\packages\apps\Camera2\feature\setting\zoom\src\com\mediatek\camera\feature\setting\zoom\Zoom.java
/**
* Initialize setting. This will be called when do open camera.
*
* @param app the instance of IApp.
* @param cameraContext the CameraContext.
* @param settingController the SettingController.
*/
public void init(IApp app,
ICameraContext cameraContext,
ISettingManager.SettingController settingController) {
super.init(app, cameraContext, settingController);
mTag = new Tag(Zoom.class.getSimpleName() + "-" + settingController.getCameraId());
mModeHandler = new Handler(Looper.myLooper());
mZoomGestureImpl.init();
mZoomViewCtrl.init(app);
initSettingValue();
mApp.registerOnOrientationChangeListener(mOrientationListener);
mAppUi.registerGestureListener(mZoomGestureImpl, IApp.DEFAULT_PRIORITY);
LogHelper.d(mTag, "[init] zoom: " + this + ", Gesture: " + mZoomGestureImpl);
// [Add for bit true test] Receive KEYCODE_ZOOM_IN and KEYCODE_ZOOM_OUT @{
mMainHandler = new MainHandler(mActivity.getMainLooper());
mApp.registerKeyEventListener(mZoomKeyEventListener, IApp.DEFAULT_PRIORITY);
// @}
}
mTag = new Tag(Zoom.class.getSimpleName() + "-" + settingController.getCameraId());
通过mTag抓取关键字log——"Zoom-"
搜索calculateDistanceRatio:
找到打印位置:
private double calculateDistanceRatio(ScaleGestureDetector scaleGestureDetector) {
float currentSpan = scaleGestureDetector.getCurrentSpan();
double distanceRatio = (currentSpan - mPreviousSpan) / mScreenDistance;
LogHelper.d(mTag, "[calculateDistanceRatio] distanceRatio = " + distanceRatio);
return distanceRatio;
}
发现是calculateDistanceRatio方法;并在onScale中调用了该方法;
@Override
public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
//First, if it should not zoom, return false.
String curValue = getValue();
if (IZoomConfig.ZOOM_OFF.equals(curValue)) {
return false;
}
if (mZoomConfig != null) {
double distanceRatio = calculateDistanceRatio(scaleGestureDetector);
mZoomConfig.onScalePerformed(distanceRatio);
if (Math.abs(distanceRatio - mLastDistanceRatio) > 0.08) {
requestZoom();
mLastDistanceRatio = distanceRatio;
}
}
return true;
}
requestZoom()
private void requestZoom() {
if (mModeHandler == null) {
return;
}
mModeHandler.post(new Runnable() {
@Override
public void run() {
mSettingChangeRequester.sendSettingChangeRequest();
}
});
}
看到这里,可以知道requestZoom()方法就是去发送sendSettingChangeRequest()的;这里if语句里面的(Math.abs(distanceRatio - mLastDistanceRatio) > 0.08)很重要,稍后会分析;
搜索mSettingChangeRequester看看这个对象是谁:
@Override
public ICaptureRequestConfigure getCaptureRequestConfigure() {
if (mCaptureRequestConfig == null) {
mCaptureRequestConfig
= new ZoomCaptureRequestConfig(this,mSettingDevice2Requester,mCurrentMode);
mCaptureRequestConfig.setZoomUpdateListener(mZoomLevelUpdateListener);
mSettingChangeRequester = mCaptureRequestConfig;
mZoomConfig = mCaptureRequestConfig;
LogHelper.d(mTag, "[getCaptureRequestConfigure]mZoomConfig: "
+ mSettingChangeRequester);
}
return (ZoomCaptureRequestConfig) mSettingChangeRequester;
}
mCaptureRequestConfig对象其实就是ZoomCaptureRequestConfig;
vendor\mediatek\proprietary\packages\apps\Camera2\feature\setting\zoom\src\com\mediatek\camera\feature\setting\zoom\ZoomCaptureRequestConfig.java
再去搜索sendSettingChangeRequest():
@Override
public void sendSettingChangeRequest() {
if (isZoomValid()) {
LogHelper.d(TAG, "[sendSettingChangeRequest]");
mSettingDevice2Requester.createAndChangeRepeatingRequest();
}
}
isZoomValid()
private boolean isZoomValid() {
LogHelper.d(TAG, "[isZoomValid] mCurZoomRatio = " + mCurZoomRatio + ", zoomRatio = "
+ calculateZoomRatio(mDistanceRatio) + ", mLastZoomRatio = " + mLastZoomRatio);
boolean needZoom = mCurZoomRatio >= ZOOM_UNSUPPORTED_DEFAULT_VALUE
&& mCurZoomRatio <= mMaxZoom
&& calculateZoomRatio(mDistanceRatio) != mLastZoomRatio;
LogHelper.d(TAG, "[isZoomValid] needZoom = " + needZoom);
return needZoom;
}
mSettingDevice2Requester.createAndChangeRepeatingRequest()——如此,调用到的camera的api2的接口函数,看名字可知该方法应该是去create和有changed时repeating请求的方法,这应该就是camera缩放倍率显示效果的函数;
手指缓慢的在camera预览界面进行缩放,抓取log:
2024-06-04 10:19:12.156 2957-2957/com.mediatek.camera D/CamAp_Zoom-0: [onScaleBegin], Gesture: com.mediatek.camera.feature.setting.zoom.Zoom$ZoomGestureImpl@ec3730, mZoomConfig: com.mediatek.camera.feature.setting.zoom.ZoomCaptureRequestConfig@c76ff1c
2024-06-04 10:19:12.175 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] mCurZoomRatio = 1.0, zoomRatio = 1.0, mLastZoomRatio = 1.0
2024-06-04 10:19:12.175 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] needZoom = false
2024-06-04 10:19:12.190 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] mCurZoomRatio = 1.0, zoomRatio = 1.0, mLastZoomRatio = 1.0
2024-06-04 10:19:12.190 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] needZoom = false
2024-06-04 10:19:12.207 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] mCurZoomRatio = 1.0, zoomRatio = 1.0, mLastZoomRatio = 1.0
2024-06-04 10:19:12.207 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] needZoom = false
2024-06-04 10:19:12.230 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] mCurZoomRatio = 1.0, zoomRatio = 1.0, mLastZoomRatio = 1.0
2024-06-04 10:19:12.231 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] needZoom = false
2024-06-04 10:19:12.241 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] mCurZoomRatio = 1.0, zoomRatio = 1.0, mLastZoomRatio = 1.0
2024-06-04 10:19:12.241 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] needZoom = false
2024-06-04 10:19:17.515 2957-2957/com.mediatek.camera D/CamAp_Zoom-0: [onScaleBegin], Gesture: com.mediatek.camera.feature.setting.zoom.Zoom$ZoomGestureImpl@ec3730, mZoomConfig: com.mediatek.camera.feature.setting.zoom.ZoomCaptureRequestConfig@c76ff1c
2024-06-04 10:19:17.549 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] mCurZoomRatio = 1.0, zoomRatio = 1.2535437, mLastZoomRatio = 1.0
2024-06-04 10:19:17.549 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] needZoom = true
2024-06-04 10:19:17.550 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [sendSettingChangeRequest]
2024-06-04 10:19:17.556 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [configCaptureRequest] this: com.mediatek.camera.feature.setting.zoom.ZoomCaptureRequestConfig@c76ff1c, mCurZoomRatio = 1.2535437, mDistanceRatio = 0.0845145732164383 mZoomRatioSupported = true mSensorRect = Rect(0, 0 - 3264, 2448)
2024-06-04 10:19:17.682 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] mCurZoomRatio = 1.2535437, zoomRatio = 1.5060472, mLastZoomRatio = 1.2535437
2024-06-04 10:19:17.682 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [isZoomValid] needZoom = true
2024-06-04 10:19:17.682 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [sendSettingChangeRequest]
2024-06-04 10:19:17.688 2957-3677/com.mediatek.camera D/CamAp_ZoomCaptureRequestConfig: [configCaptureRequest] this: com.mediatek.camera.feature.setting.zoom.ZoomCaptureRequestConfig@c76ff1c, mCurZoomRatio = 1.5060472, mDistanceRatio = 0.16868239641189575 mZoomRatioSupported = true mSensorRect = Rect(0, 0 - 3264, 2448)
发现camera缩放倍率=1.0x的时候,zoomRatio = 1.0;缩放倍率=1.2x的时候,zoomRatio = 1.2535437;
private float calculateZoomRatio(double distanceRatio) {
float find = ZOOM_UNSUPPORTED_DEFAULT_VALUE; // if not find, return 1.0f.
float maxRatio = mMaxZoom;//4.0f
float minRatio = ZOOM_UNSUPPORTED_DEFAULT_VALUE;//1.0f
float curRatio = (float) (mBasicZoomRatio + (maxRatio - minRatio) * distanceRatio);
if (curRatio <= minRatio) {
find = minRatio;
} else if (curRatio >= maxRatio) {
find = maxRatio;
} else {
find = curRatio;
}
return find;
}
由该方法可知,在[1,4]这个倍率区间里,mBasicZoomRatio 初始值=1.0f;zoomRatio =1.0 + (4.0 - 1.0) * distanceRatio;
还记得前面说过的if语句判断条件吗?
@Override
public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
//First, if it should not zoom, return false.
String curValue = getValue();
if (IZoomConfig.ZOOM_OFF.equals(curValue)) {
return false;
}
if (mZoomConfig != null) {
double distanceRatio = calculateDistanceRatio(scaleGestureDetector);
mZoomConfig.onScalePerformed(distanceRatio);
if (Math.abs(distanceRatio - mLastDistanceRatio) > 0.08) {
requestZoom();
mLastDistanceRatio = distanceRatio;
}
}
return true;
}
有一句mZoomConfig.onScalePerformed(distanceRatio)
@Override
public void onScalePerformed(double distanceRatio) {
mDistanceRatio = distanceRatio;
}
calculateZoomRatio(mDistanceRatio);前面计算公式的distanceRatio就是这个mDistanceRatio,所以distanceRatio = 0.08;所以每次变化0.08的手指缩放间距,camera缩放倍数就会增加0.24的倍数;可以得出,如果想要0.1x的渐变缩放效果,需要改成每0.033的变化就发送请求一次;
if (Math.abs(distanceRatio - mLastDistanceRatio) > 0.033) {
requestZoom();
mLastDistanceRatio = distanceRatio;
}
验证结果:
最后修改diff:
--- a/mediatek/proprietary/packages/apps/Camera2/feature/setting/zoom/src/com/mediatek/camera/feature/setting/zoom/Zoom.java
+++ b/mediatek/proprietary/packages/apps/Camera2/feature/setting/zoom/src/com/mediatek/camera/feature/setting/zoom/Zoom.java
@@ -291,7 +291,7 @@ public class Zoom extends SettingBase {
if (mZoomConfig != null) {
double distanceRatio = calculateDistanceRatio(scaleGestureDetector);
mZoomConfig.onScalePerformed(distanceRatio);
- if (Math.abs(distanceRatio - mLastDistanceRatio) > 0.08) {
+ if (Math.abs(distanceRatio - mLastDistanceRatio) > 0.033) {
requestZoom();
mLastDistanceRatio = distanceRatio;
}