Android Camera fw学习(一)-类之间的关系和作用
2017-06-06 23:29
423 查看
备注:本文基于Android 5.1分析,可能已经过时了,不过里面的原理和现在7.0基本一样。博文为个人看代码笔记,如有问题,请发表意见大家一起学习,进步。后续的博文会沿着下面几步来走,把自己对Camera分析总结一下。
1.简单介绍Camera几大接口类,以及相关类的继承关系(也就当前博文)
2.app->jni->native详细分析open camera操作过程中发生了什么
3.startPreview详细过程分析
4.生产者消费者,bufferqueue模型介绍,以及详细介绍preview buffer的生产消费过程
5.takepicture详细过程分析
6.Recording详细过程分析
7.由添加一个CameraMetadata tag引发的实战分析
8.v4l2 架构详细分析
Android Camera中的类很多,刚开始看的时候,感觉各个类之间的关系相当复杂。不过在学习过Binder后,它们的关系就渐渐浮出水面。在开始学习类之间关系时,我们先从整体上了解Camera在工作时,都有哪些对象在作用。
图一、工作时存在的3个鲜活对象
学过binder之后,我们就会知道服务端和客户端需要实现公共的接口,彼此才能默契的工作,要不然是没法友好沟通的。如上图一我们发现各个代理对象和本地对象都实现了相应的接口,各接口的作用下面做简要介绍。
1.ICameraClient: 这主要是一些消息发送的接口,包括帧可用通知,回调一些信息给client等消息。不过这里要注意的是,BnCameraClient对象其实是在client这端,不在CameraService端。
2.ICamera:camera的一些标准操作接口,比如startpreview,takepicuture,autofocus,所有的操作动作都是用的这一套接口。
3.ICameraService: 链接Camera服务,Camera device,获取Camera数量,Camera硬件信息,视厂角,镜头等信息。
下面分别介绍实现这些接口各个类的关系。
图二、ICameraClient相关类继承关系
看过源代码的同学可能比较好奇,为什么camera类没有继承ICamera类呢,但是camera类中也实现了ICamera接口。其实这里Camera类没有直接继承ICamera接口类,而是直接实现了ICamera的接口,在各个接口中调用ICamera代理对象相应的接口就行了。这里只是打了个幌子。大家看看下面的代码就知道了
上面这些类继承关系,以及模板类的一些信息,如果有些C++基础的同学一看就明白了。如果不明白,最好去看看C++中模板的介绍,再过来看博文会有事半功倍的效果。上面几个类中有几个声明需要我们知道。
1.fnConnectService:指向ICameraService::connect函数指针,这在camera.h文件开始位置已经严重声明了。
2.几个用的比较多的宏,要暂时记在心里
当我们打开Camera时,第一个调用的就是native_setup(),它会找到包名,CameraID,UID宏与CameraService进行链接获取到camera对象。
2.camera对象创建过程
这里我们不做深入追究,后续的博文会深入介绍的。这里connect连接成功后,会有下面几个新对象生成。
(1).camera,显而易见在进行connect之前,就已经new出来一个camera对象了,然后定义TCamCallbacks强引用指针cl,用于conect时传给CameraService的BnCameraClient本地对象(这里的camera对象就是BnCameraClient本地对象)。注意在CameraService代理对象中,通过writeStrongBinder将该BnCameraClient注册到了当前camera客户端进程的binder_proc的refs_by_node链表中,同时会定义一个binder_ref对象传给CameraService中(这里就是匿名binder通信了,会在后续的binder学习中好好分析)。
(2).bnCameraClient 该对象就是上面new出来的camera对象的引用,以匿名binder通信方式,注册给camera client进程中,然后将binder_ref传给mediaServer中的CameraService对象中。
(3).Camera2Client,该对象为本地对象会在CameraService中诞生,引用对象会在connect返回时传给camera对象中ICamera强引用对象mCamera中,如下。
到这个时候,Camera运行需要的主要对象,都创建完毕。
图三、ICamera相关类继承关系
该类是Camera控制的主要接口类,客户端和Service端都会实现ICamera接口类。客户端进程以匿名binder的形式,与mediaServer进程的CameraService进行通信。下面列举一些我个人认为有必要深入了解的接口。
上面我只列举了部分函数,大家可以结合源码看看其它函数都有什么用,反正都是有很大用处的。
图四、ICameraService相关类继承关系
这里是CameraService的继承关系,右侧是我列举的一些个人认为比较重要的函数。ICameraService中总共有12接口,我们只介绍下面几个。
1.简单介绍Camera几大接口类,以及相关类的继承关系(也就当前博文)
2.app->jni->native详细分析open camera操作过程中发生了什么
3.startPreview详细过程分析
4.生产者消费者,bufferqueue模型介绍,以及详细介绍preview buffer的生产消费过程
5.takepicture详细过程分析
6.Recording详细过程分析
7.由添加一个CameraMetadata tag引发的实战分析
8.v4l2 架构详细分析
Android Camera中的类很多,刚开始看的时候,感觉各个类之间的关系相当复杂。不过在学习过Binder后,它们的关系就渐渐浮出水面。在开始学习类之间关系时,我们先从整体上了解Camera在工作时,都有哪些对象在作用。
图一、工作时存在的3个鲜活对象
学过binder之后,我们就会知道服务端和客户端需要实现公共的接口,彼此才能默契的工作,要不然是没法友好沟通的。如上图一我们发现各个代理对象和本地对象都实现了相应的接口,各接口的作用下面做简要介绍。
1.ICameraClient: 这主要是一些消息发送的接口,包括帧可用通知,回调一些信息给client等消息。不过这里要注意的是,BnCameraClient对象其实是在client这端,不在CameraService端。
2.ICamera:camera的一些标准操作接口,比如startpreview,takepicuture,autofocus,所有的操作动作都是用的这一套接口。
3.ICameraService: 链接Camera服务,Camera device,获取Camera数量,Camera硬件信息,视厂角,镜头等信息。
下面分别介绍实现这些接口各个类的关系。
一、ICameraClient接口
1.类关系和一些接口宏说明
继承IcameraClient各类的继承关系如下图所示。图二、ICameraClient相关类继承关系
看过源代码的同学可能比较好奇,为什么camera类没有继承ICamera类呢,但是camera类中也实现了ICamera接口。其实这里Camera类没有直接继承ICamera接口类,而是直接实现了ICamera的接口,在各个接口中调用ICamera代理对象相应的接口就行了。这里只是打了个幌子。大家看看下面的代码就知道了
路径:frameworks/av/include/camera.h //Camera的继承的类,可以看到模板参数就是Camera类。 class Camera : public CameraBase<Camera>, public BnCameraClient { //...... } //路径:frameworks/av/include/cameraBase.h //CameraBase类继承了IBinder::DeathRecipient template <typename TCam, typename TCamTraits = CameraTraits<TCam> > class CameraBase : public IBinder::DeathRecipient { public: //下面几个类型请看下面类的CameraTraits声明 typedef typename TCamTraits::TCamListener TCamListener; //由下面的CameraTraits类可以发现TCamUser就是ICamera的强指针类型。TCamCallbacks就是ICameraClient类型,我们这里留个心眼。 typedef typename TCamTraits::TCamUser TCamUser; typedef typename TCamTraits::TCamCallbacks TCamCallbacks; typedef typename TCamTraits::TCamConnectService TCamConnectService; //...... sp<TCamUser> mCamera; status_t mStatus; sp<TCamListener> mListener; const int mCameraId; typedef CameraBase<TCam> CameraBaseT; }; //CameraTraits该类是已结构体的形式展现出来的,不过在C++中的结构体也是类。可以看到模板参数还是Camera类。 struct CameraTraits<Camera> { //下面声明的几个宏,会在其他地方用到。 typedef CameraListener TCamListener; typedef ICamera TCamUser; typedef ICameraClient TCamCallbacks; typedef status_t (ICameraService::*TCamConnectService)(const sp<ICameraClient>&, int, const String16&, int, /*out*/ sp<ICamera>&); //下面这个静态函数指针,执行的是CameraService类中的Connect函数。 static TCamConnectService fnConnectService; };
上面这些类继承关系,以及模板类的一些信息,如果有些C++基础的同学一看就明白了。如果不明白,最好去看看C++中模板的介绍,再过来看博文会有事半功倍的效果。上面几个类中有几个声明需要我们知道。
1.fnConnectService:指向ICameraService::connect函数指针,这在camera.h文件开始位置已经严重声明了。
CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService = &ICameraService::connect;
2.几个用的比较多的宏,要暂时记在心里
ICamera = TCamUser, ICameraClient = TCamCallbacks, typedef CameraBase<TCam> CameraBaseT;
2.ICameraClient创建过程发生了什么
1.android_hardware_Camera_native_setup()static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName) { // Convert jstring to String16 const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL); jsize rawClientNameLen = env->GetStringLength(clientPackageName); String16 clientName(rawClientName, rawClientNameLen); env->ReleaseStringChars(clientPackageName, rawClientName); sp<Camera> camera; if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) { // Default path: hal version is don't care, do normal camera connect. //这里调用Camera静态方法connect.请看下面代码 camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID); } else { //...... }
当我们打开Camera时,第一个调用的就是native_setup(),它会找到包名,CameraID,UID宏与CameraService进行链接获取到camera对象。
2.camera对象创建过程
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName, int clientUid) { //下面发现直接调用的是CameraBaseT::connect方法,大家应该还记得,前面说过 //CameraBaseT就是带了camera模板参数的CameraBase类。请看下面CameraBase类。 return CameraBaseT::connect(cameraId, clientPackageName, clientUid); } //CameraBase类,这里TCam = camera,TCamTraits = CameraTraits<camera>,要记住 template <typename TCam, typename TCamTraits> sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, const String16& clientPackageName, int clientUid) { ALOGV("%s: connect", __FUNCTION__); sp<TCam> c = new TCam(cameraId); //这里直接new Camera() sp<TCamCallbacks> cl = c;//这里非常要强调一下,由于camera实现了ICameraClient的接口,所以这里cl,就是callback对象的引用了,实际都是同一个对象。 status_t status = NO_ERROR; const sp<ICameraService>& cs = getCameraService();//这里获取CameraService代理对象,后续在继续分析binder getservice时,会详细分析这一流程。 if (cs != 0) {// TCamConnectService fnConnectService = TCamTraits::fnConnectService; //这里只需记着fnConnectService = ICameraService::connect,而参数c->mCamera是指向ICamera代理对象的强引用。连接成功后CameraService中会创建一个实现ICamera接口的Camera2Client类对象。这就具备友好通信的前提了。后续都是通过匿名binder实现直接通信的。 status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, /*out*/ c->mCamera); } if (status == OK && c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { ALOGW("An error occurred while connecting to camera: %d", cameraId); c.clear(); } return c; }
这里我们不做深入追究,后续的博文会深入介绍的。这里connect连接成功后,会有下面几个新对象生成。
(1).camera,显而易见在进行connect之前,就已经new出来一个camera对象了,然后定义TCamCallbacks强引用指针cl,用于conect时传给CameraService的BnCameraClient本地对象(这里的camera对象就是BnCameraClient本地对象)。注意在CameraService代理对象中,通过writeStrongBinder将该BnCameraClient注册到了当前camera客户端进程的binder_proc的refs_by_node链表中,同时会定义一个binder_ref对象传给CameraService中(这里就是匿名binder通信了,会在后续的binder学习中好好分析)。
(2).bnCameraClient 该对象就是上面new出来的camera对象的引用,以匿名binder通信方式,注册给camera client进程中,然后将binder_ref传给mediaServer中的CameraService对象中。
(3).Camera2Client,该对象为本地对象会在CameraService中诞生,引用对象会在connect返回时传给camera对象中ICamera强引用对象mCamera中,如下。
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, /*out*/ c->mCamera);//最后一个参数。
到这个时候,Camera运行需要的主要对象,都创建完毕。
二、ICamera接口
图三、ICamera相关类继承关系
该类是Camera控制的主要接口类,客户端和Service端都会实现ICamera接口类。客户端进程以匿名binder的形式,与mediaServer进程的CameraService进行通信。下面列举一些我个人认为有必要深入了解的接口。
函数名 | 功能介绍 |
---|---|
virtual status_t setPreviewTarget(const sp& bufferProducer) = 0; | “pass the buffered IGraphicBufferProducer to the camera service”,这个就是设置buffer的地方,参数我们可以看到设下去的是buffer producer对象(这里的生产者-消费者模型我们后面介绍),其实preview申请一个Surface对象后,Sureface就对应一个buffer producer对象,应用是生产者,底层是消费者 |
virtual status_t startPreview() = 0; | “start preview mode, must call setPreviewTarget first”,官方给的解释是在startpreview时,一定要先设置buffer |
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0; | ” send command to camera driver”,google介绍简单直接,就是向sensor驱动发送命令,其实这个函数最终的是传给Camera hal 的CameraMetadata,进而间接就影响到了Camera driver |
virtual void releaseRecordingFrame(const sp& mem) = 0; | “release a recording frame”,官方解释就是释放录像帧,等后面我们分析了录像,在来这里把这个补充好吧 |
三、ICameraService接口
图四、ICameraService相关类继承关系
这里是CameraService的继承关系,右侧是我列举的一些个人认为比较重要的函数。ICameraService中总共有12接口,我们只介绍下面几个。
函数名 | 函数介绍 |
---|---|
virtual int32_t getNumberOfCameras() = 0; | 这个在CameraService起来是会调用这个接口,来探测Camera硬件上有几个Camera,进而会不会有前设旋转开关,在每次Open Camera时也会调用一次 |
virtual status_t getCameraInfo(int cameraId,/out/struct CameraInfo* cameraInfo) = 0; | 获取Camera的信息,包括FOV,LENS,等信息 |
virtual status_t addListener(const sp& listener) = 0; | 目前发现没用这个函数,这里就先放这吧 |
virtual status_t connect(const sp& cameraClient,int cameraId, const String16& clientPackageName,intclientUid, /out/sp& device) = 0; | 这个函数是非常重要的,当Open Camera时,客户端会传过来一个bpCameraClientde代理对象。然后CameraService会创建一个实现ICamera接口的Camera2client类对象,紧接着就把这个Camera2Client的代理返回到客户端进程中,用于频繁的操作Camera |
四、总结
博文介绍了操作Camera的三大接口类之间的类继承关系和常用的接口分析。还没开始去分析preview,takepicture,recording等流程,后续的博文会一一展开,一起进步。相关文章推荐
- 【重头学习Android】Android 中Activity,Window和View之间的关系
- J2EE系列之Spring4学习笔记(六)--IOC详解(bean之间的关系,bean的作用范围)
- Android framework camera回顾-Camera CameraClient ICamera之间关系(1)-cl和c->mCamera去哪儿
- android基础部分再学习---Android中的APK,TASK,PROCESS,USERID之间的关系 UID和PID
- Android学习 之 Activity和Window之间的关系
- Android Camera PreviewSize PictureSize SurfaceView之间的关系
- Android Camera fw学习(五)-takepicutre(STILL_TAKEPICTURE)流程分析
- Android开发学习笔记(三):关于fragment_main.xml、activity_main.xml与主函数之间的关系
- Android framework camera回顾-Camera ICameraClient ICamera CameraClient之间关系(2)完整图
- Android之多个Activity之间的关系和Intent作用
- Android笔记-MultiThreading in Android(1)-Thread,Looper,Handler,Message,MessageQueue之间的关系
- Android入门:深入学习理解 Handler HandlerThread AsyncQueryHandler 三者的关系 收藏
- 学习:短信的收发及在android模拟器之间实践(2)
- 学习:短信的收发及在android模拟器之间实践(1)
- 2011年Android Camera学习笔记之一
- 学习JavaScript 的必备 (一),让您对js的 function, javascript内置对象,this概念及之间的关系不再迷惑
- Android多媒体学习十五:使用在内置的Camera录制视频
- android中View, Window, Activity, WindowManager,ViewRoot几者之间的关系
- JSP学习 —— 开篇:JSP,servlet容器,Tomcat,servlet容器之间的关系
- Hibernate的学习总结(映射类之间的组合关系)