Android中Camera2 Open打开过程在CameraManager的代码实现流程

发布时间:2024年01月11日

1,CameraManager介绍

CameraManager是Android系统中的一项服务,主要用于检测和打开相机,以及获取相机设备的特性。它是在Android 5.0(API级别21)及以上版本中引入的,属于android.hardware.camera2包。

要获取CameraManager实例,可以通过Context类的getSystemService()方法来实现,参数可以使用Context.CAMERA_SERVICE或CameraManager.class。此外,根据最新的Android系统框架,CameraManager运行在app进程中,与camera server进程和hal进程(provider进程)共同构成了Android的Camera整体框架。

在实际编程过程中,可以直接使用CameraManager类的相关函数,例如:openCamera(), setTorchMode(), startFaceDetection(), stopFaceDetection()等。此外,CameraManager还提供了一些回调函数,如AvailabilityCallback, TorchCallback等,以便于开发者对相机的状态进行监测和控制。

2,CameraCharacteristics介绍

CameraCharacteristics是Android系统中一个专门用于描述相机设备属性的类,其中的属性对于指定的CameraCharacteristics是Android系统中一个专门用于描述相机设备属性的类,其中的属性对于指定的CameraDevice而言是固定的。此类继承自CameraMetadata类,类似于旧版API中的CameraInfo类。

在CameraCharacteristics中,开发者可以找到各种与相机硬件相关的参数和设置,例如:曝光补偿(Exposure compensation)、自动曝光/自动对焦/自动白平衡模式(AE / AF / AWB mode)、自动曝光/自动白平衡范围、最小/最大亮度值、最大帧率等。这些属性的具体数值可以通过CameraManager接口的getCameraCharacteristics方法进行查询。

3,CameraDeviceImpl.java介绍

CameraDeviceImpl.java是Android系统中一个关键的类,它实现了android.hardware.camera2.CameraDevice接口。这个接口代表了一个连接的相机设备,你可以把它看作为相机设备在 java 代码中的表现,类似于旧版API中的Camera类。

CameraDeviceImpl的主要作用是建立与Camera框架的连接,负责管理相机设备的状态和配置信息。为了实现这一目标,它借助JNI层进行Java到C++的转换,到达native层,然后在native层通过实现CameraClient来与Camera系统进行交互。

在实际编程过程中,当调用CameraManager的openCamera()方法时,会返回一个CameraDevice对象。如果成功,该对象就代表了应用程序与相机硬件之间的一个连接。开发者可以通过这个对象的方法和回调来控制相机的各种功能,如拍照、录像等。

4,CameraCaptureSessionImpl.java介绍

CameraCaptureSessionImpl.java是Android系统中一个关键的类,它实现了android.hardware.camera2.CameraCaptureSession接口。这个接口代表了一个与相机设备进行通信的会话,我们可以将其看作为在Java代码中相机设备的表现,类似于旧版API中的Camera类。

CameraCaptureSession的主要作用是用来向相机设备发送获取图像的请求。它主要有setRepeatingRequest()和capture()两种方法。其中,setRepeatingRequest()用于重复请求获取图像数据,常用于预览或连拍;capture()则用于获取一次图像,常用于单张拍照。值得注意的是,CameraCaptureSession是一个抽象类,其直接的实现类为CameraConstrainedHighSpeedCaptureSession。

在实际编程过程中,当调用CameraManager的openCamera()方法时,会返回一个CameraDevice对象。如果成功,该对象就代表了应用程序与相机硬件之间的一个连接。开发者可以通过这个对象的方法和回调来控制相机的各种功能,如拍照、录像等。例如,当需要创建新的CameraCaptureSession时,会先判断当前CameraDevice是否已经存在一个active的CameraCaptureSession对象。如果有的话,就会先关闭这个session对象,然后再创建新的session对象。此外,一旦新的CameraCaptureSession创建完成,App便可以通过它向底层发送CaptureRequest。

5,CaptureRequest.java介绍
CaptureRequest在Android系统中是一个关键的类,主要用于表示对相机底层的捕捉请求。我们可以为预览、拍照等不同的场景创建不同的CaptureRequest,并为其配置各种属性,例如:预览分辨率、预览目标、对焦模式和曝光模式等。

