在AwesomePlayer中会调用
mVideoSource= OMXCodec::Create(
mClient.interface(),mVideoTrack->getFormat(),
false, // createEncoder
mVideoTrack,
NULL,flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
来获得videoSource,在这个函数中,会首先查找当前的在kKeyMIMEType并存入mime字串中,然后调用findMatchingCodecs,在这个函数中会判断是Decoder还是Encoder,以Decoder为例,会在kDecoderInfo这个结构体中查找与mime匹配的字串,如果成功获得componentName,则加入到matchingCodecs中。另外,这里要注意的是,如果flags中定义了kPreferSoftwareCodecs,则会重新排序,将软件编解码模块加到前面。
matchingCodecs->clear();
for (int index = 0;; ++index) {
const char *componentName;
if (createEncoder) {
componentName = GetCodec(
kEncoderInfo,
sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
mime, index);
} else {
componentName = GetCodec(
kDecoderInfo,
sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
mime, index);
}
if (!componentName) {
break;
}
if (matchComponentName && strcmp(componentName, matchComponentName)) {
continue;
}
if (((flags & kSoftwareCodecsOnly) && IsSoftwareCodec(componentName)) ||
((flags & kHardwareCodecsOnly) && !IsSoftwareCodec(componentName)) ||
(!(flags & (kSoftwareCodecsOnly | kHardwareCodecsOnly)))) {
matchingCodecs->push(String8(componentName));
}
}
if (flags & kPreferSoftwareCodecs) {
matchingCodecs->sort(CompareSoftwareCodecsFirst);
}
然后,对matchingCodecs中的每个编解码器,按照先后顺序,先看是否是软件编解码器,如果是的,则直接返回软件编解码器即可,如果是硬件的,则需先分配结点,调用allocateNode函数,这个是IOMX类的一个纯虚函数。这里涉及到binder机制,不是很清楚,大致描述下。首先会调用Client端的(IOMX.cpp)BnOMX的allocateNode函数,这里会调用remote的tranact(请求发送并要求返回调用结果)函数来传递ALLOCATE_NODE消息,这就会调用Server端的(OMX.cpp)BpOMX的allocateNode函数,继续会调用到mMaster(OMXMaster.cpp)的makeComponentInstance函数,这边关键是追传进去的name参数。接着会调用到plugin的makeComponentInstance函数,这边会先由指定的name生成index,再由index来生成OMXPluginBase类的对象plugin。
for (size_t i = 0; i < matchingCodecs.size(); ++i) {
componentName = matchingCodecs[i].string();
sp<MediaSource> softwareCodec = createEncoder?
InstantiateSoftwareEncoder(componentName, source, meta):
InstantiateSoftwareCodec(componentName, source);
if (softwareCodec != NULL) {
LOGV("Successfully allocated software codec '%s'", componentName);
return softwareCodec;
}
LOGV("Attempting to allocate OMX node '%s'", componentName);
uint32_t quirks = getComponentQuirks(componentName, createEncoder);
if (!createEncoder
&& (quirks & kOutputBuffersAreUnreadable)
&& (flags & kClientNeedsFramebuffer)) {
if (strncmp(componentName, "OMX.SEC.", 8)) {
// For OMX.SEC.* decoders we can enable a special mode that
// gives the client access to the framebuffer contents.
LOGW("Component '%s' does not give the client access to "
"the framebuffer contents. Skipping.",
componentName);
continue;
}
}
status_t err = omx->allocateNode(componentName, observer, &node);
if (err == OK) {
LOGV("Successfully allocated OMX node '%s'", componentName);
sp<OMXCodec> codec = new OMXCodec(
omx, node, quirks,
createEncoder, mime, componentName,
source, nativeWindow);
observer->setCodec(codec);
err = codec->configureCodec(meta, flags);
if (err == OK) {
return codec;
}
LOGV("Failed to configure codec '%s'", componentName);
}
}
mVideoSource= OMXCodec::Create(
mClient.interface(),mVideoTrack->getFormat(),
false, // createEncoder
mVideoTrack,
NULL,flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
来获得videoSource,在这个函数中,会首先查找当前的在kKeyMIMEType并存入mime字串中,然后调用findMatchingCodecs,在这个函数中会判断是Decoder还是Encoder,以Decoder为例,会在kDecoderInfo这个结构体中查找与mime匹配的字串,如果成功获得componentName,则加入到matchingCodecs中。另外,这里要注意的是,如果flags中定义了kPreferSoftwareCodecs,则会重新排序,将软件编解码模块加到前面。
matchingCodecs->clear();
for (int index = 0;; ++index) {
const char *componentName;
if (createEncoder) {
componentName = GetCodec(
kEncoderInfo,
sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
mime, index);
} else {
componentName = GetCodec(
kDecoderInfo,
sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
mime, index);
}
if (!componentName) {
break;
}
if (matchComponentName && strcmp(componentName, matchComponentName)) {
continue;
}
if (((flags & kSoftwareCodecsOnly) && IsSoftwareCodec(componentName)) ||
((flags & kHardwareCodecsOnly) && !IsSoftwareCodec(componentName)) ||
(!(flags & (kSoftwareCodecsOnly | kHardwareCodecsOnly)))) {
matchingCodecs->push(String8(componentName));
}
}
if (flags & kPreferSoftwareCodecs) {
matchingCodecs->sort(CompareSoftwareCodecsFirst);
}
然后,对matchingCodecs中的每个编解码器,按照先后顺序,先看是否是软件编解码器,如果是的,则直接返回软件编解码器即可,如果是硬件的,则需先分配结点,调用allocateNode函数,这个是IOMX类的一个纯虚函数。这里涉及到binder机制,不是很清楚,大致描述下。首先会调用Client端的(IOMX.cpp)BnOMX的allocateNode函数,这里会调用remote的tranact(请求发送并要求返回调用结果)函数来传递ALLOCATE_NODE消息,这就会调用Server端的(OMX.cpp)BpOMX的allocateNode函数,继续会调用到mMaster(OMXMaster.cpp)的makeComponentInstance函数,这边关键是追传进去的name参数。接着会调用到plugin的makeComponentInstance函数,这边会先由指定的name生成index,再由index来生成OMXPluginBase类的对象plugin。
for (size_t i = 0; i < matchingCodecs.size(); ++i) {
componentName = matchingCodecs[i].string();
sp<MediaSource> softwareCodec = createEncoder?
InstantiateSoftwareEncoder(componentName, source, meta):
InstantiateSoftwareCodec(componentName, source);
if (softwareCodec != NULL) {
LOGV("Successfully allocated software codec '%s'", componentName);
return softwareCodec;
}
LOGV("Attempting to allocate OMX node '%s'", componentName);
uint32_t quirks = getComponentQuirks(componentName, createEncoder);
if (!createEncoder
&& (quirks & kOutputBuffersAreUnreadable)
&& (flags & kClientNeedsFramebuffer)) {
if (strncmp(componentName, "OMX.SEC.", 8)) {
// For OMX.SEC.* decoders we can enable a special mode that
// gives the client access to the framebuffer contents.
LOGW("Component '%s' does not give the client access to "
"the framebuffer contents. Skipping.",
componentName);
continue;
}
}
status_t err = omx->allocateNode(componentName, observer, &node);
if (err == OK) {
LOGV("Successfully allocated OMX node '%s'", componentName);
sp<OMXCodec> codec = new OMXCodec(
omx, node, quirks,
createEncoder, mime, componentName,
source, nativeWindow);
observer->setCodec(codec);
err = codec->configureCodec(meta, flags);
if (err == OK) {
return codec;
}
LOGV("Failed to configure codec '%s'", componentName);
}
}
new OMXCodec是根据获取的结点来创建编解码器的,对于后面的observer->setCodec(codec)及codec->configureCodec(meta, flags)只是对编加码器的一些配置工作,没有细看。
转载请注明出处:http://blog.csdn.net/qq69696698