前面讲了OMX服务主要完成三个任务:NodeInstance列表的管理、NodeInstance的操作、事件的处理。最后这个事件处理就是放大要看的内容。要一步一步进行编解码操作,事件传递进行通信是必不可少的环节
OMXCodec与OMX callback事件的处理时序图

从时序图来看,首先要建立一个OMXCodecObserver类,该类是OMXCodec的内部类,在create函数中被创建,并把对应的OMXCodec加入自己的观察范围内,在Create中


其次初始化它的callback事件和事件的派发处理函数。那么OMX主要的callback事件有哪些呢?我们可以查看OMXNodeInstance.cpp的kCallbacks函数

callback在allocateNode定义


即每个Component对应一组回调事件,这些回调事件由哪些函数返回呢?查看OMX_Core.h



有了callback事件,如何dispatch?我们在allocateNode函数中已经定义好dispatch的函数了

如何从OMX中分发事件到OMXCodec
有了Observer、Callback Event、CallbackDispatcher,那么一个时间如何从OMX分发到OMXCodec?
以下以EmptyBuffer流程来具体看

首先查看mVideoSource->read,实际上就是调用OMXCodec::read函数

接下来看看drainInputBuffer的实现代码(截取部分)


在OMXCodec::fillOutputBuffer(BufferInfo *info)中会调用下图的函数

fillOutputBuffer作用是把输出通道中的输出缓冲区逐个传递给输出Buffer。在OMXCodec中的fillOutputBuffer函数调用mOMX->fillBuffer发送消息给OMX,相当于把缓冲区传递给OMX。以上是第一次执行OMXCodec::read时的操作,当整个编解码流程运行起来之后,会面临一个输入输出缓冲区更新的问题
缓冲区更新过程
输入缓冲区更新过程为,如果一个输入串冲去数据被读取完,OMX就触发事件omx_message::EMPTY_BUFFER_DONE通知上层,在这个事件处理流程中,会根据发送来的bufferid找到对应的输入缓冲区,然后把这个缓冲区传递给drainInputBuffer,继续往下执行,在OMXCodec::on_mseeage中有如下代码

输出缓冲区更新过程如下:解码完毕后,OMX组件触发omx_message::FILL_BUFFER_DONE,输出缓冲区会被传出交给上层使用(传递给SurfaceFlinger来显示),使用完后需要把这个缓冲区重新交给OMX。上层使用完输出缓冲区后会调用MediaBuffer::release销毁缓冲区,在这个接口中会给输出缓冲区的引用计数减一。然后调用signalBufferReturned,实际对应OMXCodec::signalBufferReturned接口。最后,下一层调用fillOutputBuffer函数,把这个缓冲区重新交给OMX
综上所述,这样就通过第一次调用drainInputBuffer触发了OMX,然后依靠OMX的事件驱动来完成数据的读取、解码操作

以输出缓冲区为例。OMX Component解码完一帧之后,会调用ppCallbacks->FillBufferDone,也就是调用了之前初始化好的OMX::OnFillBufferDone
然后查看post函数


接下来把这消息分发出去

消息回调
在消息回调中,主要通过onMessage函数处理消息,然后回调给上面调用OMX接口的类

通过调用OMXCodecObserver把消息通过onMessage函数传递给OMXCodec

在OMXCodec::on_message中的case omx_message::FILL_BUFFER_DONE

虽然在OMX框架中输入/输出端口上的Buffer的生产和消费是异步的,但还是用过一个Condition mBufferFilled来做了同步,通过信号量机制达到同步的目的。本质上是一个生产者/消费者模型。
Android中的OMX适配层是OMX IL层之上的封装层,在Android系统中被StageFright调用,也可以被其他部分调用
本文详细解析了Android中OpenMAX (OMX) 库的OMXCodec如何处理事件和管理缓冲区。OMXCodec通过Observer、CallbackEvent和CallbackDispatcher实现事件分发。OMX的主要callback事件包括EmptyBufferDone和FillBufferDone,分别对应输入和输出缓冲区的处理。在解码过程中,OMXComponent触发事件,如FillBufferDone,通知上层解码完成,输出缓冲区可用。OMXCodec通过条件变量mBufferFilled实现异步操作的同步。整个流程涉及输入缓冲区的填充、输出缓冲区的填充和释放,形成一个生产者/消费者的模型,确保数据读取和解码的顺畅进行。
1361

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



