【鸿蒙南向开发】OpenHarmony 源码解析之多媒体子系统(camera)

1 简介

媒体子系统为开发者提供一套接口,方便开发者使用系统的媒体资源,本文主要介绍多媒体下的Camera模块。

1.1 OpenHarmony 架构图

在这里插入图片描述

1.2 camera子系统

相关功能接口:相机拍照、相机预览、相机录像
在这里插入图片描述

1.3 原理图

OpenHarmony 源码解析之多媒体子系统(camera)-鸿蒙开发者社区

1.4 搭建HarmonyOS环境

我们首先需要完成HarmonyOS开发环境搭建,可参照如下步骤进行。

●安装DevEco Studio,详情请参考下载和安装软件。

●设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:

1.如果可以直接访问Internet,只需进行下载OpenHarmony SDK操作。

2.如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。

开发者可以参考以下链接,完成设备调试的相关配置:

1.使用真机进行调试

2.使用模拟器进行调试

2 基础知识

2.1 代码结构

OpenHarmony 源码解析之多媒体子系统(camera)-鸿蒙开发者社区

2.2 相机模块核心类

OpenHarmony 源码解析之多媒体子系统(camera)-鸿蒙开发者社区

3 源码解析

3.1 上层初始化示例

该文件的main方法执行了创建camera的整个流程,并且在创建初始化好了camera后,根据用户输入的字符,对camera进行拍照,录像,预览功能的执行。

int main()
{
    cout << "Camera sample begin." << endl;
    SampleHelp();
    CameraKit *camKit = CameraKit::GetInstance();
    if (camKit == nullptr) {
        cout << "Can not get CameraKit instance" << endl;
        return 0;
    }
    list<string> camList = camKit->GetCameraIds();
    string camId;
    for (auto &cam : camList) {
        camId = cam;
    break;
    }

    if (camId.empty()) {
        cout << "No available camera.(1080p wanted)" << endl;
        return 0;
    }

    EventHandler eventHdlr; // Create a thread to handle callback events
    SampleCameraStateMng CamStateMng(eventHdlr);

    camKit->CreateCamera(camId, CamStateMng, eventHdlr);

    char input;
    while (cin >> input) {
        switch (input) {
            case '1':
                CamStateMng.Capture();
                break;
            case '2':
                CamStateMng.StartRecord();
                break;
            case '3':
                CamStateMng.StartPreview();
                break;
            case 's':
                CamStateMng.Stop();
                break;
            case 'q':
                CamStateMng.Stop();
                goto EXIT;
            default:
                SampleHelp();
                break;
        }
    }
    EXIT:
    cout << "Camera sample end." << endl;
    return 0;
}

Camkit 是CameraKit类的全局的变量,这个主要提供上层的调用,这个类里面实际是通过cameraManager_对象进行调用相关的方法。图中主要的流程分为以下几个步骤:

1.获取CameraKit实例

2.调用camKit的GetCameraIds方法获取摄像头的id列表,根据id列表找到1080P分辨率的摄像头id,如果没有找到提示错误信息,直接return。

3.调用camKit的CreateCamera方法,这个方法是camera初始化的核心

根据这三个步骤,分析每一个步骤的流程,获取CameraKit实例这一步,其实一层层调用,实现camera初始化的操作,以下是相关的调用流程

(1)获取CameraKit流程

OpenHarmony 源码解析之多媒体子系统(camera)-鸿蒙开发者社区

(2)GetCameraIds流程

list<string> CameraKit::GetCameraIds()
{
    return cameraManager_->GetCameraIds();
}

CameraKit调用实际上是通过cameraManager_进行调用

list<string> GetCameraIds() override
{
    list<string> cameraList;
    for (auto &i : cameraMapCache_) {
        MEDIA_DEBUG_LOG("%s", i.first.c_str());
        cameraList.emplace_back(i.first);
    }
    return cameraList;
}

CameraService初始化完成后,通过device和ability创建的CameraImpl实例存入cameraMapCache_变量中, GetCameraIds方法通过遍历cameraMapCache_来获取可用的cameraId列表。

(3)CreateCamera流程

void CameraKit::CreateCamera(const string &cameraId, CameraStateCallback &callback, EventHandler &handler)
{
    g_cameraManager->CreateCamera(cameraId, callback, handler);
}

CameraKit实际调用了CameraManagerImpl的CreateCamera方法

void CreateCamera(const string &cameraId, CameraStateCallback &callback, EventHandler &handler) override
{
    auto p = cameraMapCache_.find(cameraId);
    if (p == cameraMapCache_.end()) {
        MEDIA_ERR_LOG("Camera impl not found.");
        handler.Post([&callback, &cameraId] { callback.OnCreateFailed(cameraId, MEDIA_ERR); });
        return;
    }
    p->second->RegistCb(callback, handler);
    cameraService_->CreateCamera(cameraId);
}

首先根据cameraId在cameraMapCache_中找到CameraImpl的位置,将CameraStateCallback回调注册到CamerImpl中,CameraStateCallback是从应用层通过参数传入进来,所以后续CameraImpl中的Configure,Release,OnCreate,OnCreateFailed等方法会通过回调,调用应用层的接口。最后调用CameraService的CreateCamera方法进行创建camera。

void CameraService::CreateCamera(string cameraId)
{
    if (cameraId != g_mainCamera) {
        MEDIA_ERR_LOG("This camera does not exist. (cameraId=%s)", cameraId.c_str());
    }
    cameraServiceCb_->OnCameraStatusChange(cameraId, CameraServiceCallback::CAMERA_STATUS_CREATED, *device_);
}

