Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程

转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52629449

前言:上篇文中分析到AwesomePlayer到OMX服务,曾介绍到,OMX服务主要完成三个任务: NodeInstance列表的管理,NodeInstance的操作, 事件的处理。最后这个事件处理就是今天放大看的内容。要一步一步一Codec,事件传递必不可少,看下今天的Agenda:

  • OMXCodec与OMX callback事件的处理时序图
  • 如何从OMX中dispatch到OMXCodec(附时序图)
  • 缓冲区更新过程
  • onMessage回调

OMXCodec与OMX callback事件的处理时序图

OMXCodec与OMX callback事件的处理时序图:

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第1张图片

从时序图看,首先我们要建立个OMXCodecObserver,该类是OMXCodec的内部类,在create函数中被创建,并把对应的OMXCodec加入都自己的观察范围内,具体代码如下:
framework/base/media/libstagefright/OMXCodec.cpp

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第2张图片

其次初始化它的callback事件和事件的派发处理函数
OMX主要的callback事件有哪些呢?
在framework/base/media/libstagefright/omx/OMXNodeInstance.cpp中的kCallbacks函数有如下定义:

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第3张图片

callback在哪定义呢?
看framework/base/media/libstagefright/omx/OMX.cpp中的

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第4张图片

即每个component对应一组callback事件。
这些callback由哪些函数返回呢?具体的定义在framework/base/media/libstagefright/openmax/OMX_Core.h

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第5张图片

有了callback事件,如何dispatch呢?其实我们在allocateNote函数已经定义好了我们的dispatch函数
mDispatchers.add(*node, new CallbackDispatcher(instance));

如何从OMX中dispatch到OMXCodec

有了oberser, callback event , callbackdispatcher,那么一个callback event 如何从OMX传到OMXCodec呢?
下面我们以emptybuffer流程来具体看下,时序图如下:

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第6张图片

从时序图上看:首先mVideoSource->read,实际上就是调用了OMXCodec::read,对应代码如下:

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第7张图片
Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第8张图片

接着调用drainInputBuffer,把输入通道中的所有输入缓存区,逐个传递给drainInputBuffer,即先把inputbuffer都读满,
然后一次性送给具体的component,让其慢慢解码,drainInputBuffer的实现如下:

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第9张图片

以上代码总结为:

  • 第一次执行OMXCodec::read时的操作。
  • 当整个编解码流程运行起来之后,会面临着一个输入\输出缓冲区更新的问题。

缓冲区更新过程

输入缓冲区更新过程:
如果一个输入缓冲区数据被读取完了,OpenMAX会触发事件omx_message::EMPTY_BUFFER_DONE通知上层,
在这个事件处理流程中,会根据发送来的bufferid找到对应的输入缓冲区,
然后把这个缓冲区传递给drainInputBuffer,继续往下执行。
如下:

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第10张图片

输出缓冲区更新过程:

  • 解码完毕后,OpenMAX组件触发omx_message::FILL_BUFFER_DONE,
    输出缓冲区会被传出交给上层使用(传递给surfaceflinger来显示),使用完后需要把这个缓存区重新交给OpenMax,
  • 上层使用完输出缓冲区后会调用MediaBuffer::release进行销毁,在这个接口中会把输出缓冲区的引用计数减1,
  • 然后调用signalBufferReturned,实际对应OMXCodec::signalBufferReturned接口,
  • 最后再下一层调用fillOutputBuffer,把这个缓冲区重新交给openMAX。

总结:这样就是通过第一次调用drainInputBuffers触发openMAX,然后后面依靠openMAX的事件驱动来完成数据的读取、解码操作。

下面我们用输出缓冲区为例,再放大下上面分析的流程:
openmax component解码完一帧之后,
会调用ppCallbacks->FillBufferDone,也就是调用了之前初始化好的OMX::OnFillBufferDone

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第11张图片

接着看下CallbackDispatcher的post函数

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第12张图片

接下来把这个msg开始分发出去

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第13张图片

onMessage回调

在onMessage方法中,进行通知回去

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第14张图片

通过调用OMXCodecObserver把msg通过onMessage函数接着传给OMXCodec。
代码如下:

Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程_第15张图片

通过上面的分析可以看到,虽然在OMX框架中 Input/OutPutPort上的buffer的生产和消费是异步,但是还是通过了一个Condition mBufferFilled来做同步。通过信号量机制来达到同步的目的。本质上是一个生产者/消费者模型。

第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

这里写图片描述

如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易

你可能感兴趣的:(Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程)