具体来说,一个CaptureRequest包含了两部分内容:Settings和Output Surfaces。Settings部分包含了硬件相关的参数,比如sensor, lens, flash等,以及ISP Processing Pipeline相关参数和3A相关参数。这些参数都是用于告诉Camera底层如何处理某一帧数据的。而Output Surfaces则是指CaptureRequest中带的Surfaces,这些Surfaces必须在创建CameraCaptureSession时使用的Surface List的子集。

在实际编程过程中,可以通过CameraCaptureSession的createCaptureRequest()方法来获取CaptureRequest对象。一旦新的CaptureRequest创建完成,App便可以通过它向底层发送请求以获取图像数据。

7,Camera open在framework中的代码实现
camera open在CameraManager中代码实现过程
1,获取camera的logic ID信息的时候实现如下

public String[] getCameraIdList() {
            String[] cameraIds = null;
            synchronized (mLock) {
                // Try to make sure we have an up-to-date list of camera devices.
                connectCameraServiceLocked();
                cameraIds = extractCameraIdListLocked();
            }
            sortCameraIds(cameraIds);
            return cameraIds;
        }

这里先拿到cameraservice的接口,然后拿到camera的连接状态和ID,如下:

private void connectCameraServiceLocked() {
            
            ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
            try {
                CameraStatus[] cameraStatuses = cameraService.addListener(this);
                for (CameraStatus c : cameraStatuses) {
                    onStatusChangedLocked(c.status, c.cameraId);
                }
                mCameraService = cameraService;
            } catch(ServiceSpecificException e) {
                // Unexpected failure
                throw new IllegalStateException("Failed to register a camera service listener", e);
            } catch (RemoteException e) {
                // Camera service is now down, leave mCameraService as null
            }

            
        }

这个将拿到的状态和ID添加到devicestatus表中,如下:

private void onStatusChangedLocked(int status, String id) {
            
            Integer oldStatus;
            if (status == ICameraServiceListener.STATUS_NOT_PRESENT) {
                oldStatus = mDeviceStatus.remove(id);
                mUnavailablePhysicalDevices.remove(id);
            } else {
                oldStatus = mDeviceStatus.put(id, status);
                if (oldStatus == null) {
                    mUnavailablePhysicalDevices.put(id, new ArrayList<String>());
                }
            }

        } // onStatusChangedLocked

如上就可以拿到cameraID。

2,获取camerametadata的代码实现过程,CameraCharacteristics 调用:

public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId)
            throws CameraAccessException {
        
            ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
            
                Size displaySize = getDisplaySize();

                CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
                        mContext.getApplicationInfo().targetSdkVersion);
             
                characteristics = new CameraCharacteristics(info);
            
        return characteristics;
    }

这个拿到cameraservice后直接获取到camerametadata,在封装到CameraCharacteristics。这里就可以通过tagID就看获取到metadata的数据信息。

3,openCamera调用:

public void openCamera(@NonNull String cameraId,
            @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
            throws CameraAccessException {

        openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
                USE_CALLING_UID);
    }
private CameraDevice openCameraDeviceUserAsync(String cameraId,
            CameraDevice.StateCallback callback, Executor executor, final int uid,
            final int oomScoreOffset) throws CameraAccessException {
        CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
        CameraDevice device = null;
        Map<String, CameraCharacteristics> physicalIdsToChars =
                getPhysicalIdToCharsMap(characteristics);
        synchronized (mLock) {

            ICameraDeviceUser cameraUser = null;
            android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                    new android.hardware.camera2.impl.CameraDeviceImpl(
                        cameraId,
                        callback,
                        executor,
                        characteristics,
                        physicalIdsToChars,
                        mContext.getApplicationInfo().targetSdkVersion,
                        mContext);

            ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();

            try {
                ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
                if (cameraService == null) {
                    throw new ServiceSpecificException(
                        ICameraService.ERROR_DISCONNECTED,
                        "Camera service is currently unavailable");
                }
                cameraUser = cameraService.connectDevice(callbacks, cameraId,
                    mContext.getOpPackageName(),  mContext.getAttributionTag(), uid,
                    oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion);
            } deviceImpl.setRemoteDevice(cameraUser);
            device = deviceImpl;
        }

        return device;
    }

这个先创建了CameraDeviceImpl对象,接着调用cameraservice的connectDevice拿到service端的cameradevice接口。然后将这个接口设置给CameraDeviceImpl,如下:

public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
        synchronized(mInterfaceLock) {
            // TODO: Move from decorator to direct binder-mediated exceptions
            // If setRemoteFailure already called, do nothing
            if (mInError) return;

            mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);

            mDeviceExecutor.execute(mCallOnOpened);
            mDeviceExecutor.execute(mCallOnUnconfigured);
        }
    }

这里就回调app callback,这样app端就拿到cameradevice这个接口了。如下:

private final Runnable mCallOnOpened = new Runnable() {
        @Override
        public void run() {
            
            mDeviceCallback.onOpened(CameraDeviceImpl.this);
        }
    };

4,createCaptureSession调用:在app拿到cameradevice后就可以创建capturesession了,如下:

private void createCaptureSessionInternal(InputConfiguration inputConfig,
            List<OutputConfiguration> outputConfigurations,
            CameraCaptureSession.StateCallback callback, Executor executor,
            int operatingMode, CaptureRequest sessionParams) throws CameraAccessException {
      
                newSession = new CameraCaptureSessionImpl(mNextSessionId++, input,
                        callback, executor, this, mDeviceExecutor, configureSuccess);
            
            // TODO: wait until current session closes, then create the new session
            mCurrentSession = newSession;

            mSessionStateCallback = mCurrentSession.getDeviceStateCallback();
        }
    }

这里就是创建CameraCaptureSession,如下:

CameraCaptureSessionImpl(int id, Surface input,
            CameraCaptureSession.StateCallback callback, Executor stateExecutor,
            android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
            Executor deviceStateExecutor, boolean configureSuccess) {
       
        mStateCallback = createUserStateCallbackProxy(mStateExecutor, callback);

        if (configureSuccess) {
            mStateCallback.onConfigured(this);
            if (DEBUG) Log.v(TAG, mIdString + "Created session successfully");
            mConfigureSuccess = true;
        } else {
            mStateCallback.onConfigureFailed(this);
            mClosed = true; // do not fire any other callbacks, do not allow any other work
            Log.e(TAG, mIdString + "Failed to create capture session; configuration failed");
            mConfigureSuccess = false;
        }
    }

到这里app端就可以获取到capturesession了。

5,CaptureRequest调用:这块就是操作camerametadata相关接口,如下:

public CaptureRequest.Builder createCaptureRequest(int templateType)
            throws CameraAccessException {
        synchronized(mInterfaceLock) {
            checkIfCameraClosedOrInError();

            CameraMetadataNative templatedRequest = null;

            templatedRequest = mRemoteDevice.createDefaultRequest(templateType);

            CaptureRequest.Builder builder = new CaptureRequest.Builder(
                    templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE,
                    getId(), /*physicalCameraIdSet*/ null);

            return builder;
        }
    }
public Builder(CameraMetadataNative template, boolean reprocess,
                int reprocessableSessionId, String logicalCameraId,
                Set<String> physicalCameraIdSet) {
            mRequest = new CaptureRequest(template, reprocess, reprocessableSessionId,
                    logicalCameraId, physicalCameraIdSet);
        }

capturerequest主要是camerametadata相关操作。

6,camera preview request调用:

public int setRepeatingBurst(List<CaptureRequest> requests,
            CaptureCallback callback, Handler handler) throws CameraAccessException {
        
            return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests,
                    createCaptureCallbackProxy(handler, callback), mDeviceExecutor));
        }
    }
public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback callback,
            Executor executor) throws CameraAccessException {
       
        return submitCaptureRequest(requests, callback, executor, /*streaming*/true);
    }
private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback,
            Executor executor, boolean repeating) throws CameraAccessException {

            CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]);
            
            requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating);
            
    }

这块就是把capturerequest传递到cameraservice端的cameradevice中,进行下一步的处理。
到这来整个open过程在framework里面cameramanager的调用过程就实现了。

7,总结框架

CameraManager CameraDeviceImpl cameraService app CameraCaptureSessionImpl CaptureRequest.Builder mRemoteDevice new CameraDeviceImpl connectDevice mCallOnOpened createCaptureSessionInternal createCaptureRequest submitRequestList CameraManager CameraDeviceImpl cameraService app CameraCaptureSessionImpl CaptureRequest.Builder mRemoteDevice

你的鼓励将是我创作的最大动力
在这里插入图片描述

文章来源:https://blog.csdn.net/jiangchaobing_2017/article/details/135519073
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。