Android MediaPlayer整体架构源码分析 -【MediaCodec编解码器插件模块化注册和创建处理流程】【Part 5】

承接上一章节分析:Android MediaPlayer整体架构源码分析 -【MediaCodec编解码器插件模块化注册和创建处理流程】【Part 2】
本系列文章分析的安卓源码版本:【Android 10.0 版本】

推荐涉及到的知识点:
Binder机制实现原理:Android C++底层Binder通信机制原理分析总结【通俗易懂】
ALooper机制实现原理:Android native层媒体通信架构AHandler/ALooper机制实现源码分析
Binder异常关闭监听:Android native层DeathRecipient对关联进程(如相关Service服务进程)异常关闭通知事件的监听实现源码分析

【本章节小节序号将重新开始】
分析sCodec2InfoBuilder的buildMediaCodecList(&writer)实现分析:
读取编解码器配置信息并存入writer中返回。
根据前面流程中的分析可知,它的实现是在Codec2InfoBuilder.cpp中,如下
其实根据下面的实现,可以看到它的实现和前面已分析的另一个Builder实现类似的处理。

// [frameworks/av/media/codec2/sfplugin/Codec2InfoBuilder.cpp]
status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
   
    // TODO: Remove run-time configurations once all codecs are working
    // properly. (Assume "full" behavior eventually.)
    //
    // debug.stagefright.ccodec supports 5 values.
    //   0 - No Codec 2.0 components are available.
    //   1 - Audio decoders and encoders with prefix "c2.android." are available
    //       and ranked first.
    //       All other components with prefix "c2.android." are available with
    //       their normal ranks.
    //       Components with prefix "c2.vda." are available with their normal
    //       ranks.
    //       All other components with suffix ".avc.decoder" or ".avc.encoder"
    //       are available but ranked last.
    //   2 - Components with prefix "c2.android." are available and ranked
    //       first.
    //       Components with prefix "c2.vda." are available with their normal
    //       ranks.
    //       All other components with suffix ".avc.decoder" or ".avc.encoder"
    //       are available but ranked last.
    //   3 - Components with prefix "c2.android." are available and ranked
    //       first.
    //       All other components are available with their normal ranks.
    //   4 - All components are available with their normal ranks.
    //
    // The default value (boot time) is 1.
    //
    // Note: Currently, OMX components have default rank 0x100, while all
    // Codec2.0 software components have default rank 0x200.
    // 该系统属性值此前章节中已介绍过,并可根据英文注释更清晰了解其作用。
    // 默认该值通常为4,该值的作用其实就是一个编解码器列表信息的排序模式。规定如何排序它们。
    int option = ::android::base::GetIntProperty("debug.stagefright.ccodec", 4);

    // 获取特征属性列表信息,其实就是系统中可用组件服务的组件列表信息
    // 见第1小节分析
    // Obtain Codec2Client
    std::vector<Traits> traits = Codec2Client::ListComponents();

    // 如下解析音视频编解码器xml配置信息。
    // 下面的解析处理流程,请参考前面流程已分析过程,此处只是从不同的路径下加载配置文件而已,
    // 但是也会加载前面已分析的default默认xml配置文件信息
    // parse APEX XML first, followed by vendor XML
    MediaCodecsXmlParser parser;
    parser.parseXmlFilesInSearchDirs(
            parser.getDefaultXmlNames(),
            {
    "/apex/com.android.media.swcodec/etc" });

    // 若组件移动到了默认文件中,它将会删除c2即Codec2特殊配置文件信息中值
    // TODO: remove these c2-specific files once product moved to default file names
    parser.parseXmlFilesInSearchDirs(
            {
    "media_codecs_c2.xml", "media_codecs_performance_c2.xml" });

    // 加载默认配置文件
    // parse default XML files
    parser.parseXmlFilesInSearchDirs();

    // 注意:解析状态未完成时也返回OK
    if (parser.getParsingStatus() != OK) {
   
        ALOGD("XML parser no good");
        return OK;
    }

    // 获取已解析的服务属性设置映射信息
    MediaCodecsXmlParser::AttributeMap settings = parser.getServiceAttributeMap();
    for (const auto &v : settings) {
   
        if (!hasPrefix(v.first, "media-type-")
                && !hasPrefix(v.first, "domain-")
                && !hasPrefix(v.first, "variant-")) {
   
            // 若不是以这三个开头的属性值,那么将其添加到全局属性值设置信息列表中,见前面章节流程中已有分析    
            writer->addGlobalSetting(v.first.c_str(), v.second.c_str());
        }
    }

    for (const Traits& trait : traits) {
   
        C2Component::rank_t rank = trait.rank;

        // Interface must be accessible for us to list the component, and there also
        // must be an XML entry for the codec. Codec aliases listed in the traits
        // allow additional XML entries to be specified for each alias. These will
        // be listed as separate codecs. If no XML entry is specified for an alias,
        // those will be treated as an additional alias specified in the XML entry
        // for the interface name.
        // 获取(插件编解码器)组件名或其别名列表信息
        std::vector<std::string> nameAndAliases = trait.aliases;
        nameAndAliases.insert(nameAndAliases.begin(), trait.name);
        // for循环处理每一个编解码器配置信息
        for (const std::string &nameOrAlias : nameAndAliases) {
   
        	// 若不相同则表示当前组件名为别名
            bool isAlias = trait.name != nameOrAlias;
            // 根据指定组件名创建编解码器客户端代理接口对象
            // 见第2小节分析
            std::shared_ptr<Codec2Client::Interface> intf =
                Codec2Client::CreateInterfaceByName(nameOrAlias.c_str());
            if (!intf) {
   
            	// 若接口创建失败,那么将跳过该编解码器组件(配置信息)
                ALOGD("could not create interface for %s'%s'",
                        isAlias ? "alias " : "",
                        nameOrAlias.c_str());
                continue;
            }
            if (parser.getCodecMap().count(nameOrAlias) == 0) {
   
            	// 由前面流程已对该方法的分析可知,若为0表示该组件名或别名,在xml配置信息中未找到
                if (isAlias) {
   
                	// 若是别名,则查找该组件名对应的MediaCodecInfoWriter信息对象
                    std::unique_ptr<MediaCodecInfoWriter> baseCodecInfo =
                        writer->findMediaCodecInfo(trait.name.c_str());
                    if (!baseCodecInfo) {
   
                    // 若不存在则表示xml中未找到系统中可用服务组件名的编解码器配置信息,那么将会跳过该组件别名信息处理
                        ALOGD("alias '%s' not found in xml but canonical codec info '%s' missing",
                                nameOrAlias.c_str(),
                                trait.name.c_str());
                    } else {
   
                    // 找到该信息,则缓存该编解码器别名到对应的MediaCodecInfoWriter信息对象中
                        ALOGD("alias '%s' not found in xml; use an XML <Alias> tag for this",
                                nameOrAlias.c_str());
                        // merge alias into existing codec
                        baseCodecInfo->addAlias(nameOrAlias.c_str());
                    }
                } else {
   
                    ALOGD("component '%s' not found in xml", trait.name.c_str());
                }
                // 然后进行下一个组件信息【已经存储该组件信息了,因此不需要下面处理再次缓存了】
                continue;
            }
            // 注意:此为标准组件名
            std::string canonName = trait.name;

            // 接下来处理排序问题,此处就不详细分析了。
            // TODO: Remove this block once all codecs are enabled by default.
            switch (option) {
   
            case 0:
            	// 不需要重新排序,因此直接接跳过该组件,处理下一个组件信息
                continue;
            case 1:
                if (hasPrefix(canonName, "c2.vda.")) {
   
                    break;
                }
                if (hasPrefix(canonName, "c2.android.")) {
   
                    if (trait.domain == C2Component::DOMAIN_AUDIO) {
   
                        rank = 1;
                        break;
                    }
                    break;
                }
                if (hasSuffix(canonName, ".avc.decoder") ||
                        hasSuffix(canonName, ".avc.encoder")) {
   
                    rank = std::numeric_limits<decltype(rank)>::max();
                    break;
                }
                continue;
            case 2:
                if (hasPrefix(canonName, "c2.vda.")) {
   
                    break;
                }
                if (hasPrefix(canonName, "c2.android.")) {
   
                    rank = 1;
                    break;
                }
                if (hasSuffix(canonName, ".avc.decoder") ||
                        hasSuffix(canonName, ".avc.encoder")) {
   
                    rank = std::numeric_limits<decltype(rank)>::max
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值