【问题标题】:How MediaCodec finds the codec inside the framework in Android?MediaCodec如何在Android中找到框架内的编解码器?
【发布时间】:2014-05-16 10:16:49
【问题描述】:

我正在尝试了解 MediaCodec 如何用于硬件解码。

我对android内部的了解非常有限。

这是我的发现:

有一个xml文件代表android系统中编解码器的详细信息。

 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
    }

我对这种流动感到震惊。如果有人指出如何推进它会很有帮助。

谢谢。

【问题讨论】:

    标签: android android-internet stagefright openmax opencore


    【解决方案1】:

    让我们一步一步来。

    1. MediaCodec::CreateByType 将创建一个新的MediaCodec 对象

    2. MediaCodec 构造函数将创建一个新的ACodec 对象并将其存储为mCodec

    3. MediaCodec::init被调用时,它在内部指示底层ACodec通过mCodec-&gt;initiateAllocateComponent分配OMX组件。

    4. ACodec::initiateAllocateComponent 会调用onAllocateComponent

    5. ACodec::UninitializedState::onAllocateComponent 将调用OMXCodec::findMatchingCodecs 来查找与调用者传递的MIME 类型匹配的编解码器。

    6. OMXCodec::findMatchingCodecs 中,有一个调用以将MediaCodecList 的实例检索为MediaCodecList::getInstance()

    7. MediaCodecList::getInstance 中,检查是否存在MediaCodecLista new object of MediaCodecList is created

    8. MediaCodecList的构造函数中,调用了parseXMLFile,文件名为/etc/media_codecs.xml

    9. parseXMLFile 读取内容并将不同的组件名称等存储到MediaCodecList 中,MediaCodecList 也可用于任何其他编解码器实例。用于解析的辅助函数是 startElementHandler 。感兴趣的函数可能是addMediaCodec

    通过这些步骤,XML 文件内容被翻译成一个列表,任何其他模块都可以使用该列表。 MediaCodecList 也暴露在 Java 层,可以参考 here

    我已经跳过了几个跳跃,其中MediaCodecACodec 使用消息来实际通信和调用方法,但是所呈现的流程应该可以很好地了解底层机制。

    【讨论】:

    • 令人印象深刻的甘尼什!!。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2013-02-22
    • 2021-08-30
    • 2015-04-30
    • 2020-05-27
    • 1970-01-01
    • 2017-04-12
    • 2023-04-02
    • 2021-11-07
    相关资源
    最近更新 更多