Andriod Camera之Open Camera

前言       

       打开相机的第一步便是在APP里去调用openCamera(),去打开指定的Camera设备(通过Device id指定),并建立起连接。APP通过openCamera()调用成功后,可以获取到一个已经初始化过的CameraDeviceImp,它表示一个已经打开的Camera设备,后续APP便可以通过CameraDeviceImp去执行各种操作,以控制相机的各种行为。


主要流程

           下面简单地介绍一些openCamera的流程,希望可以对整个的过程有一个大概的了解, openCamera()的主要flow如下图所示

       可以将这个过程划分为3个部分来看,分别是App、native framework、Hal层,接下来也将从这三个部分去分析openCamera()这个过程。 

一、App部分:

        对应上图中CameraManager.java这部分。App首先要获取到CameraManager服务,然后才可以查询到某个CameraId所对应的相机设备信息,再调用openCamera(),去打开指定CameraId所对应的相机设备。前面的flow就是:

    ——> openCamera(String cameraId,CameraDevice.StateCallback callback,......)
    ——> openCameraForUid(String cameraId,CameraDevice.StateCallback callback,......)
    ——> openCameraDeviceUserAsync(String cameraId,CameraDevice.StateCallback callback,......)

        其中的两个参数:cameraId就不必多说了^v^;这个callback参数是一个回调对象,用来接收这个CameraDevice的状态变化情况的,这个回调对象里有提供几个回调函数(onOpened()、onClosed()、onError()、onDisconnected()),APP必须要去实作这些方法,以便于底层的CameraDevice切到对应的状态后,APP能够做出对应的反应。前面两个函数的逻辑比较简单,下面主要看一下openCameraDeviceUserAsync()里做的事情:

     1、利用获取的相机设备信息创建CameraDeviceImpl实例

               ---------> CameraDeviceImpl deviceImpl=new CameraDeviceImpl();

          但是这个deviceImpl里还有一个重要的成员-------->mRemoteDevice 没有初始化,它是这个deviceImpl的远端服务,其实后续APP对deviceImpl的操作都会转化为对这个远端服务mRemoteDevice的操作,而这个远端服务需要通过CameraService这个系统服务去获取到。

     2、调用远程CameraService获取当前相机的远程服务

              ----------> cameraUser=CameraService.connectDevice();

    3、将获取到的远程服务设置到CameraDeviceImpl实例中

              ----------> deviceImpl.setRemoteDevice(cameraUser)

           这里面最终会通过前面APP传下来的回调函数---> callback.onOpened() ,返回这个CameraDeviceImpl

   4、返回CameraDeviceImpl实例,即deviceImpl,它代表一个已经打开的相机设备。

         所以是App调用的CameraManager的openCamera()方法,调用成功后,在回调函数里可以得到一个CameraDeviceImpl的实例,这个实例里包含其对应的远端服务。接下来看一看这其中所说的“调用远程CameraService获取当前相机的远程服务”是在做什么。


二、native framework

       在App部分其中有一步叫做:调用远程CameraService获取当前相机的远程服务。这一步其实是通过AIDL调用到了CameraService::connectDevice(),这里就进入了native framework层,这个过程对应于前面流程图中CameraService.cpp到CameraProviderManager.cpp的这一部分 ,接下来看看这个过程中经历的事情。这里面有涉及到几个class:CameraService、CameraDeviceClient、Camera2ClientBase、Camera3Device、CameraProviderManager,它们之间的关系如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6I-c6bihVVA=,size_20,color_FFFFFF,t_70,g_se,x_16

  通过这部分的flow,我们可以看到在native framework里面做的事情大概可以总结如下:

   1、handleEvictionsEvicted

         处理相机的抢占机制,可以参考:Android Camera抢占机制——handleEvictionsLocked()

   2、创建CameraDeviceClient对象,并初始化

       即CameraDeviceClient::initialize()。这里面会调用到Camera2ClientBase::initialize(),而Camera3Device继承自Camera2ClientBase,从前面关系图里可以看出,其实可以看出来Camera3Device就是CameraDeviceClient的成员变量。所以这里面其实是会调用到Camera3Device::initialize()。

   3、初始化Camera3Device

       即Camera3Device::initialize()。这里面最重要的一步便是CameraProviderManager::openSession(),接下来看看这个openSession()里面做的事情:

  •  findDeviceInfoLocked()

            根据CameraDevice的版本,从所有Provider中,找到对应的DeviceInfo。这些信息是在CameraService起来时已经保存好的,可以参考Android Camera之CameraServer的启动过程

  •  startProviderInterface()

          根据刚刚deviceInfo中对应的provider的信息,获取到对应CameraProvider服务。

  •  startDeviceInterface()

         通过CameraProvider的getCameraDeviceInterface_V3_x()实例化一个CameraDevice。这一步是通过HIDL调用到了Hal层,这个CameraDevice是Hal层实作的,和前面APP部分的CameraDevice有所不同,也有所联系

  •    interface->open()

        这个interface就是前面startDeviceInterface()得到的CameraDevice,这里是要通过CameraDevicce::open()创建一个有效的CameraDeviceSession。这一步也是通过HIDL调用到了HAL层。

      需要说一下的是,这个函数有带一个参数给Hal层:即ICameraDeviceCallback。再向前追溯,可以看到是Camera3Device,调用CameraProviderManager::openSession()时传下来的,这个参数是this,其实就是Camera3Device,其实Camera3Device也是自ICameraDeviceCallback继承下来的,这个类可以看这里定义的接口:

