Android Camera 打开预览流程分析(一)--打开camera的SDK流程

	Android系统应用场景中,Camera的使用场景变得越来越重要,在手机端不管是牌照美颜,
           还是拍小视频上传小视频平台。在其他领域,如车载,倒车视频,
           360全景影像也同样会用到Camera接口。那我们这个系列就拿Camera来分析了,
           我们主要就是android camera流程进行一个分析,对于照片美颜,
           视频上传这些就不在我们关注的范围了。那我们分析还是带着问题去分析吧,
           Camera就如何打开的,现在一个手机上少则2,3个摄像头,多着5~6个摄像头,
           那如何去打开想要的那个摄像头呢。另一方面的问题就是Camera预览窗口的图像是
           如何传到我们打开的那个窗口的,经过了那些流程呢。我们后续的分析文章就围绕着
           两个方面来展开分析。
	## Camera的分层框架  (等分析完这两个流程,应该就可以画出这个框图了)
	HAL层服务:frameworks/hardware/interfaces/cameraservice
	FW层服务: frameworks/av/services/camera/libcameraservice
	FW层SDK: frameworks/base/core/java/android/hardware/camera(2)

Camera的打开

我们就从android 标准的camera open接口开始撸:

open() ------framework/base/core/java/android/hardware/camera.java
    new Camera(int id)
        cameraInitVersion(int cameraId, int halVersion)
            native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName)
                android_hardware_Camera_native_setup(..., jint cameraId, jint halVersion, jstring clientPackageName) 
-----framework/base/core/jni/android_hardware_camera.cpp

Camera从open接口开始分析,直接就调用到JNI中去了,我们接着从JNI中继续分析:

static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
...
		//调用camera的connect接口 打开camera
        camera = Camera::connect(cameraId, clientName,
                Camera::USE_CALLING_UID, Camera::USE_CALLING_PID);
...
    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
    context->incStrong((void*)android_hardware_Camera_native_setup);
    camera->setListener(context);

    // save context in opaque field
    env->SetLongField(thiz, fields.context, (jlong)context.get());

    // Update default display orientation in case the sensor is reverse-landscape
    CameraInfo cameraInfo;
    //获取camera的信息
    status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);         
...           

从JNI的native_setup中可以看到,调用了camera的connect接口,成功打开之后就可以获取camera的信息了. 再往下分析时,发现很多不对劲的地方,网上去百度了下,发现我们现在分析的camera 接口是Camera 最早的接口了,现在基本被弃用了,现在基本都是是使用Camera2的API接口,Camera2 与Camera 接口还是有挺大区别。Camera接口都被弃用了,我们就直接上手分析Camera2的接口吧。

Camera2 的接口
上面有说到camera 已经被弃用了,都推荐使用camera2的接口。我们就直接再从camera2 开始分析。camer2中有好些类:
CameraManager
相机系统服务,用于管理和连接相机设备
CameraDevice
相机设备类,和Camear1中的Camera类似
CameraCharacteristics
用于获取相机信息,内部携带大量的相机信息,包括摄像头的正反等,和Camear1中的Camera.Parameters同等功能。
CameraRequest
相机捕获图像的设置请求,包括sensor, flashlight等
CameraCaptureSession
请求抓去相机图像帧的会话,会话会创建一个通道,一个CameraDevice只能打开一个CameraCaptureSession.源头是Target, Target可以是Preview, 也可以是ImageReader

打开相机
 

public void Open(){
	CameraManager cameraManager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
	for(String cameraId: cameraManager.getCameraIdList()){
		CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
		//打开相机,第一个参数:哪个摄像头,第二个参数mStateCallback为相机打开的回调接口,第三个参数用来确定callback在哪个线程中执行,为null的话,在当前线程中执行
		cameraManager.openCamera(cameraId, mStateCallback, null)
	}
}

private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback(){
	public void onOpened(CameraDevice camera){
		mCameraDevice = camera;
		...
	}
	
	public void onDisconnected(CameraDevice camera){
		camera.close();
		mCameraDevice = null;
	}

	public void onError(){CameraDevice camera, int error}{
		camera.close();
		mCameraDevice = null;
	}
}

打开Camera时将CameraDevice.StateCallback对象传给openCamera当做参数,在OnOpened的回调中,再把Camera对象传给mCameraDevice, 后面就是用mCameraDevice 来操作。
那我们看看CameraManager.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);
    }
        public void openCameraForUid(@NonNull String cameraId,
            @NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
            int clientUid)
            throws CameraAccessException {
		......
        openCameraDeviceUserAsync(cameraId, callback, executor, clientUid);
    }
private CameraDevice openCameraDeviceUserAsync(String cameraId,
            CameraDevice.StateCallback callback, Executor executor, final int uid)
            throws CameraAccessException {
        CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
        CameraDevice device = null;

        synchronized (mLock) {

            ICameraDeviceUser cameraUser = null;
            //初始化android.hardware.camera2.impl.CameraDeviceImpl
            android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                    new android.hardware.camera2.impl.CameraDeviceImpl(
                        cameraId,
                        callback,
                        executor,
                        characteristics,
                        mContext.getApplicationInfo().targetSdkVersion);
             ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
             
            		//初始化CameraService
					ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
					//CameraService 连接设备
                    cameraUser = cameraService.connectDevice(callbacks, cameraId,
                            mContext.getOpPackageName(), uid);    
            deviceImpl.setRemoteDevice(cameraUser);
            device = deviceImpl;
        }
        return device;
    }

这一步调用就直接调用到CameraService 里去了,与其他服务不同的是,其他服务直接是在SystemServer里的一个服务,CameraService是运行在CameraServer的一个独立进程中的。里面是使用cpp代码写的一个进程。下篇我们继续研究这个CameraService进程。
 

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值