IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> [sprd camera] 3 camera open -> 正文阅读

[移动开发][sprd camera] 3 camera open

一、前言

? ? ? 图借用的这篇博文?Android : Camera2/HAL3 框架分析 - sheldon_blogs - 博客园 (cnblogs.com)

1、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);
}

这里是open开始金丹的调用,我们主要是注意这个callback 和 cameraid 这两个参数。

cameraid决定是打开那个摄像头,callback是回调函数,open成功后会回调相应的函数。

2、openCameraDeviceUserAsync

private CameraDevice openCameraDeviceUserAsync(String cameraId,
        CameraDevice.StateCallback callback, Executor executor, final int uid)
        throws CameraAccessException {
    CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
    CameraDevice device = null;

    ICameraDeviceUser cameraUser = null;

    //这里调用CameraDeviceImpl的构造函数赋值。
    android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
            new android.hardware.camera2.impl.CameraDeviceImpl(
                cameraId,
                callback,
                executor,
                characteristics,
                mContext.getApplicationInfo().targetSdkVersion);

    //这里callback实质还是参数callback。
    ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();

    // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
    ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
    cameraUser = cameraService.connectDevice(callbacks, cameraId,
                    mContext.getOpPackageName(), uid);

    deviceImpl.setRemoteDevice(cameraUser);
    device = deviceImpl;
    
    return device;
}

1、生成?CameraDeviceImpl 的对象这个对象会通过后面的回调返回给apk,apk可以通过这个对象来操控镜头。

2、connectDevice 方法连接到相机设备,cameraUser 实际上指向的是远端 CameraDeviceClient 的本地接口。

3、将 CameraDeviceClient 设置到 CameraDeviceImpl 中进行管理。

我们可以先看看deviceImpl.setRemoteDevice(cameraUser)

3、setRemoteDevice

public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
 
    mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);

    mDeviceExecutor.execute(mCallOnOpened);
    mDeviceExecutor.execute(mCallOnUnconfigured);
}
private final Runnable mCallOnOpened = new Runnable() {
    @Override
    public void run() {
        mDeviceCallback.onOpened(CameraDeviceImpl.this);
    }
};

1、这里就是对CameraDeviceClient进行的一层封装,再加入到CameraDeviceImpl 中。

2、调用回调open成功的回调函数,回调函数实在应用中实现的。

3、close后调用的回调函数。

4、connectDevice

Status CameraService::connectDevice(
        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
        const String16& cameraId,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<hardware::camera2::ICameraDeviceUser>* device) {

    Status ret = Status::ok();
    String8 id = String8(cameraId);
    sp<CameraDeviceClient> client = nullptr;

    ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
            /*api1CameraId*/-1,
            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
            clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, /*out*/client);
			
    *device = client;
    return ret;
}

template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
        int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,
        int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
        /*out*/sp<CLIENT>& device) {
    binder::Status ret = binder::Status::ok();

    String8 clientName8(clientPackageName);

    int originalClientPid = 0;

    sp<CLIENT> client = nullptr;
    {
        sp<BasicClient> tmp = nullptr;
        if(!(ret = makeClient(this, cameraCb, clientPackageName,
                cameraId, api1CameraId, facing,
                clientPid, clientUid, getpid(),
                halVersion, deviceVersion, effectiveApiLevel,
                /*out*/&tmp)).isOk()) {
            return ret;
        }
        client = static_cast<CLIENT*>(tmp.get());

        err = client->initialize(mCameraProviderManager, mMonitorTags);

    } // lock is destroyed, allow further connect calls

    device = client;
    return ret;
}

1、生成CameraDeviceClient

2、初始化这个CameraDeviceClient

4.1、makeClient

Status CameraService::makeClient(const sp<CameraService>& cameraService,
        const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
        int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
        int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
        /*out*/sp<BasicClient>* client) {

    // Default path: HAL version is unspecified by caller, create CameraClient
    // based on device version reported by the HAL.
    switch(deviceVersion) {
      case CAMERA_DEVICE_API_VERSION_3_2:
      case CAMERA_DEVICE_API_VERSION_3_5:
        sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
        *client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
                facing, clientPid, clientUid, servicePid);
        break;
    }

    return Status::ok();
}

Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
        const sp<hardware::ICameraClient>& cameraClient,
        const String16& clientPackageName,
        const String8& cameraDeviceId,
        int api1CameraId,
        int cameraFacing,
        int clientPid,
        uid_t clientUid,
        int servicePid):
        Camera2ClientBase(cameraService, cameraClient, clientPackageName,
                cameraDeviceId, api1CameraId, cameraFacing,
                clientPid, clientUid, servicePid),
        mParameters(api1CameraId, cameraFacing)
{}

