Android Codec2 CCodec(二)服务启动

本篇文章我们会先简单了解Android Framework提供的Codec2软件编解码服务(SW Codec Service)的启动过程,然后分析C2Store的设计结构。

1、Codec2 SW Codec Service

Codec2 SW服务启动文件名为main_swcodecservice.cpp,它和OpenMAX服务的启动文件放在同一个文件夹。

cpp 复制代码
int main(int argc __unused, char** argv)
{
    LOG(INFO) << "media swcodec service starting";
    signal(SIGPIPE, SIG_IGN);
    SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
    strcpy(argv[0], "media.swcodec");

    ::android::hardware::configureRpcThreadpool(64, false);

    RegisterCodecServices();

    ::android::hardware::joinRpcThreadpool();
}

从代码中可以看到,Codec2 SW服务名为media.swcodec,而我们之前学习的OpenMAX服务名为media.codec。

cpp 复制代码
$ ps -A | grep codec
mediacodec     489     1      67712   2144 binder_thread_read  0 S media.codec
mediacodec     600     1     102996   2012 binder_thread_read  0 S media.swcodec

media.swcodec是一个HIDL Service,所以它会有一个Manifest文件,比较奇怪的是media.swcodec的清单文件位于frameworks/av/media/mediaserver目录下:

xml 复制代码
<manifest version="1.0" type="framework">
    <hal>
        <name>android.hardware.media.c2</name>
        <transport>hwbinder</transport>
        <version>1.2</version>
        <interface>
            <name>IComponentStore</name>
            <instance>software</instance>
        </interface>
    </hal>
</manifest>

回过头来看main,主要是调用RegisterCodecServices创建ComponentStore实例。简化后的代码如下:

cpp 复制代码
extern "C" void RegisterCodecServices() {
    // 创建C2ComponentStore实例
    std::shared_ptr<C2ComponentStore> store =
        android::GetCodec2PlatformComponentStore();

    using namespace ::android::hardware::media::c2;

    int platformVersion = android_get_device_api_level();
    // 创建IComponentStore/ComponentStore实例
    if (platformVersion >= __ANDROID_API_S__) {
        android::sp<V1_2::IComponentStore> storeV1_2 =
            new V1_2::utils::ComponentStore(store);
        if (storeV1_2->registerAsService("software") != android::OK) {
            LOG(ERROR) << "Cannot register software Codec2 v1.2 service.";
            return;
        }
    } else if (platformVersion == __ANDROID_API_R__) {
        android::sp<V1_1::IComponentStore> storeV1_1 =
            new V1_1::utils::ComponentStore(store);
        if (storeV1_1->registerAsService("software") != android::OK) {
            LOG(ERROR) << "Cannot register software Codec2 v1.1 service.";
            return;
        }
    } else if (platformVersion == __ANDROID_API_Q__) {
        android::sp<V1_0::IComponentStore> storeV1_0 =
            new V1_0::utils::ComponentStore(store);
        if (storeV1_0->registerAsService("software") != android::OK) {
            LOG(ERROR) << "Cannot register software Codec2 v1.0 service.";
            return;
        }
    } else {  // platformVersion < __ANDROID_API_Q__
        LOG(ERROR) << "The platform version " << platformVersion <<
                      " is not supported.";
        return;
    }
}

RegisterCodecServices做了如下两件事:

  1. 调用GetCodec2PlatformComponentStore创建了一个C2ComponentStore对象,从函数名中的Platform可以看出,这个ComponentStore是由Android Framework提供;
  2. 根据Android版本,将C2ComponentStore对象封装到不同版本的IComponentStore中,并将创建的IComponentStore注册到hw binder中。

2、C2ComponentStore

cpp 复制代码
std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
    static std::mutex mutex;
    static std::weak_ptr<C2ComponentStore> platformStore;
    std::lock_guard<std::mutex> lock(mutex);
    std::shared_ptr<C2ComponentStore> store = platformStore.lock();
    if (store == nullptr) {
        store = std::make_shared<C2PlatformComponentStore>();
        platformStore = store;
    }
    return store;
}

