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定义的是流的媒体类型,这两个参数看起来有一点重复。
从上述代码可以看到,请求参数有两种方式: