SnapdragonCamera骁龙相机源码解析

骁龙相机是高通开发的一个测试系统摄像头的demo,代码完善,功能强大。可以配合Camera驱动进行功能联调。

很多逻辑代码在CaptureModule.java里。

CaptureModule有8000多行,包罗万象。

涉及到界面显示要结合CaptureUI.java  一起来实现。

CaptureActivity持有了 CaptureModule 和 CaptureUI 。

以上是主要的引用关系。

CameraActivity 中调用了以下代码

case ModuleSwitcher.CAPTURE_MODULE_INDEX:if(mCaptureModule == null) {mCaptureModule = new CaptureModule();//核心代码!!!mCaptureModule.init(this, mCameraCaptureModuleRootView);} else {mCaptureModule.reinit();}mCurrentModule = mCaptureModule;mCameraCaptureModuleRootView.setVisibility(View.VISIBLE);Log.e("CameraActity"," setModuleFromIndex =================== CAPTURE_MODULE_INDEX");break;

 CaptureModule 里初始化代码:

@Overridepublic void init(CameraActivity activity, View parent) {mActivity = activity;mRootView = parent;mSettingsManager = SettingsManager.getInstance();mSettingsManager.createCaptureModule(this);mSettingsManager.registerListener(this);if (mSettingsManager.mIsHasOneCamera) {CURRENT_ID = 0;} else {if (isBackCameraId()) {CURRENT_ID = BACK_MODE;} else {CURRENT_ID = FRONT_MODE;}}mSettingsManager.init();mFirstPreviewLoaded = false;Log.d(TAG, "init");for (int i = 0; i < MAX_NUM_CAM; i++) {mCameraOpened[i] = false;mTakingPicture[i] = false;}for (int i = 0; i < MAX_NUM_CAM; i++) {mState[i] = STATE_PREVIEW;}SceneModule module;for (int i = 0; i < mSelectableModes.length + 2; i++) {module = new SceneModule();module.mode = CameraMode.values()[i];mSceneCameraIds.add(module);}mPostProcessor = new PostProcessor(mActivity, this);mFrameProcessor = new FrameProcessor(mActivity, this);mContentResolver = mActivity.getContentResolver();initModeByIntent();initCameraIds();mUI = new CaptureUI(activity, this, parent);mUI.initializeControlByIntent();mFocusStateListener = new FocusStateListener(mUI);mLocationManager = new LocationManager(mActivity, this);}

通过以下代码初始化CaptureUI

 mUI = new CaptureUI(activity, this, parent);mUI.initializeControlByIntent();

介绍一个核心操作来,了解是如何切换拍照模式的。

首先,通过CaptureUI ,来对组件赋予监听回调。

mFlashButton = (FlashToggleButton) mRootView.findViewById(R.id.flash_button);mModeSelectLayout = (RecyclerView) mRootView.findViewById(R.id.mode_select_layout);mModeSelectLayout.setLayoutManager(new LinearLayoutManager(mActivity,LinearLayoutManager.HORIZONTAL, false));mCameraModeAdapter = new Camera2ModeAdapter(mModule.getCameraModeList());//设置单击回调 mCameraModeAdapter.setOnItemClickListener(mModule.getModeItemClickListener());mModeSelectLayout.setAdapter(mCameraModeAdapter);mSettingsIcon = (ImageView) mRootView.findViewById(R.id.settings);mSettingsIcon.setImageResource(R.drawable.settings);mSettingsIcon.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {openSettingsMenu();}});

对应CaptureModule的处理。

 public OnItemClickListener getModeItemClickListener() {return new OnItemClickListener() {@Overridepublic int onItemClick(int mode) {if (showLog) Log.e(TAG, "mode >>> " + mode);if (!getCameraModeSwitcherAllowed()) {return -1;}if (mode == CameraMode.VIDEO.ordinal()) {videoCameraId = -1;videoType = VIDEO_DEFAULT;} else {if (mode == CameraMode.MACRO.ordinal() || mode == CameraMode.NIGHT.ordinal()) {videoCameraId = -1;videoType = -1;}}return selectCameraMode(mode);}};}

CaptureModule 核心代码处理:

public int selectCameraMode(int mode) {if (showLog) Log.e("CaptureModule", "  mode:: ============== " + mode);if (showLog)Log.e("CaptureModule", "  mCurrentSceneMode.mode:: =================== " + mCurrentSceneMode.mode);for (SceneModule sceneModule : mSceneCameraIds) {if (showLog) Log.e(TAG, " secenmode:: >> " + sceneModule.mode);}if (showLog)Log.e("CaptureModule", "  mSceneCameraIds.get(mode).mode:: =================== " + mSceneCameraIds.get(mode).mode);if (showLog) Log.e("CaptureModule", "  videoType:: =================== " + videoType);if (showLog)Log.e("CaptureModule", "  videoCameraId:: =================== " + videoCameraId);showCameraDevice();String value = mSettingsManager.getValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE);boolean post = false;if (mode == CameraMode.VIDEO.ordinal()) {videoType = VIDEO_DEFAULT;videoCameraId = 0;} else if (mode == CameraMode.MACRO.ordinal()) {if (value != null && value.equals("front")) {post = true;if (!isBackCamera()) {mUI.performCameraSwitchClick();}}} else if (mode == CameraMode.DEFAULT.ordinal()) {videoType = -1;videoCameraId = -1;} else if (mode == CameraMode.NIGHT.ordinal()) {if (value != null && value.equals("front")) {if (!isBackCamera()) {post = true;mUI.performCameraSwitchClick();}}if (showLog)Log.e("xxx", " mPreviewRequestBuilder.length ===========> " + mPreviewRequestBuilder.length);if (showLog)Log.e("xxx", " mPreviewRequestBuilder.length ===========> " + mPreviewRequestBuilder.length);} else if (mode == CameraMode.PRO_MODE.ordinal()) {
//            if (value != null && value.equals("front")) {
//                if (!isBackCamera()) {
//                    post = true;
//                    mUI.performCameraSwitchClick();
//                }
//            }} else if (mode == CameraMode.HFR.ordinal()) {if (value != null && value.equals("front")) {if (!isBackCamera()) {post = true;mUI.performCameraSwitchClick();}}}if (showLog)Log.e("CaptureModule", "  mode2:: ============== " + mode);if (showLog)Log.e("CaptureModule", "  mCurrentSceneMode.mode2 :: =================== " + mCurrentSceneMode.mode);if (showLog)Log.e("CaptureModule", "  mSceneCameraIds.get(mode).mode2 :: =================== " + mSceneCameraIds.get(mode).mode);showCameraDevice();nmode = mode;if (post) {mHandler.postDelayed(new Runnable() {@Overridepublic void run() {selectModle(nmode);}}, 1000);} else {selectModle(mode);}return 1;}

以上经过定制后的代码。代码逻辑更加复杂。因为要支持,夜视和微距摄像头效果。还要支持前摄。

再调用selectModle方法

selectModle(int mode) 
private int selectModle(int mode) {
//        if (!isVideoModel) {
//            if (mCurrentSceneMode.mode == mSceneCameraIds.get(mode).mode) {
//                return -1;
//            }
//        }showCameraDevice();setCameraModeSwitcherAllowed(false);setNextSceneMode(mode);SceneModule nextSceneMode = mSceneCameraIds.get(mode);String value = mSettingsManager.getValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE);if (showLog)Log.e(TAG, " =============== current Mode is :::  " + mCurrentSceneMode.mode.ordinal());if (value != null && value.equals("front") &&(nextSceneMode.mode == CameraMode.RTB|| nextSceneMode.mode == CameraMode.SAT|| nextSceneMode.mode == CameraMode.PRO_MODE)) {if (showLog)Log.e(TAG, " selectModle begin set value KEY_FRONT_REAR_SWITCHER_VALUE  rear ==========   mode:: " + mode);mSettingsManager.setValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE, "rear");} else {if (showLog) Log.e(TAG, " restartAll ==========   mode:: " + mode);restartAll();}updateZoomSeekBarVisible();return 1;}

再调用 restartAll方法

 public void restartAll() {showCameraDevice();int nextCameraId = getNextScreneModeId(mNextModeIndex);CURRENT_ID = getMainCameraId();Log.d(TAG, "restart all CURRENT_ID :" + CURRENT_ID + " nextCameraId :" + nextCameraId);if (CURRENT_ID == nextCameraId && mCameraDevice[nextCameraId] != null) {mIsCloseCamera = false;} else {mIsCloseCamera = true;}SceneModule nextSceneModule = mSceneCameraIds.get(mNextModeIndex);if (nextSceneModule.mode == CameraMode.DEFAULT|| nextSceneModule.mode == CameraMode.PRO_MODE|| nextSceneModule.mode == CameraMode.HFR) {mIsCloseCamera = true;}if (mCameraDevice[nextCameraId] == null) {if (showLog) Log.e(TAG, "  mCameraDevice[nextCameraId] is null " + nextCameraId);} else {if (showLog) Log.e(TAG, "  mCameraDevice[nextCameraId] is not null " + nextCameraId);}

在restartAll中执行各种Camera的初始化操作。首先要关闭原来的摄像头资源,再打开新的摄像头资源。各种操作都封装在以下几个方法。

onPauseBeforeSuper();
if (showLog) Log.e(TAG, " do onPauseBeforeSuper");
onPauseAfterSuper(false);
if (showLog) Log.e(TAG, " do onPauseAfterSuper false");
reinitSceneMode();
if (showLog) Log.e(TAG, " do reinitSceneMode ");
onResumeBeforeSuper(true);
if (showLog) Log.e(TAG, " do onResumeBeforeSuper ");
onResumeAfterSuper(true);
if (showLog) Log.e(TAG, " do onResumeAfterSuper ");
setRefocusLastTaken(false);
if (showLog) Log.e(TAG, " do setRefocusLastTaken ");

打开摄像头的操作。

onResumeAfterSuper 方法里的
 if (mIsCloseCamera) {Message msg = Message.obtain();msg.what = OPEN_CAMERA;msg.arg1 = mCurrentSceneMode.getCurrentId();Log.d(TAG, "open is " + msg.arg1);if (mCameraHandler != null) {mCameraHandler.sendMessage(msg);}}

对应Handle的操作

private class MyCameraHandler extends Handler {public MyCameraHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {int id = msg.arg1;switch (msg.what) {case OPEN_CAMERA:openCamera(id);break;case CANCEL_TOUCH_FOCUS:cancelTouchFocus(id);break;}}}

执行openCamra操作:

private void openCamera(int id) {if (mPaused) {return;}if (showLog) Log.e(TAG, "openCamera  1111 " + id);CameraManager manager;try {manager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);mCameraId[id] = manager.getCameraIdList()[id];if (!mCameraOpenCloseLock.tryAcquire(5000, TimeUnit.MILLISECONDS)) {Log.d(TAG, "Time out waiting to lock camera opening.");throw new RuntimeException("Time out waiting to lock camera opening");}manager.openCamera(mCameraId[id], mStateCallback, mCameraHandler);} catch (CameraAccessException e) {e.printStackTrace();if (showLog) Log.d(TAG, "openCamera CameraAccessException  2222" + id);} catch (InterruptedException e) {e.printStackTrace();if (showLog) Log.d(TAG, "openCamera InterruptedException  3333 " + id);} catch (Exception e) {e.printStackTrace();if (showLog) Log.d(TAG, "openCamera Exception  44444 " + id);}if (showLog) Log.d(TAG, "openCamera  end  55555 " + id);}

回调mStateCallback 操作。

private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {@Overridepublic void onOpened(CameraDevice cameraDevice) {int id = Integer.parseInt(cameraDevice.getId());Log.d(TAG, "onOpened " + id);mCameraOpenCloseLock.release();if (mPaused) {return;}showCameraDevice();if (showLog)Log.e(TAG, "mStateCallback  onOpened  ========== id:: " + id);mCameraDevice[id] = cameraDevice;mCameraOpened[id] = true;if (isBackCamera() && getCameraMode() == DUAL_MODE && id == BAYER_ID) {Message msg = mCameraHandler.obtainMessage(OPEN_CAMERA, MONO_ID, 0);mCameraHandler.sendMessage(msg);} else {mCamerasOpened = true;if (showLog)Log.e(TAG, "mStateCallback  onOpened  ========== mCamerasOpened:: " + mCamerasOpened);mActivity.runOnUiThread(new Runnable() {@Overridepublic void run() {if (showLog)Log.e(TAG, "mStateCallback  onOpened  ========== mUI.onCameraOpened:: ");mUI.onCameraOpened(mCurrentSceneMode.getCurrentId());if (showLog)Log.e(TAG, "mStateCallback  onOpened  ========== mUI.onCameraOpened:: end ");}});showCameraDevice();createSessions();}}

注意 mCameraDevice[id] = cameraDevice; 和   mCameraOpened[id] = true;  有几个摄像头就有几个mCameraDevice。id就是CameraId,一般就是其下标。

同样会有一个非常重要的函数 createSessions() ,有了 CameraDevice就要创建 CaptureSeesion。

private void createSessions() {if (PersistUtil.isTraceEnable())Trace.beginSection("createSessions");if (mPaused || !mCamerasOpened || mTempHoldVideoInVideoIntent) return;int cameraId = mCurrentSceneMode.getCurrentId();if (showLog)Log.e(TAG, "createSessions : Current SceneMode is ==== " + mCurrentSceneMode.mode);Log.e(TAG, "createSessions : Current cameraId is ===== " + cameraId);showCameraDevice();switch (mCurrentSceneMode.mode) {case VIDEO:case VIDEO_NIGHT:case VIDEO_MACRO:case NIGHT:createSessionForVideo(cameraId);break;case HFR:if (!HFR_RATE.equals("")) {mSettingsManager.setValue(SettingsManager.KEY_VIDEO_HIGH_FRAME_RATE, HFR_RATE);}createSessionForVideo(cameraId);break;default:createSession(cameraId);}if (PersistUtil.isTraceEnable())Trace.endSection();}

对应的会执行2个方法,一个是创建Camera的Session  createSession(cameraId)  一个是创建Video的Session  createSessionForVideo(cameraId)

createSession()

if (mChosenImageFormat == ImageFormat.YUV_420_888 || mChosenImageFormat == ImageFormat.PRIVATE) {if (mPostProcessor.isZSLEnabled()) {mPreviewRequestBuilder[id].addTarget(mImageReader[id].getSurface());list.add(mPostProcessor.getZSLReprocessImageReader().getSurface());if (mSaveRaw) {mPreviewRequestBuilder[id].addTarget(mRawImageReader[id].getSurface());}mCameraDevice[id].createReprocessableCaptureSession(new InputConfiguration(mImageReader[id].getWidth(),mImageReader[id].getHeight(), mImageReader[id].getImageFormat()), list, captureSessionCallback, mCameraHandler);} else {if (mSettingsManager.isHeifWriterEncoding() && outputConfigurations != null) {mCameraDevice[id].createCaptureSessionByOutputConfigurations(outputConfigurations,captureSessionCallback, mCameraHandler);} else {mCameraDevice[id].createCaptureSession(list, captureSessionCallback, mCameraHandler);}}} else {outputConfigurations = null;if (ApiHelper.isAndroidPOrHigher() && outputConfigurations != null) {Log.i(TAG, "list size:" + list.size());Log.i(TAG, "create session 111 ");createCameraSessionWithSessionConfiguration(id, outputConfigurations,captureSessionCallback, mCameraHandler, mPreviewRequestBuilder[id]);//                        mCameraDevice[id].createCaptureSession(list, captureSessionCallback, mCameraHandler);} else {Log.i(TAG, "create session 222 ");mCameraDevice[id].createCaptureSession(list, captureSessionCallback, mCameraHandler);}

 captureSessionCallback 的操作

CameraCaptureSession.StateCallback captureSessionCallback =new CameraCaptureSession.StateCallback() {@Overridepublic void onConfigured(CameraCaptureSession cameraCaptureSession) {if (mPaused || null == mCameraDevice[id] ||cameraCaptureSession == null) {return;}Log.i(TAG, "cameracapturesession - onConfigured " + id);setCameraModeSwitcherAllowed(true);// When the session is ready, we start displaying the preview.mCaptureSession[id] = cameraCaptureSession;if (id == getMainCameraId()) {mCurrentSession = cameraCaptureSession;}initializePreviewConfiguration(id);setDisplayOrientation();updateFaceDetection();mFirstPreviewLoaded = false;try {if (isBackCamera() && getCameraMode() == DUAL_MODE) {linkBayerMono(id);mIsLinked = true;}// Finally, we start displaying the camera preview.// for cases where we are in dual mode with mono preview off,// don't set repeating request for monoif (mCaptureSession[id] == null) {return;}
//                                if (id == NIGHT_CAMRA_ID) { //Night模式
//                                    mPreviewRequestBuilder[id].set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
//                                }if (id == MONO_ID && !canStartMonoPreview()&& getCameraMode() == DUAL_MODE) {mCaptureSession[id].capture(mPreviewRequestBuilder[id].build(), mCaptureCallback, mCameraHandler);} else {if (id == NIGHT_CAMRA_ID) { //Night模式mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
//                                        mPreviewRequestBuilder[id].set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);Log.d(TAG, "createSession : mPreviewRequestBuilder FLASH_MODE_TORCH ===== ");}mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id].build(), mCaptureCallback, mCameraHandler);}if (mIntentMode == INTENT_MODE_STILL_IMAGE_CAMERA &&mIsVoiceTakePhote) {mHandler.sendEmptyMessageDelayed(VOICE_INTERACTION_CAPTURE, 500);}if (isClearSightOn()) {ClearSightImageProcessor.getInstance().onCaptureSessionConfigured(id == BAYER_ID, cameraCaptureSession);} else if (mChosenImageFormat == ImageFormat.PRIVATE && id == getMainCameraId()) {mPostProcessor.onSessionConfigured(mCameraDevice[id], mCaptureSession[id]);}} catch (CameraAccessException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}mCurrentSessionClosed = false;}@Overridepublic void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {if (showLog)Log.e(TAG, "cameracapturesession - onConfigureFailed " + id);setCameraModeSwitcherAllowed(true);if (mActivity.isFinishing()) {return;}
//                            Toast.makeText(mActivity, "Camera Initialization Failed",
//                                    Toast.LENGTH_SHORT).show();}@Overridepublic void onClosed(CameraCaptureSession session) {Log.d(TAG, "cameracapturesession - onClosed");setCameraModeSwitcherAllowed(true);}};

createSessionForVideo()

 if (showLog)Log.e(TAG, "createSessionForVideo   66666666666666 ");if (isHighSpeedRateCapture()) {int optionMode = isSSMEnabled() ? STREAM_CONFIG_SSM : SESSION_HIGH_SPEED;if (showLog)Log.e("TAG", " buildConstrainedCameraSession in ");buildConstrainedCameraSession(mCameraDevice[cameraId], optionMode,surfaces, mSessionListener, mCameraHandler, mVideoRecordRequestBuilder);if (showLog)Log.e(TAG, "createSessionForVideo    77777777777777777");} else {if (showLog)Log.e("TAG", " configureCameraSessionWithParameters in  cameraId :: " + cameraId);configureCameraSessionWithParameters(cameraId, surfaces,mSessionListener, mCameraHandler, mVideoRecordRequestBuilder);if (showLog)Log.e(TAG, "createSessionForVideo    888888888888");}

创建CameraSession和VideoSession的主要区别。

CameraSession 使用了 mVideoRecordRequestBuilder 和  mPreviewRequestBuilder。
VideoSession 使用了 mVideoPreviewSurface 和 mMediaRecorderSurface。

CameraSession 通过拍照操作,来使用ImageReader获取图片数据。对应CameraSession有ImageReader实现的地方。

 mCurrentSession.setRepeatingRequest(mVideoRecordRequestBuilder.build(),mCaptureCallback, mCameraHandler);

执行以上操作后,就可以预览看到的内容了。

对应的,还有关闭Camera的操作。

closeCamera()
/*** Closes the current {@link CameraDevice}.*/private void closeCamera() {Log.d(TAG, "closeCamera ============== begin");closeProcessors();/* no need to set this in the callback and handle asynchronously. This is the samereason as why we release the semaphore here, not in camera close callback functionas we don't have to protect the case where camera open() gets called during cameraclose(). The low level framework/HAL handles the synchronization for open()happens after close() */try {// Close camera starting with AUX firstfor (int i = MAX_NUM_CAM - 1; i >= 0; i--) {if (null != mCameraDevice[i]) {try {if (!mCameraOpenCloseLock.tryAcquire(2000, TimeUnit.MILLISECONDS)) {Log.d(TAG, "Time out waiting to lock camera closing.");
//                            throw new RuntimeException("Time out waiting to lock camera closing");}} catch (Exception e) {mCameraOpenCloseLock.release();e.printStackTrace();}Log.d(TAG, "Closing camera: " + mCameraDevice[i].getId());// session was closed here if intentMode is INTENT_MODE_VIDEOif (mIntentMode != INTENT_MODE_VIDEO) {try {if (isAbortCapturesEnable() && mCaptureSession[i] != null) {mCaptureSession[i].abortCaptures();Log.d(TAG, "Closing camera call abortCaptures ");}if (isSendRequestAfterFlushEnable() && mCaptureSession[i] != null) {Log.v(TAG, "Closing camera call setRepeatingRequest");mCaptureSession[i].setRepeatingRequest(mPreviewRequestBuilder[i].build(),mCaptureCallback, mCameraHandler);}} catch (IllegalStateException | CameraAccessException e) {e.printStackTrace();}}mCameraDevice[i].close();mCameraDevice[i] = null;mCameraOpened[i] = false;mCaptureSession[i] = null;}}mIsLinked = false;if (null != mMediaRecorder) {mMediaRecorder.release();mMediaRecorder = null;}} catch (RuntimeException e) {mCameraOpenCloseLock.release();
//            throw new RuntimeException("Interrupted while trying to lock camera closing.", e);e.printStackTrace();} catch (Exception e) {e.printStackTrace();} finally {mCurrentSessionClosed = true;mCameraOpenCloseLock.release();}Log.d(TAG, "closeCamera ============== end");}
closeImageReader()的操作
private void closeImageReader() {for (int i = MAX_NUM_CAM - 1; i >= 0; i--) {if (null != mImageReader[i]) {mImageReader[i].close();mImageReader[i] = null;}if (null != mRawImageReader[i]) {mRawImageReader[i].close();mRawImageReader[i] = null;}}for (int i = mYUVCount - 1; i >= 0; i--) {if (null != mYUVImageReader[i]) {mYUVImageReader[i].close();mYUVImageReader[i] = null;}}if (null != mVideoSnapshotImageReader) {mVideoSnapshotImageReader.close();mVideoSnapshotImageReader = null;}}

closeProcessors()

private void closeProcessors() {if (mPostProcessor != null) {mPostProcessor.onClose();}if (mFrameProcessor != null) {mFrameProcessor.onClose();}}

closeSessions()

private void closeSessions() {for (int i = MAX_NUM_CAM - 1; i >= 0; i--) {if (null != mCaptureSession[i]) {if (mCamerasOpened) {try {if (mCurrentSession instanceof CameraConstrainedHighSpeedCaptureSession) {List requestList = ((CameraConstrainedHighSpeedCaptureSession)mCurrentSession).createHighSpeedRequestList(mVideoRecordRequestBuilder.build());mCurrentSession.captureBurst(requestList, null, mCameraHandler);} else {mCaptureSession[i].capture(mPreviewRequestBuilder[i].build(), null,mCameraHandler);}} catch (CameraAccessException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}mCaptureSession[i].close();mCaptureSession[i] = null;}}}

以上是Camera的初始化流程,很复杂。这里单纯的是CaptureModule的逻辑。其中还要涉及到

CaptureUI的逻辑交互。

其中主要调用 showRelatedIcons(CaptureModule.CameraMode mode),根据显示模式显示不同的界面。

public void showRelatedIcons(CaptureModule.CameraMode mode) {//common settingsmShutterButton.setVisibility(View.VISIBLE);mFrontBackSwitcher.setVisibility(View.VISIBLE);photoVideoSwitcher.setVisibility(View.INVISIBLE);txt_macro_advice.setVisibility(View.INVISIBLE);mMakeupButton.setVisibility(View.INVISIBLE);mSceneModeSwitcher.setVisibility(View.INVISIBLE);//settings for each modeswitch (mode) {case DEFAULT:mFilterModeSwitcher.setVisibility(View.VISIBLE);mSceneModeSwitcher.setVisibility(View.VISIBLE);mVideoButton.setVisibility(View.INVISIBLE);mMuteButton.setVisibility(View.INVISIBLE);mPauseButton.setVisibility(View.INVISIBLE);break;case RTB:case SAT:mFilterModeSwitcher.setVisibility(View.VISIBLE);mSceneModeSwitcher.setVisibility(View.VISIBLE);mVideoButton.setVisibility(View.INVISIBLE);mFlashButton.setVisibility(View.INVISIBLE);mMuteButton.setVisibility(View.INVISIBLE);mPauseButton.setVisibility(View.INVISIBLE);if (!DEV_LEVEL_ALL) {mFrontBackSwitcher.setVisibility(View.INVISIBLE);}break;case VIDEO:case HFR:mFrontBackSwitcher.setVisibility(View.VISIBLE);photoVideoSwitcher.setVisibility(View.INVISIBLE);mVideoButton.setVisibility(View.VISIBLE);mFilterModeSwitcher.setVisibility(View.VISIBLE);if (mModule.isBackCamera()) {mFlashButton.setVisibility(View.INVISIBLE);} else {mFlashButton.setVisibility(View.VISIBLE);}mShutterButton.setVisibility(View.INVISIBLE);break;case PRO_MODE:mFilterModeSwitcher.setVisibility(View.INVISIBLE);mVideoButton.setVisibility(View.INVISIBLE);mFrontBackSwitcher.setVisibility(View.INVISIBLE);mMuteButton.setVisibility(View.INVISIBLE);mPauseButton.setVisibility(View.INVISIBLE);
//                if (mModule.isBackCamera()) {
//                    mFlashButton.setVisibility(View.VISIBLE);
//                } else {mFlashButton.setVisibility(View.INVISIBLE);
//                }break;case MACRO:mFrontBackSwitcher.setVisibility(View.INVISIBLE);photoVideoSwitcher.setVisibility(View.VISIBLE);((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.video_switch);mVideoButton.setVisibility(View.INVISIBLE);mFilterModeSwitcher.setVisibility(View.INVISIBLE);txt_macro_advice.setVisibility(View.VISIBLE);break;case VIDEO_MACRO:mFrontBackSwitcher.setVisibility(View.INVISIBLE);photoVideoSwitcher.setVisibility(View.VISIBLE);((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.photo_switch);mVideoButton.setVisibility(View.VISIBLE);mFilterModeSwitcher.setVisibility(View.INVISIBLE);mShutterButton.setVisibility(View.INVISIBLE);txt_macro_advice.setVisibility(View.VISIBLE);break;case VIDEO_NIGHT:mFlashButton.setVisibility(View.VISIBLE);mFrontBackSwitcher.setVisibility(View.INVISIBLE);photoVideoSwitcher.setVisibility(View.VISIBLE);((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.photo_switch);mFilterModeSwitcher.setVisibility(View.INVISIBLE);mShutterButton.setVisibility(View.INVISIBLE);mVideoButton.setVisibility(View.VISIBLE);break;case NIGHT:mFlashButton.setVisibility(View.INVISIBLE);mFrontBackSwitcher.setVisibility(View.INVISIBLE);photoVideoSwitcher.setVisibility(View.VISIBLE);((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.video_switch);mVideoButton.setVisibility(View.INVISIBLE);mFilterModeSwitcher.setVisibility(View.INVISIBLE);break;default:break;}String value = mSettingsManager.getValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE);if (value == null) {mFrontBackSwitcher.setVisibility(View.INVISIBLE);}if (mModule.getVideoType() == CaptureModule.VIDEO_DEFAULT || mModule.getCurrenCameraMode() == CaptureModule.CameraMode.HFR) {photoVideoSwitcher.setVisibility(View.INVISIBLE);if (mModule.getCurrenCameraMode() == CaptureModule.CameraMode.HFR) {if (mModule.isBackCamera()) {mFlashButton.setVisibility(View.VISIBLE);} else {mFlashButton.setVisibility(View.INVISIBLE);}}}if (mModule.mMFNREnable && mModule.getMainCameraId() == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) {mFilterModeSwitcher.setVisibility(View.INVISIBLE);}}

源码多读,多多比较思考和跟踪代码的流程。

如何编译 在SnapdragonCamera工程呢?

执行

source  ./build/envsetup.sh

执行

lunch

选择正确的配置

在SnapdragonCamera工程下,执行 ,

mm

编译即可。

执行

adb install -r  ../../../../SnapdragonCamera.apk

安装即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/76335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多线程猜数问题

题目&#xff1a;线程 A 生成随机数&#xff0c;另外两个线程来猜数&#xff0c;线程 A 可以告诉猜的结果是大还是小&#xff0c;两个线程都猜对后&#xff0c;游戏结束&#xff0c;编写代码完成。 一、Semaphore 多个线程可以同时操作同一信号量&#xff0c;由此实现线程同步…

seq2seq

理解 transformer 中的 encoder decoder 详细的 transformer 教程见&#xff1a;【极速版 – 大模型入门到进阶】Transformer 文章目录 &#x1f30a; Encoder: 给一排向量输出另外一排向量&#x1f30a; Encoder vs. Decoder: multi-head attention vs. masked multi-head at…

Proxmox pct 部署ubuntu

pct 前言 PCT(Proxmox Container Tool)是 PVE 中用于管理 Linux 容器(LXC)的命令行工具。通过 PCT,用户可以执行各种容器管理任务,例如创建新的容器、启动和停止容器、更新容器、安装软件包、导出和导入容器等。PCT 提供了与 Web 界面相同的功能,但通过命令行进行操作,…

Google Play关键字优化:关键排名因素与实战策略

如果您准备发布应用程序或开始专注于关键字优化&#xff0c;您可能想知道如何向Google Play上的应用程序添加关键字。Google Play上的搜索量和排名与App Store不同&#xff0c;而且被索引排名的关键字也不同。在此文中&#xff0c;我们将确定Google Play上的关键排名因素&#…

Kafka延迟队列实现分级重试

技术方案 方案背景 Kafka队列消息消费处理过程中&#xff0c;发生处理异常&#xff0c;需要实现重试机制&#xff0c;并基于重试次数实现不同延迟时间重试方案。 方案介绍 通过实现Kafka延迟队列来实现消息重试机制。 目标&#xff1a; 支持所有业务场景的延迟重试支持多…

Maven核心配置文件深度解析:pom.xml完全指南

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、全栈领域优质创作者、高级开发工程师、高级信息系统项目管理师、系统架构师&#xff0c;数学与应用数学专业&#xff0c;10年以上多种混合语言开发经验&#xff0c;从事DICOM医学影像开发领域多年&#xff0c;熟悉DICOM协议及…

MSTP多域生成树

协议信息 MSTP 兼容 STP 和 RSTP&#xff0c;既可以快速收敛&#xff0c;又提供了数据转发的多个冗余路径&#xff0c;在数据转发过程中实现 VLAN 数据的负载均衡。 MSTP 可以将一个或多个 VLAN 映射到一个 Instance&#xff08;实例&#xff09;&#xff08;一个或多个 VLAN…

MQTT 服务器(emqx)搭建及使用(一)

一. EMQX 服务器搭建 1.下载EMQX 下载链接&#xff1a;Windows | EMQX 文档 官方手册 2.下载内容解压至盘符根目录 3.进入bin文件夹&#xff0c;在地址栏输入cmd 4.依次输入下面命令安装服务 .\emqx.cmd install .\emqx.cmd console 5.设置自启动 创建批处理文件&#x…

在Thinkphp中使用JWT 包括JWT是什么,JWT的优势

首先了解一下什么是JWT JWT 是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在各方之间以 JSON 对象形式安全传输信息4。其核心特点包括&#xff1a; 结构&#xff1a;由三部分组成&#xff08;Header、Payload、Signature&#xff09;&#xff0c;通过点号…

hackmyvn-casino

arp-scan -l nmap -sS -v 192.168.255.205 目录扫描 dirsearch -u http://192.168.255.205/ -e * gobuster dir -u http://192.168.255.205 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php -b 301,401,403,404 80端口 随便注册一个账号 玩游戏时的…

图表配置表增加分析指标字段

在设计报表图表配置表时&#xff0c;为存储 同比、环比 这类分析指标&#xff0c;建议通过以下方式定义字段结构和命名&#xff1a; 一、字段设计方案 // 配置表示例结构 interface ChartConfig {id: string; // 唯一标识name: string; // 图表…

广州SMT贴片加工厂精密制造工艺解析

内容概要 在电子制造领域&#xff0c;SMT贴片加工技术已成为现代电子产品精密组装的核心环节。广州作为华南地区电子产业的重要枢纽&#xff0c;其SMT贴片加工厂通过融合自动化设备与严格工艺标准&#xff0c;构建起高效可靠的制造体系。 对于电子产品制造商而言&#xff0c;…

RK3568-适配ov5647摄像头

硬件原理图 CAM_GPIO是摄像头电源控制引脚,连接芯片GPIO4_C2 CAM_LEDON是摄像头led灯控制引脚,连接芯片GPIO4_C3编写设备树 / {ext_cam_clk: external-camera-clock {compatible = "fixed-clock";clock-frequency = <25000000>;clock-output-names = "…

关于 @Autowired 和 @Value 使用 private 字段的警告问题分析与解决方案

问题背景 在使用 Spring 框架进行开发时&#xff0c;我们经常会使用 Autowired 和 Value 注解来进行依赖注入和属性值注入。然而&#xff0c;当我们将这些注解应用于 private 字段时&#xff0c;IDE&#xff08;如 IntelliJ IDEA&#xff09;可能会显示警告信息&#xff0c;提…

Flutter 开发环境配置--宇宙级教学!

目录 一、安装环境&#xff08;Windows&#xff09;二、Android 创建Flutter项目三、VSCode 搭建环境四、补充 一、安装环境&#xff08;Windows&#xff09; Flutter SDK 下载 推荐使用中国镜像站点下载 Flutter SDK&#xff0c;速度更快&#xff1a;中国环境 或者从官网下载…

碰一碰发视频网页版本开发的源码搭建指南

引言 在数字化信息快速传播的时代&#xff0c;近场通信&#xff08;NFC&#xff09;技术为信息交互带来了新的便捷方式。通过网页版本实现碰一碰发视频功能&#xff0c;能够让用户在浏览器环境中轻松实现视频分享&#xff0c;拓展了视频传播的途径。本文将详细介绍碰一碰发视频…

OMNIWeb 数据介绍

网址&#xff1a;SPDF - OMNIWeb Service 注&#xff1a;OMNI并非特定缩写&#xff0c;仅表示"多样化"含义。 About the Data All the data to which this interface and its multiple underlying interfaces provide access have in common that they are relevan…

Python学习(二)操作列表

一、列表的遍历 每个缩进的代码行都是循环的一部分&#xff0c;且将针对列表中的每个值都执行一次。因此&#xff0c;可对列表中的每个值执行任意次数的操作。 magicians [alice, david, carolina] for magician in magicians:print(magician)注意&#xff1a; 1、遍历的时…

浅析RAG技术:大语言模型的知识增强之道

浅析RAG技术&#xff1a;大语言模型的知识增强之道 &#x1f3e0; 引言&#xff1a;当生成遇到检索 在人工智能领域&#xff0c;大型语言模型(LLMs)如GPT-4、Llama3等展现出了惊人的文本生成能力&#xff0c;但它们也面临着知识滞后、事实性错误等挑战。Retrieval-Augmented …

Linux Vim 编辑器的使用

Vim 编辑器的使用 一、安装及介绍二、基础操作三、高级功能四、配置与插件 一、安装及介绍 Vim是一款强大且高度可定制的文本编辑器&#xff0c;相当于 Windows 中的记事本。具备命令、插入、底行等多种模式。它可通过简单的键盘命令实现高效的文本编辑、查找替换、分屏操作等…