template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
        const sp<CameraService>& cameraService,
        const sp<TCamCallbacks>& remoteCallback,
        const String16& clientPackageName,
        const String8& cameraId,
        int api1CameraId,
        int cameraFacing,
        int clientPid,
        uid_t clientUid,
        int servicePid):
        TClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
        mSharedCameraCallbacks(remoteCallback),
        mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
        mDevice(new Camera3Device(cameraId)),
        mDeviceActive(false), mApi1CameraId(api1CameraId)
{}

这一路下来都是在生成CameraDeviceClient的对象,最后重要是生成一个Camera3Device的对象赋值给mDdevice。

?4.2、client->initialize

status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager,
        const String8& monitorTags) {
    return initializeImpl(manager, monitorTags);
}

template<typename TProviderPtr>
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags) {
    status_t res;

    res = Camera2ClientBase::initialize(providerPtr, monitorTags);

    //这一块暂时还不知道有什么作用
    String8 threadName;
    mFrameProcessor = new FrameProcessorBase(mDevice);
    threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
    mFrameProcessor->run(threadName.string());

    mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                      FRAME_PROCESSOR_LISTENER_MAX_ID,
                                      /*listener*/this,
                                      /*sendPartials*/true);

    mProviderManager = providerPtr;
    return OK;
}

template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,
        const String8& monitorTags) {
    return initializeImpl(manager, monitorTags);
}

template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr,
        const String8& monitorTags) {

    res = mDevice->initialize(providerPtr, monitorTags);

    wp<CameraDeviceBase::NotificationListener> weakThis(this);
    res = mDevice->setNotifyCallback(weakThis);

    return OK;
}

这一路下来兜售client的初始化,最终变成mDevice的初始化。

status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
    Mutex::Autolock il(mInterfaceLock);
    Mutex::Autolock l(mLock);

    sp<ICameraDeviceSession> session;
    ATRACE_BEGIN("CameraHal::openSession");
    status_t res = manager->openSession(mId.string(), this,
            /*out*/ &session);

    res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);

    std::shared_ptr<RequestMetadataQueue> queue;
    auto requestQueueRet = session->getCaptureRequestMetadataQueue(
        [&queue](const auto& descriptor) {
            queue = std::make_shared<RequestMetadataQueue>(descriptor);
            if (!queue->isValid() || queue->availableToWrite() <= 0) {
                ALOGE("HAL returns empty request metadata fmq, not use it");
                queue = nullptr;
                // don't use the queue onwards.
            }
        });


    std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
    auto resultQueueRet = session->getCaptureResultMetadataQueue(
        [&resQueue](const auto& descriptor) {
            resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
            if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
                ALOGE("HAL returns empty result metadata fmq, not use it");
                resQueue = nullptr;
                // Don't use the resQueue onwards.
            }
        });

    camera_metadata_entry bufMgrMode =
            mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);

    mInterface = new HalInterface(session, queue, mUseHalBufManager);
    std::string providerType;
    mVendorTagId = manager->getProviderTagIdLocked(mId.string());
    mTagMonitor.initialize(mVendorTagId);

    return initializeCommonLocked();
}

1、通过CameraProviderManager 获取 session,这里会调用到hal 层获取到hal层的CameraDevice::open

2、获取hal 层的RequestMetadataQueue 和?ResultMetadataQueue队列?

从这里看感觉framework中的?Camera3Device 和 hal层的CameraDevice是对应的

3、生成mInterface 对象

openSession

status_t CameraProviderManager::openSession(const std::string &id,
        const sp<device::V3_2::ICameraDeviceCallback>& callback,
        /*out*/
        sp<device::V3_2::ICameraDeviceSession> *session) {

    //获取cameraservice启动时扫描的的镜头信息
    auto deviceInfo = findDeviceInfoLocked(id,
            /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});

    auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
    //这里获取CameraProvidermanager的对象
    const sp<provider::V2_4::ICameraProvider> provider =
            deviceInfo->mParentProvider->startProviderInterface();

    saveRef(DeviceMode::CAMERA, id, provider);

    Status status;
    hardware::Return<void> ret;
    //这里获取到hal层的CameraDevice代理的对象
    auto interface = deviceInfo3->startDeviceInterface<
            CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();

    //这里相当于调用CameraDevice::open
    ret = interface->open(callback, [&status, &session]
            (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
                status = s;
                if (status == Status::OK) {
                    *session = cameraSession;
                }
            });

    return mapToStatusT(status);
}

这样cameraopen从apk中到cameraservice中的流程就走完了。

?

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-13 09:23:14  更:2021-09-13 09:25:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:00:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码