androidandroid-internetstagefrightopenmaxopencore

How MediaCodec finds the codec inside the framework in Android?


I am trying to understanding how MediaCodec is used for hardware decoding.

My knowledge in android internal is very limited.

Here is my findings:

There is a xml file which represents the codec details in the android system .

 device/ti/omap3evm/media_codecs.xml for an example. 

Which means, that If we create a codec from the Java Application with Media Codec

MediaCodec codec = MediaCodec.createDecoderByType(type);

It should be finding out respective coder with the help of xml file.

What am I doing?

I am trying to figure our which part of the code is reading xml and find the codec based on given 'type'.

1) Application Layer :

   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 Implementation -> [ 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
}

from 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
    }

I am struck with this flow. If someone points out how to take it forward would help a lot.

thanks.


Solution

  • Let's take the flow step by step.

    1. MediaCodec::CreateByType will create a new MediaCodec object

    2. MediaCodec constructor would create a new ACodec object and store it as mCodec

    3. When MediaCodec::init is invoked, it internally instructs the underlying ACodec to allocate the OMX component through mCodec->initiateAllocateComponent.

    4. ACodec::initiateAllocateComponent would invoke onAllocateComponent

    5. ACodec::UninitializedState::onAllocateComponent would invoke OMXCodec::findMatchingCodecs to find the codecs matching the MIME type passed from the caller.

    6. In OMXCodec::findMatchingCodecs, there is a call to retrieve an instance of MediaCodecList as MediaCodecList::getInstance().

    7. In MediaCodecList::getInstance, there is a check if there is an existing MediaCodecList or else a new object of MediaCodecList is created.

    8. In the constructor of MediaCodecList, there is a call to parseXMLFile with the file name as /etc/media_codecs.xml.

    9. parseXMLFile reads the contents and stores the different component names etc into MediaCodecList which can be used for any other codec instance too. The helper function employed for the parsing is startElementHandler . A function of interest could be addMediaCodec.

    Through these steps, the XML file contents are translated into a list which can be employed by any other module. MediaCodecList is exposed at Java layer too as can be referred from here.

    I have skipped a few hops wherein MediaCodec and ACodec employ messages to actually communicate and invoke methods, but the flow presented should give a good idea about the underlying mechanism.