环境
AndroidR(11)
camera2
IDE为Android studio
1、切换按钮的点击监听
com.mediatek.camera.feature.setting.CameraSwitcher.java
private View initView() {
Activity activity = mApp.getActivity();
View switcher = activity.getLayoutInflater().inflate(R.layout.camera_switcher, null);
switcher.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (SystemProperties.getInt(SWITCH_CAMERA_DEBUG_PROPERTY, 0) == 1) {
LogHelper.d(TAG, "[onClick], enter debug mode.");
switchCameraInDebugMode();
} else if (SystemProperties.getInt(DEBUG_MAIN2, 0) == 1) {
LogHelper.d(TAG, "[onClick], enter main2 debug mode.");
switchCameraInDebugMain2();
} else {
LogHelper.d(TAG, "[onClick], enter camera normal mode.");
switchCameraInNormal();
}
}
});
switcher.setContentDescription(mFacing);
return switcher;
}
上面的监听方法中点击后走的都是else ,所以要跟踪的是switcCameraInNormal方法
2、switcCameraInNormal
private void switchCameraInNormal() {
String nextFacing = mFacing.equals(CAMERA_FACING_BACK) ? CAMERA_FACING_FRONT
: CAMERA_FACING_BACK;
LogHelper.d(TAG, "[switchCameraInNormal], switch camera to " + nextFacing);
String newCameraId = mFacing.equals(CAMERA_FACING_BACK) ? CameraUtil
.getCamIdsByFacing(false, mApp.getActivity()).get(0) :
CameraUtil.getCamIdsByFacing(true, mApp.getActivity()).get(0);
//for dual zoom
if (nextFacing.equals(CAMERA_FACING_BACK) && CameraUtil.getDualZoomId() != null
&& !mCurrentMode.equals(INTENT_PHOTO_MODE)
&& !mCurrentMode.equals(INTENT_VIDEO_MODE)) {
newCameraId = CameraUtil.getDualZoomId();
}
//for stereo
if (mCurrentMode.equals(STEREO_PHOTO_MODE) || mCurrentMode.equals(STEREO_VIDEO_MODE)) {
if (nextFacing.equals(CAMERA_FACING_BACK)
&& CameraUtil.getLogicalCameraId() != null) {
newCameraId = CameraUtil.getLogicalCameraId();
} else if (nextFacing.equals(CAMERA_FACING_FRONT)
&& CameraUtil.getFrontLogicalId() != null) {
newCameraId = CameraUtil.getFrontLogicalId();
} else if (nextFacing.equals(CAMERA_FACING_FRONT)
&& CameraUtil.getFrontLogicalId() == null
&& CameraUtil.getLogicalCameraId() != null) {
newCameraId = CameraUtil.getLogicalCameraId();
}
}
boolean success = mApp.notifyCameraSelected(newCameraId);
if (success) {
LogHelper.d(TAG, "[switchCameraInNormal], switch camera success.");
mFacing = nextFacing;
mDataStore.setValue(KEY_CAMERA_SWITCHER, mFacing,
getStoreScope(), true);
}
mSwitcherView.setContentDescription(mFacing);
}
上面大部分逻辑在走是由前置--->后置,还是后置--->前置。接下来走的是 mApp.notifyCameraSelected(newCameraId);就是通知要切换摄像头了
3、notifyCameraSelected(newCameraId)
可以看到是在CameraActivity.java中调用了该方法。
4、在CameraActivity.java中跟踪
可以看到在很多地方都调用了该接口,例如photoMode,videoMode等(拍照模式和拍视频模式),我们选择跟踪的是VideoMode(总得找个入口)
5、在VideoModel中具体调用代码如下
@Override
public boolean onCameraSelected(@Nonnull String newCameraId) {
LogHelper.i(TAG, "[onCameraSelected] new id = " + newCameraId + " old id = " + mCameraId);
super.onCameraSelected(newCameraId);
if (canSelectCamera(newCameraId)) {
mIApp.getAppUi().onCameraSelected(newCameraId);
mCameraDevice.setPreviewCallback(null, getPreviewStartCallback());
doCameraSelect(newCameraId);
return true;
} else {
mAppUi.applyAllUIEnabled(true);
return false;
}
}
mIApp.getAppUi().onCameraSelected(newCameraId);是通知UImCameraDevice.setPreviewCallback(null, getPreviewStartCallback());预览回调doCameraSelect(newCameraId);摄像头切换(终于找到了,看看做了啥)
6、doCameraSelect
private void doCameraSelect(String newCameraId) {
LogHelper.i(TAG, "[doCameraSelect] + mVideoState = " + mVideoState);
if (getVideoState() == VideoState.STATE_PREVIEW
&& getModeState() == ModeState.STATE_RESUMED) {
mCameraDevice.preventChangeSettings();
updateVideoState(VideoState.STATE_UNKNOWN);
mCameraDevice.closeCamera(true);
mCameraContext.getSettingManagerFactory().recycle(mCameraId);
mCameraId = newCameraId;
mSettingManager = mCameraContext.getSettingManagerFactory().getInstance(
mCameraId, getModeKey(), ModeType.VIDEO, mCameraApi);
initStatusMonitor();
mVideoHelper.releasePreviewFrameData();
mCameraDevice.setPreviewCallback(
mVideoHelper.getPreviewFrameCallback(), getPreviewStartCallback());
mCameraDevice.openCamera(mSettingManager, mCameraId, true, mRestrictionProvider);
}
}
mCameraDevice.closeCamera(true);先是关闭,mCameraDevice.openCamera(mSettingManager, mCameraId, true, mRestrictionProvider);然后打开(此时的mCameraId为切换后的ID)
问题是关闭和打开是同步还是异步(执行关闭后,再执行打开?还是关闭的同时打开)这么看着不清除啊
如上图所示,关闭和开机都是加了锁的。
思路是在close和open里都打上debug ,然后跑一下看看此种状态下是同步还是异步(猜一下啊,应该不是同步的,但是为啥切换前后置的时候还是这么慢(差不多1200毫秒),搞一把)。
走分析了啊,是不是跟本文的标题不符了(跑题了)