OMXCodec是一个codec框架,实现者可以在这个框架中实现各种解码方式,包括硬件解码。OMXMaster 负责OMX中编解码器插件管理,软件解码和硬件解码都是使用OMX标准,挂载plugins的方式来进行管理。软解通过 addPlugin(new SoftOMXPlugin);会把这些编解码器的名字都放在mPluginByComponentName中。硬件编解码是通过 addVendorPlugin();加载libstagefrighthw.so.各个芯片平台可以遵循openmax 标准,生成libstagefrighthw.so的库来提供android应用。
OMXMaster::OMXMaster()
:mVendorLibHandle(NULL) {
addVendorPlugin();
addPlugin(newSoftOMXPlugin);
}
在allocateNode的时候,SoftOMXPlugin调用makeComponentInstance,遍历所有的libstagefright_soft_*.so库,创建软件component,并将component和plugin一起存入mPluginByInstance。
OMX解码的方式很像流水线,由两个线程(工人)负责操作,一个decoder/encoder线程,一个dispatcher线程。对buffer的操作如下:OMXCodec使用draininputbuffer试图解码,调用IOMX的emptyBuffer,然后调到OMX的emptyBuffer,然后OMX找到node,调用OMX_EmptyThisBuffer,然后发消息KwhatEmptyThisBuffer给SoftComponent,此时进入编解码线程。component收到该命令后会读取inputport buffer中的数据,调用onQueueFilled,将其组装成帧进行解码,读取buffer中的数据完成后会调用EmptyBufferDone通知OMXNodeInstance,然后调用OMXNodeInstance中注册好的回调onEmptyBufferDone,然后调到OMX里的OnEmptyBufferDone。OMX发消息EMPTY_BUFFER_DONE给对应的Dispather线程。在Dispather的on_message中,调用drainInputBuffer。compoment使用EmptyBufferDone通知OMXCodec已完成inputportbuffer的读取,OMXCodec收到该命令后会通过mVideoTrack读取新的视频buffer到input port的buffer中,并调用OMX_EmptyThisBuffer通知component。OMXCodec使用OMX_FillThisBuffer传递空的bffer给component用于存储解码后的帧,component收到该命令后将解码好的帧数据复制到该buffer上,然后调用FillBufferDone通知OMXCodec,compoment使用FillBufferDone通知OMXCodec已完成outputportbuffer的填充OMXCodec收到该命令后将解码好的帧传递给mISurface进行图像绘制,绘制完毕后使用OMX_FillThisBuffer通知component有空的buffer可填充。OnEmptyBufferDone由Decoder线程执行,而EMPTY_BUFFER_DONE由Dispather线程执行,二者通过message进行通信。
一个StageFrightPlayer对应一个AwesomePlayer,若媒体源既有视频又有音频,则会创建两个OMXCodec实例,若只有视频会音频一样,则只创建一个OMXCodec实例。
播放音频的是AudioPlayer,在initAudioDecoder里,调用OMXCodec::Create拿到mAudioSource,在需要软件解码情况下是mOmxSource,在offload模式下(无需软件解码)直接用mAudioTrack。Audio和Video都有一个TimedEventQueue,start的时候都create了一个thread,入口函数是threadEntry,这是个典型的事件驱动模型,对于一些耗时的操作,一个线程产生事件,通知另一个线程去处理事件,以保证第一个线程响应的及时性。TimedEventQueue就是一个新线程,
AwesomeEvent实现了Event里的抽象方法fire,即(mPlayer->*mMethod)()。AwesomePlayer在prepareAsync_l时,就是create了一个AwesomeEvent,并放入mQueue。然后在TimedEventQueue里去异步的执行。
在play_l中,若mAudioSource存在,则创建createAudioPlayer_l,并且mAudioPlayer->setSource(mAudioSource);然后startAudioPlayer_l。
AT的callback函数MediaPlayerService::AudioOutput::CallbackWrapper会调到AudioPlayer里的AudioSinkCallback,然后在fillBuffer里调用到了mSource->read(&mInputBuffer,&options);最终到了OMXCodec里的read,或者是mAudioTrack里的read。在调用OMXCodec中read的情况下,可以看出mInputBuffer其实是个输出参数,然后把Codec里的输出Buffer赋值给mInputBuffer。而这些Buffer都是在allocateBuffersOnPort里申请的。在InitOMXParams和initPort进行参数设置,一般都会分配4个InputBuffer,4个OutputBuffer。最后memcpyoutputBuffer里的数据到AT和AF的ShareBuffer。在调用mAudioTrack的read的情况下,mInputBuffer同样也是个输出参数,直接获取MediaBufferGroup里的MediaBuffer,最后也是memcpy到AT和AF的ShareBuffer。
需要软解码的Buffer数据交换
无需软解码的Buffer数据交换
869



被折叠的 条评论
为什么被折叠?