GetCodec2PlatformComponentStore最终创建的是一个C2PlatformComponentStore对象,该类型实现了C2ComponentStore的接口。另外,从上述方法可以看出,C2ComponentStore使用了单例,每个进程只有一个store实例。

cpp 复制代码
C2PlatformComponentStore::C2PlatformComponentStore()
    : mVisited(false),
      mReflector(std::make_shared<C2ReflectorHelper>()),
      mInterface(mReflector) {

    auto emplace = [this](const char *libPath) {
        mComponents.emplace(libPath, libPath);
    };

    emplace("libcodec2_soft_h263dec.so");
    emplace("libcodec2_soft_h263enc.so");
    emplace("libcodec2_soft_hevcdec.so");
    emplace("libcodec2_soft_hevcenc.so");
    // ...
}

C2PlatformComponentStore在构造函数中做了三件事:

  1. 实例化C2ReflectorHelper;
  2. 实例化C2PlatformComponentStore::Interface;
  3. 将Android提供的Codec2 SW encoder/decoder Component添加到store中。

添加组件的步骤是不是似曾相识呢?和OMXStore是差不多的。

cpp 复制代码
std::map<C2String, ComponentLoader> mComponents;

mComponents是一个键值列表,key是组件lib名,value是ComponentLoader对象,在给列表添加条目时使用了隐式转换。

cpp 复制代码
ComponentLoader(std::string libPath)
    : mLibPath(libPath) {}

3、ComponentStore

ComponentStore是HDIL接口实现,创建ComponentStore实例需要传入先前创建的C2ComponentStore对象。

cpp 复制代码
struct ComponentStore : public IComponentStore {

protected:
    sp<CachedConfigurable> mConfigurable;
    std::shared_ptr<C2ComponentStore> mStore;
    std::shared_ptr<StoreParameterCache> mParameterCache;
}

ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store)
      : mConfigurable{new CachedConfigurable(std::make_unique<StoreIntf>(store))},
        mParameterCache{std::make_shared<StoreParameterCache>(this)},
        mStore{store} {

    std::shared_ptr<C2ComponentStore> platformStore = android::GetCodec2PlatformComponentStore();
    SetPreferredCodec2ComponentStore(store);

    mParamReflector = mStore->getParamReflector();

    using namespace std::placeholders;
    mInit = mConfigurable->init(mParameterCache);
}
  1. ComponentStore的构造函数会实例化CachedConfigurable成员以及StoreParameterCache成员;
  2. 调用SetPreferredCodec2ComponentStore;
  3. 调用C2ComponentStore的getParamReflector;
  4. 调用CachedConfigurable的init方法。

在Codec2框架中,HIDL实现位于frameworks/av/media/codec2/hal/hidl/1.2/utils,服务最终调用的是Codec2 Core定义的接口。下图是ComponentStore相关的简单UML类图:

相关推荐
陆地鲨鱼-彻几秒前
C++ 音频
c++·音视频
soso19681 分钟前
借助大模型将文档转换为视频
音视频
羚通科技3 分钟前
视频监控管理平台LntonAIServer视频智能分析抖动检测算法应用场景
大数据·人工智能·算法·音视频
Java搬砖组长27 分钟前
快手视频怎么去水印保存到手机?
智能手机·音视频
EasyCVR1 小时前
视频监控平台是如何运作的?EasyCVR视频汇聚平台的高效策略与实践
人工智能·音视频·视频编解码·视频监控·监控视频接入
何大春2 小时前
ProbVLM: Probabilistic Adapter for Frozen Vison-Language Models 论文阅读
论文阅读·人工智能·深度学习·语言模型·音视频·论文笔记
轻口味2 小时前
Android JobScheduler介绍
android
音视频牛哥2 小时前
实时音视频之医疗手术示教技术方案探究
音视频·实时音视频·医疗培训·手术示教·rtmp手术示教·rtmp推送·rtmp播放
技术无疆3 小时前
TitleBar:打造高效Android标题栏的新选择
android·java·ui·android studio·android-studio
爱研究的小牛3 小时前
ESRGAN——老旧照片、视频帧的修复和增强,提高图像的分辨率
人工智能·深度学习·自动化·aigc·音视频