赞
踩
由于 android 版本差异、 camera子系统框架也有不同调整,本文是采用 android8 源码作为参考对象,对 camera 子系统进行框架梳理,
建立起框架性认知后、在进一步分析各模块实现时、就如同有了地图和指南针功用。
网上有不同版本摄像头框架描述,笔者为给看客们以简明扼要框架概念、特在文章尾部绘制了该框架图。
APP代码位置:@packages/apps/Camera2/
主要对 Framework中 android.hardware.Camera类的调用,并且实现 Camera 应用的业务逻辑和 UI 显示。
Camera 的应用层在 Android 上表现为直接调用SDK API 开发的一个Camera 应用APK包。
一个Android 应用中若要使用frameworks中的android.hardware.Camera类,需要在Manifest 文件声明Camera的权限,
另外还 需要添加一些 元素来声明应用中的Camera 特性,如自动对焦等。
代码路径:@frameworks/base/core/java/android/hardware/Camera.java
此类是提供给用户空间app端引用的封装、该类调用 android_hardware_Camera.cpp 中的注册的 JNI 本地方法,来管理摄像头设备、设置 camera 事件回调;
从而让用户的App 与 Camera 驱动连接起来形成完整数据链路。
代码路径:@frameworks/base/core/jni/android_hardware_Camera.cpp
与Camera有关的本地方法封装与注册,向上供java空间程序引用,向下调用原生代码以获得物理camera的访问权,
然后返回用于在framework层创建android.hardware.Camera对象的数据。
源码路径: @frameworks/av/camera/Camera.cpp
程序编译生成 libcamera_client.so 库,是摄像头 Client 端的实现,android系统管理 Camera 是采用 C/S 模式。
JNI 封装的本地方法都是 client 端方法, Client调用IPC binder与camera service 服务端通讯、实现调用Servcie管理
物理摄像头目的。
源码路径:@frameworks/av/camera/ICameraClient.cpp
IPC binder代理实现client与service进程间通信,类继承关系主要在 ICamera.h、 ICameraClient.h 和 Camera.h 文件中,内容如下:
@frameworks/av/camera/include/camera/android/ICamera.h
class ICamera: public android::IInterface { public: enum { // Pass real YUV data in video buffers through ICameraClient.dataCallbackTimestamp(). VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV = 0, // Pass metadata in video buffers through ICameraClient.dataCallbackTimestamp(). VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA = 1, // Pass video buffers through IGraphicBufferProducer set with setVideoTarget(). VIDEO_BUFFER_MODE_BUFFER_QUEUE = 2, }; // set a buffer interface to use for client-received preview frames instead // of preview callback buffers. Passing a valid interface here disables any // active preview callbacks set by setPreviewCallbackFlag(). Passing NULL // disables the use of the callback target. virtual status_t setPreviewCallbackTarget( const sp<IGraphicBufferProducer>& callbackProducer) = 0; // start preview mode, must call setPreviewTarget first virtual status_t startPreview() = 0; /* * take a picture. * @param msgType the message type an application selectively turn on/off * on a photo-by-photo basis. The supported message types are: * CAMERA_MSG_SHUTTER, CAMERA_MSG_RAW_IMAGE, CAMERA_MSG_COMPRESSED_IMAGE, * and CAMERA_MSG_POSTVIEW_FRAME. Any other message types will be ignored. */ virtual status_t takePicture(int msgType) = 0; } class BnCamera: public android::BnInterface<ICamera> { public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); };
@frameworks/av/camera/include/camera/android/ICameraClient.h
class ICameraClient: public android::IInterface { public: DECLARE_META_INTERFACE(CameraClient); virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void dataCallback(int32_t msgType, const sp<IMemory>& data, camera_frame_metadata_t *metadata) = 0; virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0; // Invoked to send a recording frame handle with a timestamp. Call // ICamera::releaseRecordingFrameHandle to release the frame handle. virtual void recordingFrameHandleCallbackTimestamp(nsecs_t timestamp, native_handle_t* handle) = 0; // Invoked to send a batch of recording frame handles with timestamp. Call // ICamera::releaseRecordingFrameHandleBatch to release the frame handles. // Size of timestamps and handles must match virtual void recordingFrameHandleCallbackTimestampBatch( const std::vector<nsecs_t>& timestamps, const std::vector<native_handle_t*>& handles) = 0; }; // ---------------------------------------------------------------------------- class BnCameraClient: public android::BnInterface<ICameraClient> { public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); };
上面贴出源码头文件中已经把类之间关系描述很清晰了,我们看一下 BnCameraClient 类是如何与 Camera 间关联的,如下:
@frameworks/av/camera/Camera.h
class Camera : public CameraBase<Camera>, public ::android::hardware::BnCameraClient { public: enum { USE_CALLING_UID = ::android::hardware::ICameraService::USE_CALLING_UID }; enum { USE_CALLING_PID = ::android::hardware::ICameraService::USE_CALLING_PID }; // construct a camera client from an existing remote static sp<Camera> create(const sp<::android::hardware::ICamera>& camera); static sp<Camera> connect(int cameraId, const String16& clientPackageName, int clientUid, int clientPid); static status_t connectLegacy(int cameraId, int halVersion, const String16& clientPackageName, int clientUid, sp<Camera>& camera); // start preview mode, must call setPreviewTarget first status_t startPreview(); ...... //省略部分源码 // ICameraClient interface virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2); virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata); ...... //省略部分源码 }
Camera 类直接继承 BnCameraClient 类,所以构建出来的 Camera 对象的 client 角色也就确认下来,此处是 Camera 摄像头 C/S 模式结合点,
梳理清晰框架关键节点非常关键。
源码路径:@frameworks/av/services/camera/libcameraservice/CameraService.cpp
此源码编译生成 libcameraservice.so 库文件,主要实现两个功能:
(1). 实现 Camera 服务端功能,通过 BinderService 实现与 libcamera_client.so 库进行通讯;
(2). 在 CameraProviderManager.cpp 中以服务方式来管理 v4l1_camera_hal 驱动接口,实现物理摄像头管理功能;
此部分内容暂时不过多描述,笔者将在下一篇《详解 CameraService 都做了什么》文章中,详细梳理和分析。暂时简单介绍呢,
就是 CameraProviderManager.cpp 中获取 “legacy/0” 系统服务,通过系统服务的方式、调用 CameraProvider 服务中的功能.
源码路径:@hardware/interfaces/camera/2.4/default/service.cpp
主要功能:管理安卓系统的物理摄像头、作为独立系统服务存在于android系统中,给 CameraService 提供支持;我们可以理解该模块就是物理摄像头代理服务机构。
CameraProvider 服务启动时在系统服务中注册了 “legacy/0” 服务,使用者通过该名称可以获取到 CameraProvider 服务。 详细梳理请看官参考
上一篇 《谁在调用 v4l2_camera_HAL 摄像头驱动》文章内容。
源码路径: @hardware/libhardware/modules/camera/3_4/
硬件抽象层定义了一套标准接口,HAL内容开放给各个厂家去实现,因此实现风格各异。
我们上一篇《重构android8.1 的 v4l2_camera_HAL 支持虚拟摄像头》 文章中,详细梳理CameraHal-3.4程序框架,及实现逻辑。
内核中摄像头驱动有各厂家实现的驱动,笔者使用的是NXP的硬件平台,
源码路径:@kernel/drivers/media/platform/imx8/ov5640_mipi_v3.c & ov5640_v3.c
Camera驱动向下与真实的camera硬件进行交互,向上与HAL实现进行交互。
内核中除了有真实的摄像头驱动也有虚拟机摄像头驱动,如: v4l2loopback 、vivi等,笔者的虚拟摄像头实现就是通过v4l2loopback
作为基础的技术框架来实现。
本篇文章是从 camera 子系统框架入手、先建立整体框架概念;此源码版本是 android8.1 版本,因源码版本差异、框架实现也也会有差别。
这个子系统框图、可清晰指引 android8 camera 学习路标之功效,如果看官你认为本篇文章对你有所启发或帮助、请点赞一下哦,谢谢。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。