/hardware/interfaces/camera/device/3.x/ICameraDeviceCallback.hal 

      里面有两个重要的方法:processCaptureResult()和notify()

再根据CameraDeviceSession构造HalInterface

       将CameraDeviceSession赋值给HalInterface::mHidlSession_3_X

   4 、创建FrameProcessor

       即创建CameraDeviceClient::mFrameProcessor,并将CameraDeviceClient注册进mRangeListener中,因为CameraDeviceClient继承自FilteredListener。关于这个FrameProcessor的作用会在后面的文章中介绍,这里暂时就先跳过了。只需要知道CameraDeviceClient在初始化的时候有建立一个FrameProcessor线程就好了。

   5、返回CameraDeviceClient对象给CameraManager.

         所以到这里后,可以看出App openCamera()中,CameraDeviceImpl的RemoteDevice其实就是CameraService的CameraDeviceClient,后面App里对CameraDeviceImpl的操作,会通过AIDL调用到CameraService里的CameraDeviceClient。


三 、Hal层

        Android在hardware/interfaces/camera下定义了几个hidl interface:ICameraProvider、ICameraDevice和ICameraDeviceSession。Hal层必须要去实作这些Interface, 这部分是由各个厂商(比如MTK、高通)去实作的,因此不同厂商的平台在这部分是会有差异的,这里就不细讲了。

         前面在openSession()时,getCameraDeviceInterface_V3_x()和CameraDevice::open()会通过Hidl调用到由HAL层对应的实作里。

      getCameraDeviceInterface_V3_x()这个接口通过HIDL调用到由Hal层实作的getCameraDeviceInterface_V3_x()函数里面去获取到一个实例化的Cameradevice;CameraDevice::open(),也会通过HIDL调用到HAL层实做的CameraDevice::open()去创建一个实例化的CameraDeviceSession

getCameraDeviceInterface_V3_x()定义在:hardware/interfaces/camera/provider/2.4/ICameraProvider.hal

CameraDevice::open()定义在:hardware/interfaces/camera/device/3.2/ICameraDevice.hal


 总结

            当APP调用openCamera(),会通AIDL调用到CameraService里面,CameraService又会通过HIDL去获取到HAL层实作的CameraDevice和CameraDeviceSession,并保存在Camera3Device中;APP也会在回调函数里得到一个CameraDeviceImpl实例,这个实例中远程服务(即 RemoteDevice)其实就是CameraSevice中的CameraDeviceClient,前面所说的Camera3Device正是CameraDeviceClient的数据成员,这样就建立起了从APP、framework和HAL层之间的联系,如下图所示:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5Y-v54ix55qE5aSn5Y-v54ixaGlhaGlhaGlh,size_20,color_FFFFFF,t_70,g_se,x_16

 Google的这张图更全面一些,也更清晰明了 

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjQ2MzQ4Mg==,size_16,color_FFFFFF,t_70

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,很高兴回答你关于Android开发中的相机(Camera)学习问题。在Android开发中,相机是一个非常常见的模块,因此学习如何使用相机是非常重要的一部分。 首先,你需要在AndroidManifest.xml中声明相机权限: ```xml <uses-permission android:name="android.permission.CAMERA" /> ``` 接着,在你的Activity中,你需要获取相机的实例并启动预览: ```java private Camera mCamera; private void startCameraPreview() { try { mCamera = Camera.open(); Camera.Parameters parameters = mCamera.getParameters(); // 设置相关参数 mCamera.setParameters(parameters); // 设置预览SurfaceView mCamera.setPreviewDisplay(mSurfaceView.getHolder()); // 开启预览 mCamera.startPreview(); } catch (IOException e) { Log.e(TAG, "Error while setting camera preview", e); } } ``` 上面的代码中,我们首先获取系统相机的实例,然后获取相机参数,并设置相关参数。接着,我们将预览SurfaceView和相机绑定,最后开启预览。 当你完成相机预览后,你就可以使用相机拍照了。以下是拍照的示例代码: ```java private void takePicture() { mCamera.takePicture(null, null, new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // 处理拍照后的数据 } }); } ``` 当你调用`takePicture()`方法时,相机会拍摄一张照片,并通过PictureCallback返回照片的数据。你可以将数据保存到文件中,或者进行进一步的处理,比如将照片显示在ImageView中。 以上就是Android开发中相机的基本使用方法。当然,相机的功能还有很多,你可以尝试更多的参数设置和拍照处理,来发掘相机的更多特性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值