SuperIC社区_

标题: 【stagefrightplayer】4 OMX Codec介绍 [打印本页]

作者: 果果    时间: 2016-9-22 19:34
标题: 【stagefrightplayer】4 OMX Codec介绍
OMX Codec是stagefrightplayer中负责解码的模块。
由于遵循openmax接口规范,因此结构稍微有点负责,这里就依照awesomeplayer中的调用顺序来介绍。
主要分如下几步:
1 mClient->connect
2 InitAudioDecoder & InitVideoDecoder
3 消息通信机制模型的介绍
4 解码过程介绍
先看下类图

这里OMX Codec是以service的方式提供服务的。Awesomeplayer中通过mOmx(IOMX) 作为客户端通过binder方式与OMX 通信完成解码的工作
下面一句具体代码分析
1 mClient->connect

在awesomeplayer的构造函数中调用,具体代码如下
[html] view plaincopy



看下具体实现
[html] view plaincopy



这里主要就是通过binder机制与mediaplayerservice通信来完成,具体实现看mediaplayerservice
[html] view plaincopy




主要就是构造一个OMX对象返回给上层保存在mClient的IOMX对象mOmx中
看下构造函数都做了啥
[html] view plaincopy



在构造函数中又调用了OMXMaster的构造函数,代码如下
[html] view plaincopy



这里OMXMaster可以看成是解码器的入口,通过makeComponentInstance建立解码器的实例之后就可以进行解码操作了。
这里我们以软件解码器插件为例来看整个流程,主要是addPlugin(newSoftOMXPlugin);先看SoftOMXPlugin构造函数
[html] view plaincopy



是空的~~
再看下addPlugin代码
[html] view plaincopy



这里传入的plugin参数时上面SoftOMXPlugin 构造函数产生的实例
从代码可以看出主要是将enumerateComponents枚举出来的各种解码器存放在成员变量mPluginByComponentName中,类型为 KeyedVector
看下enumerateComponents实现
[html] view plaincopy



[html] view plaincopy




这里enumerateComponents主要就是将数组kComponents中的以为index下标的plugin传递出来
这里只是将插件名字返回最终存储在mPluginByComponentName列表中
后面还会通过makeComponentInstance产生实际的解码器实例,后面再详细看
至此mClient->connect()就结束了。
这里的主要工作就是通过getOMX()在mediaplayerservice端构造一个OMX实例,并返回给mClient的IOMX成员mOmx中
而且在OMX的构造函数中调用OMXMaster的构造函数,可以通过makeComponentInstance 建立实际的解码器实例。
2 InitAudioDecoder & InitVideoDecoder

awesomeplayer构造函数结束后,在setDataSource之后会调用prepare方法,其实现中会调用initAudioDecoder和initVideoDecoder
由于在setDataSource中已经拿到了对应的解码器信息,因此此处initAudioDecoder 便可以构造实际的解码器了。以audio为例
[html] view plaincopy



这里只列出的主要操作,下面依次来看OMXCodec::Create和mAudioSource->start的主要工作
代码比较多,我们这里主要将重要的代码列出,无关代码省略
[html] view plaincopy



下面依次来看每个过程
2.1 findMatchingCodecs
先看下代码
[html] view plaincopy




从代码可以看到主要就是从MediaCodecList找到与传入的matchComponentName对应的解码器
MediaCodecList 的实现不看了,感兴趣的看下,主要就是从/etc/media_codecs.xml解析出支持的解码器并匹配出对应的解码器
举例:
这里需要注意的是在前面我们看到 kComponents 数组定义了支持的解码器,这里/etc/media_codecs.xml 也列出了对应的解码器,这里名字要对应上
这里找到符合条件的解码器便通过matchingCodecs->add()添加一个项,并将各个成员赋值,主要是name
最终符合条件的插件便都放在了matchingCodecs列表中
2.2 allocateNode
这里主要有如下重要代码   
    sp observer = new OMXCodecObserver;
    IOMX::node_id node = 0;
    status_t err = omx->allocateNode(componentName, observer, &node);
observer的作用主要用于消息传递。
这里allocateNode主要是调用service端的OMX类来完成工作(省略中间的binder操作)
[html] view plaincopy



首先构造了OMXNodeInstance,封装了传入的observer参数,作为消息传递的载体
调用mMaster->makeComponentInstance生成实际的解码器实例
生成node_id
将node_id与实际的解码器handle保存在instance中,最终instance会保存在OMX的mLiveNodes列表中
这样OMXCodec就可以通过OMXNodeInstance与解码器通信了,具体参考下面通信模型。
后面会介绍通信过程。这里重点讲解一下与解码器的操作
上面代码中通过mMaster->makeComponentInstance创建了解码器的实例,这里我们以android自带的mp3 解码器为例来讲解
通过上面介绍mp3解码器对应的项为(/etc/media_codecs.xml):
而findMatchingCodecs 传入的字符串为:audio/mpeg 以此为依据进行匹配
这里找到对应的解码器后,解码器的名字为:OMX.google.mp3.decoder
这样便可以通过查表(数组kComponents )得到实际的解码器了
实际的mp3解码器代码文件为:framework/av/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
调用的方法为:mMaster->makeComponentInstance 实际代码是
[html] view plaincopy



主要是调用插件的makeComponentInstance方法
这里插件是通过OMXMaster构造函数addPlugin(new SoftOMXPlugin);加载的插件,因此这里makeComponentInstance 是SoftOMXPlugin 的方法
看下具体实现
[html] view plaincopy



这里主要是通过枚举kComponents找到对应的解码器记录
{ "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },
这里可以看到每个库都是以.so的方式提供的,命名符合如下规则:libstagefright_soft_mp3dec.so
通过dlopen加载后通过dlsym找到createSoftOMXComponent方法并执行,这里每个解码器都应该实现此函数


作者: Robby.zou    时间: 2016-9-28 11:02





欢迎光临 SuperIC社区_ (/) Powered by Discuz! X3.3