Android CCodec Codec2 (十二)CCodecConfig

Codec2组件的运行参数都存储在Interface中,这些参数由厂商预先设定,并力求达到最优(best effort),因此非必要情况下不建议进行修改。在CCodec中,我们很少看到对组件参数的修改,这与ACodec对组件配置的过程形成了明显的对比。CCodecConfig在Codec2框架中主要起着参数存储的作用,参数来自于两部分:从组件实例读取的厂商预定义的参数和上层应用配置下来的参数。 CCodecConfig还有另外一个重要功能:向上层提供参数反射,实现非标准参数的设定,这部分我们不做了解。

1、CCodecConfig::initialize

组件创建完成后会调用initialize方法初始化CCodecConfig,代码比较长我们分段来讲。

status_t CCodecConfig::initialize(
        const std::shared_ptr<C2ParamReflector> &reflector,
        const std::shared_ptr<Codec2Client::Configurable> &configurable);

initialize传入两个参数,第一个参数reflector是调用ComponentStore的getParamReflector获取到的C2ParamReflector对象,第二个参数configurable是组件实例。

C2ComponentDomainSetting domain(C2Component::DOMAIN_OTHER);
C2ComponentKindSetting kind(C2Component::KIND_OTHER);

std::vector<std::unique_ptr<C2Param>> queried;
c2_status_t c2err = configurable->query({ &domain, &kind }, {}, C2_DONT_BLOCK, &queried);
if (c2err != C2_OK) {
    if (kind.value == C2Component::KIND_OTHER) {
        if (configurable->getName().find("encoder") != std::string::npos) {
            kind.value = C2Component::KIND_ENCODER;
        } else if (configurable->getName().find("decoder") != std::string::npos) {
            kind.value = C2Component::KIND_DECODER;
        }
    }

    if (domain.value == C2Component::DOMAIN_OTHER) {
        AString mediaType = QueryMediaType(true /* input */, configurable);
        if (mediaType.startsWith("audio/")) {
            domain.value = C2Component::DOMAIN_AUDIO;
        } else if (mediaType.startsWith("video/")) {
            domain.value = C2Component::DOMAIN_VIDEO;
        } else if (mediaType.startsWith("image/")) {
            domain.value = C2Component::DOMAIN_IMAGE;
        }
    }
}

进入函数体后首先向组件请求Domain和Kind信息(ACodec是根据创建组件时的组件名来获取Domain和Kind信息)。如果组件没有定义C2ComponentKindSetting,就根据组件名称来判断Kind。

如果组件没有定义C2ComponentDomainSetting,会先调用QueryMediaType获取组件输入的mime type:

template <typename PORT, typename STREAM>
AString QueryMediaTypeImpl(
        const std::shared_ptr<Codec2Client::Configurable> &configurable) {
    AString mediaType;
    std::vector<std::unique_ptr<C2Param>> queried;
    // 请求参数
    c2_status_t c2err = configurable->query(
            {}, { PORT::PARAM_TYPE, STREAM::PARAM_TYPE }, C2_DONT_BLOCK, &queried);
    if (c2err != C2_OK && queried.size() == 0) {
        ALOGD("Query media type failed => %s", asString(c2err));
    } else {
        // 将C2Param转为具体的参数类型
        PORT *portMediaType =
            PORT::From(queried[0].get());
        if (portMediaType) {
            mediaType = AString(
                    portMediaType->m.value,
                    strnlen(portMediaType->m.value, portMediaType->flexCount()));
        } else {
            STREAM *streamMediaType = STREAM::From(queried[0].get());
            if (streamMediaType) {
                mediaType = AString(
                        streamMediaType->m.value,
                        strnlen(streamMediaType->m.value, streamMediaType->flexCount()));
            }
        }
        ALOGD("read media type: %s", mediaType.c_str());
    }
    return mediaType;
}

AString QueryMediaType(
        bool input, const std::shared_ptr<Codec2Client::Configurable> &configurable) {
    typedef C2PortMediaTypeSetting P;
    typedef C2StreamMediaTypeSetting S;
    if (input) {
        return QueryMediaTypeImpl<P::input, S::input>(configurable);
    } else {
        return QueryMediaTypeImpl<P::output, S::output>(configurable);
    }
}

C2PortMediaTypeSetting定义的是端口的媒体类型,C2StreamMediaTypeSetting定义的是流的媒体类型,这两个参数看起来有一点重复。

从上述代码可以看到,请求参数有两种方式:

2、ReflectedParamUpdater

关注公众号《青山渺渺》订阅合集阅读完整内容

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青山渺渺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值