1.MediaCodec初始化流程分析
通过上面流程分析可知,MediaCodecList初始化是通过调用它的getLocalInstance函数,然后在里面new的MediaCodecList对象。在MediaCodec的CreateByType函数中new了MediaCodec对象。
allocateNode调用流程是在ACodec.cpp中的onAllocateComponent中,然后调用到IOMX.cpp中的allocateNode,再调用到WOmx.cpp的allocateNode中,再调用到Omx.cpp(IOmx.hal)中的allocateNode:
所以ACodec中的omxNode是LWOmxNode,其中的mBase是Omx.cpp,LWOmxNode中的mBase是TWOmxNode,TWOmxNode中的mBase是OMXNodeInstance。
2. makeComponentInstance流程分析
在OMX得allocateNode中调用了makeComponentInstance函数,
<1>. 获取了&handle,这个handle就是调用MtkOmxBase.h中得GetComponentHandle得到的:
mCompHandle的初始化,最后framework层调用handle的函数都在这里面对应:
<2>. 回调函数分析:
OMX_ERRORTYPE err = mMaster->makeComponentInstance(name.c_str(), &OMXNodeInstance::kCallbacks,instance.get(), &handle);
主要是三个回调:
OMX_ERRORTYPE (*EventHandler)(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_PTR pAppData,OMX_IN OMX_EVENTTYPE eEvent,OMX_IN OMX_U32 nData1,OMX_IN OMX_U32 nData2,OMX_IN OMX_PTR pEventData);OMX_ERRORTYPE (*EmptyBufferDone)(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_PTR pAppData,OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);OMX_ERRORTYPE (*FillBufferDone)(OMX_OUT OMX_HANDLETYPE hComponent,OMX_OUT OMX_PTR pAppData,OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
回调处理:
<3>.设置回调:
在调用Mtk_OMX_GetHandle的时候调用了SetCallbacks函数最后对应到MtkOmxVdecEx.cpp类里面的MtkVdec_SetCallbacks,里面调用到了它的SetCallbacks:
<4>. mObserver->onMessages最后调用到了ACodec中,回调的处理重点看ACodec中:
3.MediaCodecList流程分析
main_codecservice.cpp服务创建了OmxStore对象,OmxStore主要是初始化MediaCodecsXmlParser解析 media_codecs.xml和media_codecs_performance.xml两个xml文件,这两个文件主要是编解码配置参数配置文件。
在Omx初始化的时候也初始化了MediaCodecsXmlParser对象。
4.加载OMX插件
/hardware/google/av/codec2/hidl/services/C2SoftwareCodecServiceRegistrant.cpp中的RegisterCodecServices函数调用是在 /frameworks/av/services/mediacodec/main_codecservice.cpp中,
addVendorPlugin是加载硬编解码插件,SoftOMXPlugin是加载软编解码插件
5. 硬编解码MtkOMXPlugin初始化
(1). MTK_OMXCORE_CFG_FILE定义:
#define MTK_OMXCORE_CFG_FILE "/vendor/etc/mtk_omx_core.cfg"
实际文件路径:
/device/mediatek/mt6771/mtk_omx_core.cfg
内容如下:
OMX.MTK.VIDEO.DECODER.HEVC video_decoder.hevc libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.MPEG2 video_decoder.mpeg2 libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.H263 video_decoder.h263 libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.MPEG4 video_decoder.mpeg4 libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.AVC video_decoder.avc libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.VPX video_decoder.vp8 libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.VP9 video_decoder.vp9 libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.DIVX video_decoder.divx libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.DIVX3 video_decoder.divx3 libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.XVID video_decoder.xvid libMtkOmxVdecEx.so 16
OMX.MTK.VIDEO.DECODER.VC1 video_decoder.vc1 libMtkOmxVdecEx.so 16
OMX.MTK.AUDIO.DECODER.MP3 audio_decoder.mp3 libMtkOmxMp3Dec.so 32
OMX.MTK.AUDIO.DECODER.WMA audio_decoder.wma libMtkOmxWmaDec.so 32
OMX.MTK.VIDEO.ENCODER.AVC video_encoder.avc libMtkOmxVenc.so 16
OMX.MTK.VIDEO.ENCODER.HEVC video_encoder.hevc libMtkOmxVenc.so 16
OMX.MTK.VIDEO.ENCODER.H263 video_encoder.h263 libMtkOmxVenc.so 16
OMX.MTK.VIDEO.ENCODER.MPEG4 video_encoder.mpeg4 libMtkOmxVenc.so 16
OMX.MTK.AUDIO.DECODER.APE audio_decoder.ape libMtkOmxApeDec.so 32
OMX.MTK.AUDIO.DECODER.ADPCM.MS audio_decoder.adpcm libMtkOmxAdpcmDec.so 32
OMX.MTK.AUDIO.DECODER.ADPCM.DVI audio_decoder.adpcm libMtkOmxAdpcmDec.so 32
OMX.MTK.AUDIO.DECODER.GSM audio_decoder.gsm libMtkOmxGsmDec.so 32
OMX.MTK.AUDIO.DECODER.ALAC audio_decoder.alac libMtkOmxAlacDec.so 32
OMX.MTK.AUDIO.DECODER.MP2 audio_decoder.mp2 libMtkOmxMp3Dec.so 32
(2). ParseMtkCoreConfig主要是解析mtk_omx_core.cfg
<1>. 第一个解析为name,第二个解析为role,第三个参数解析为lib_path(库的名称),第四个解析为max_inst。也就是主要是读取文件然后把内容存在gCoreComponents(mtk_omx_comp_type)这个结构体中。lib_path就是libomx的so库,
libomx路径:vendor/mediatek/proprietary/hardware/libomx
<2>. Modecodec.cpp初始化的时候调用initiateAllocateComponent,这个函数最后调用到了MtkOMXPlugin.cpp的makeComponentInstance函数,该函数调用的就是mGetHandle,也就是调用到了MtkOmxCore.cpp的Mtk_OMX_GetHandle函数,这个函数最后就是调用libomx对应得so库得MtkOmxComponentCreate函数。
6. MediaCodec设置回调
7. MediaCodec配置参数
MtkOmxVdecEx.cpp是vendor下面的代码。
8. 设置setInputSurface流程分析
最后调用ACodec.cpp的setupInputSurface,初始化GraphicBufferSource,部分代码如下:
9.开始编解码
以音频为例子,往编码器输入数据和解码后输出数据,在MtkOmxAudioDecBase.cpp可知,HandleEmptyThisBuffer这个是输入数据,HandleFillThisBuffer这个是解码后输出数据,在MtkOmxAudioCommandThread线程中,是通过管道来传递数据得。
在framework层会区分是哪个得数据输入进去编码得OMXNodeInstance.cpp:
10. 解码数据流程分析
OMX_FillThisBuffer
和OMX_EmptyThisBuffer
共同完成了OMX的buffer运转。OMX_FillThisBuffer是操作解码完后数据(PCM/YUV)的,OMX_EmptyThisBuffer是操作解码前(es)数据的。
OMX_FillThisBuffer介绍:
通过ACodec.cpp的 onOutputBufferDrained函数可知,最后的数据是填充到ANativeWindow中:
OMX_EmptyThisBuffer
数据流介绍:
在MediaCodec.cpp的init函数中初始化BufferChannel,并且设置回调
11.数据填充
在ACodec.cpp的allocateBuffers可以看到有输入和输出数据的填充和获取
来看下mCodec->allocateBuffersOnPort(kPortIndexOutput)数据的填充,用的是ashmem来实现匿名内存共享:
注:kernel的位置是kernel-4.4/drivers/misc/mediatek/videocodec/mt6771/videocodec_kernel_driver.c
参考:
1. Android MediaPlayer整体架构源码分析 -【MediaCodec编解码器插件模块化注册和创建处理流程】【Part 1】_小白兔LHao的博客-CSDN博客_findcodecbytype
2. 【Android 10 源码】深入理解 MediaCodec configure_TYYJ-洪伟的博客-CSDN博客_native_configure
3. https://blog.csdn.net/u012430727/category_10894882.html (1中内容也在里面)
4. 编解码抽象层OpenMax简介_runafterhit的博客-CSDN博客_openmax
5. Android MediaCodec的数据处理方式分析_Luckie stone的博客-CSDN博客
6. MediaCodec原理及使用_音视频开发老舅的博客-CSDN博客_mediacodec使用
7. Android 音视频开发打怪升级:音视频硬解码篇(1)音视频基础知识 - 知乎
8. OMX标准接口OMX_EmptyThisBuffer机制详解_丽萨的托马斯的博客-CSDN博客
9. OMX标准接口OMX_FillThisBuffer机制详解_丽萨的托马斯的博客-CSDN博客