我试图了解 MediaCodec 如何用于硬件解码。
我对android内部的了解非常有限。
这是我的发现:
android系统中有一个xml文件代表编解码器的详细信息。
device/ti/omap3evm/media_codecs.xml for an example.
这意味着,如果我们使用媒体编解码器从 Java 应用程序创建编解码器
MediaCodec codec = MediaCodec.createDecoderByType(type);
它应该在 xml 文件的帮助下找出相应的编码器。
我在做什么?
我试图找出代码的哪一部分正在读取 xml 并根据给定的“类型”找到编解码器。
1) 应用层:
MediaCodec codec = MediaCodec.createDecoderByType(type);
2) MediaCodec.java -> [ frameworks/base/media/java/android/media/MediaCodec.java ]
public static MediaCodec createDecoderByType(String type) {
return new MediaCodec(type, true /* nameIsType */, false /* encoder */);
}
3)
private MediaCodec(
String name, boolean nameIsType, boolean encoder) {
native_setup(name, nameIsType, encoder); --> JNI Call.
}
4)
JNI 实现 -> [ frameworks/base/media/jni/android_media_MediaCodec.cpp ]
static void android_media_MediaCodec_native_setup (..) {
.......
const char *tmp = env->GetStringUTFChars(name, NULL);
sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder); ---> Here
}
来自 frameworks/base/media/jni/android_media_MediaCodec.cpp
JMediaCodec::JMediaCodec( ..) {
....
mCodec = MediaCodec::CreateByType(mLooper, name, encoder); //Call goes to libstagefright
.... }
sp<MediaCodec> MediaCodec::CreateByType(
const sp<ALooper> &looper, const char *mime, bool encoder) {
sp<MediaCodec> codec = new MediaCodec(looper);
if (codec->init(mime, true /* nameIsType */, encoder) != OK) { --> HERE.
return NULL;
}
return codec;
}
status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) {
// MediaCodec
}
我对这个流程感到震惊。如果有人指出如何推进它会很有帮助。
谢谢。
最佳答案
让我们一步一步地了解流程。
MediaCodec::CreateByType
将创建一个新的 MediaCodec
对象 MediaCodec
构造函数将创建一个新的 ACodec
对象并将其存储为 mCodec
MediaCodec::init
被调用时,它内部指示底层 ACodec
通过 OMX
分配 mCodec->initiateAllocateComponent
组件。 ACodec::initiateAllocateComponent
会调用 onAllocateComponent
ACodec::UninitializedState::onAllocateComponent
将调用 OMXCodec::findMatchingCodecs
来查找与调用者传递的 MIME
类型匹配的编解码器。 OMXCodec::findMatchingCodecs
中,有一个调用将 MediaCodecList
的实例检索为 MediaCodecList::getInstance()
。 MediaCodecList::getInstance
中,检查是否存在现有的 MediaCodecList
或 a new object of MediaCodecList
is created 。 MediaCodecList
的构造函数中,有一个对 parseXMLFile
的调用,文件名为 /etc/media_codecs.xml
。 parseXMLFile
读取内容并将不同的组件名称等存储到 MediaCodecList
中,startElementHandler
也可用于任何其他编解码器实例。用于解析的辅助函数是 addMediaCodec
。感兴趣的函数可能是 XML
。 通过这些步骤,
MediaCodecList
文件内容被翻译成一个列表,任何其他模块都可以使用该列表。 MediaCodec
也暴露在 Java 层,可以从 here 引用。我已经跳过了一些步骤,其中
ACodec
和 ojit_code 使用消息来实际通信和调用方法,但是所呈现的流程应该很好地了解底层机制。