虚拟摄像头之五: 详解 android8 的 Camera 子系统框架

前言

由于 android 版本差异、 camera子系统框架也有不同调整,本文是采用 android8 源码作为参考对象,对 camera 子系统进行框架梳理,
建立起框架性认知后、在进一步分析各模块实现时、就如同有了地图和指南针功用。
网上有不同版本摄像头框架描述,笔者为给看客们以简明扼要框架概念、特在文章尾部绘制了该框架图。

Camera 系统框架分层描述

App 应用

APP代码位置:@packages/apps/Camera2/

主要对 Framework中 android.hardware.Camera类的调用,并且实现 Camera 应用的业务逻辑和 UI 显示。
Camera 的应用层在 Android 上表现为直接调用SDK API 开发的一个Camera 应用APK包。

一个Android 应用中若要使用frameworks中的android.hardware.Camera类,需要在Manifest 文件声明Camera的权限,
另外还 需要添加一些 元素来声明应用中的Camera 特性,如自动对焦等。

framework层

代码路径:@frameworks/base/core/java/android/hardware/Camera.java
此类是提供给用户空间app端引用的封装、该类调用 android_hardware_Camera.cpp 中的注册的 JNI 本地方法,来管理摄像头设备、设置 camera 事件回调;
从而让用户的App 与 Camera 驱动连接起来形成完整数据链路。

JNI

代码路径:@frameworks/base/core/jni/android_hardware_Camera.cpp
与Camera有关的本地方法封装与注册,向上供java空间程序引用,向下调用原生代码以获得物理camera的访问权,
然后返回用于在framework层创建android.hardware.Camera对象的数据。

Camera Client

源码路径: @frameworks/av/camera/Camera.cpp
程序编译生成 libcamera_client.so 库,是摄像头 Client 端的实现,android系统管理 Camera 是采用 C/S 模式。
JNI 封装的本地方法都是 client 端方法, Client调用IPC binder与camera service 服务端通讯、实现调用Servcie管理
物理摄像头目的。

IPC Binder

源码路径:@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 模式结合点,
梳理清晰框架关键节点非常关键。

Camera Service

源码路径:@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 服务中的功能.

CameraProvider

源码路径:@hardware/interfaces/camera/2.4/default/service.cpp

主要功能:管理安卓系统的物理摄像头、作为独立系统服务存在于android系统中,给 CameraService 提供支持;我们可以理解该模块就是物理摄像头代理服务机构。
CameraProvider 服务启动时在系统服务中注册了 “legacy/0” 服务,使用者通过该名称可以获取到 CameraProvider 服务。 详细梳理请看官参考
上一篇 《谁在调用 v4l2_camera_HAL 摄像头驱动》文章内容。

HAL

源码路径: @hardware/libhardware/modules/camera/3_4/

硬件抽象层定义了一套标准接口,HAL内容开放给各个厂家去实现,因此实现风格各异。
我们上一篇《重构android8.1 的 v4l2_camera_HAL 支持虚拟摄像头》 文章中,详细梳理CameraHal-3.4程序框架,及实现逻辑。

Kernel Driver

内核中摄像头驱动有各厂家实现的驱动,笔者使用的是NXP的硬件平台,
源码路径:@kernel/drivers/media/platform/imx8/ov5640_mipi_v3.c & ov5640_v3.c
Camera驱动向下与真实的camera硬件进行交互,向上与HAL实现进行交互。

内核中除了有真实的摄像头驱动也有虚拟机摄像头驱动,如: v4l2loopback 、vivi等,笔者的虚拟摄像头实现就是通过v4l2loopback
作为基础的技术框架来实现。

总结

本篇文章是从 camera 子系统框架入手、先建立整体框架概念;此源码版本是 android8.1 版本,因源码版本差异、框架实现也也会有差别。

在这里插入图片描述这个子系统框图、可清晰指引 android8 camera 学习路标之功效,如果看官你认为本篇文章对你有所启发或帮助、请点赞一下哦,谢谢。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值