CameraService中主要通过回调OnCameraStatusChange方法,这个是在CameraManagerImpl类中实现的,CameraManagerImpl通过调用CameraService的Initialize(*this)实现回调接口注册。

void CameraService::Initialize(CameraServiceCallback &callback)
{
    MEDIA_DEBUG_LOG("Camera service initializing");
    InitCameraDevices();

    list<string> cameraList = {g_mainCamera};
    cameraServiceCb_->OnCameraServiceInitialized(cameraList);
}

接下来看一下CameraManagerImpl中的回调实现

void OnCameraStatusChange(string &cameraId, CameraStauts status) override
{
    auto p = cameraMapCache_.find(cameraId);
    switch (status) {
        case CAMERA_STATUS_UNAVAIL:
            if (p != cameraMapCache_.end()) {
                for (auto &i : deviceCbList_) {
                    i.second->Post(
                        [i, cameraId]() { i.first->OnCameraStatus(cameraId, CAMERA_DEVICE_STATE_UNAVAILABLE); });
                }
                // User may still using icamera now
                delete p->second;
                cameraMapCache_.erase(p);
            }
            break;
        case CAMERA_STATUS_AVAIL:
            InitCameraAbility(cameraId);
            if (p == cameraMapCache_.end()) {
                for (auto &i : deviceCbList_) {
                    i.second->Post(
                        [i, cameraId]() { i.first->OnCameraStatus(cameraId, CAMERA_DEVICE_STATE_AVAILABLE); });
                }
            }
            break;
        case CAMERA_STATUS_CREATED:
            if (p != cameraMapCache_.end()) {
                p->second->OnCreate(cameraId);
            }
            break;
        case CAMERA_STATUS_CREATE_FAILED:
            if (p != cameraMapCache_.end()) {
                p->second->OnCreateFailed();
            }
            break;
        default:
            break;
    }
}

调用cameraMapCache_中对应cameraId的OnCreate方法,其中device参数是CameraService中创建并传给CameraImpl的,接下来看一下CameraImpl的OnCreate方法

void CameraImpl::OnCreate(CameraDevice &device)
{
    device_ = &device;
    if (stateCb_ == nullptr || handler_ == nullptr) {
        return;
    }
    handler_->Post([this] { this->stateCb->OnCreated(*this); });
}

首先在CameraImpl中保存一份device_, 其次在EventHandler中通过之前注册的CameraStateCallback回调OnCreate方法,该回调是上层应用实现的,具体如下图所示

class SampleCameraStateMng : public CameraStateCallback {
public:
    SampleCameraStateMng() = delete;
    SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {}
    ~SampleCameraStateMng()
    {
        CloseRecorder();
    }
    void OnCreated(Camera &c) override
    {
        cout << "Sample recv OnCreate camera." << endl;
        auto config = CameraConfig::CreateCameraConfig();
        config->SetFrameStateCallback(&fsCb_, &eventHdlr_);
        c.Configure(*config);
        cam_ = &c;
    }
    void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {}
    void OnReleased(Camera &c) override {}

主要配置了FrameStateCallback回调,以及设置了EventHandler,然后保存CameraImpl,应用层拿到了CameraImpl的对象,并且赋值给cam_对象,后续的camera操作都是通过cam_进行的。

3.2 上层调用相机功能

char input;
while (cin >> input) {
    switch (input) {
        case '1':
            CamStateMng.Capture();
            break;
        case '2':
            CamStateMng.StartRecord();
            break;
        case '3':
            CamStateMng.StartPreview();
            break;
        case 's':
            CamStateMng.Stop();
            break;
        case 'q':
            CamStateMng.Stop();
            goto EXIT;
        default:
            SampleHelp();
            break;
    }
}

应用层根据用户输入的字符进行拍照,开始录像,开始预览以及停止的操作,以下是拍照,录像和预览的时序图

拍照流程
OpenHarmony 源码解析之多媒体子系统(camera)-鸿蒙开发者社区

录像流程
-OpenHarmony 源码解析之多媒体子系统(camera)-鸿蒙开发者社区

总结
通过本文的学习可以大致了解Camera的初始化流程,明白Camera的创建过程,并且对Camera的拍照,录像等功能有详细的了解。

写在最后

有很多小伙伴不知道该从哪里开始学习鸿蒙开发技术?也不知道鸿蒙开发的知识点重点掌握的又有哪些?自学时频繁踩坑,导致浪费大量时间。结果还是一知半解。所以有一份实用的鸿蒙(HarmonyOS NEXT)全栈开发资料用来跟着学习是非常有必要的。

获取完整版高清学习资料,请点击→鸿蒙全栈开发学习资料(安全链接,请放心点击)

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了

最新鸿蒙全栈开发学习线路在这里插入图片描述

鸿蒙HarmonyOS开发教学视频

在这里插入图片描述
在这里插入图片描述

大厂面试真题

在这里插入图片描述

在这里插入图片描述

鸿蒙OpenHarmony源码剖析

在这里插入图片描述

这份资料能帮住各位小伙伴理清自己的学习思路,更加快捷有效的掌握鸿蒙开发的各种知识。有需要的小伙伴自行领取,,先到先得~无套路领取!!

获取这份完整版高清学习资料,请点击→鸿蒙全栈开发学习资料(安全链接,请放心点击)

  • 29
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值