Android-StageFright之OpenMAX的实现

http://disanji.net/2011/03/07/stagefright-openmax0realization/


OMXCodec是一个MediaSource,完成数据的parse和decode。而OMXCodec则主要通过IOMX跨越OpenBinder机制操作OMX来实现。

重点介绍一下OMX。OMX主要完成三个任务,NodeInstance列表的管理,针对一个NodeInstance的操作以及事件的处理。

一、NodeInstance列表的管理。

这个主要包括NodeInstance的生成(allocateNode)和删除(freeNode)。其实就是对mDispatchers和 mNodeIDToInstance进行添加和删除。mNodeIDToInstance就是一个key为node_id,value为 NodeInstance的名值对列表。而mDispatchers就是一个key为node_id,value为 OMX::CallbackDispatcher的名值对列表。并且,一个NodeInstance都拥有一个 OMX::CallbackDispatcher。

二、NodeInstance节点的操作。

主要成员函数如下:

sendCommand

getParameter

setParameter

… …

fillBuffer

emptyBuffer

getExtensionIndex

这些方法执行时,都是先通过findInstance在mNodeIDToInstance列表中找到对应的NodeInstance,然后调用NodeInstance对应的方法。

三、事件处理

先看一下OMXNodeInstance.cpp中的这样一段代码:

1
2
3
4
5
OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
 
    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
 
};

它把三个OMXNodeInstance类的静态方法注册给了kCallbacks。而kCallbacks在哪里使用呢?看一下OMX.cpp中的allocateNode方法中的代码:

1
2
3
4
5
OMX_ERRORTYPE err = mMaster->makeComponentInstance(
 
            name, &OMXNodeInstance::kCallbacks,
 
            instance, &handle);

事件处理函数传给了组件ComponentInstance。当组件有事件发生时,就会调用OMXNodeInstance中这几个注册过的事件处理函数,而这几个函数又会去调用OMX中对应的函数,也就是下面这三个:

OnEvent、OnEmptyBufferDone、OnFillBufferDone。

这几个方法都采用相同的路子:根据node_id找到CallbackDispatcher,并把事件信息post过去。具体点儿,就是调用findDispatcher(node)->post(msg)。

这里不得不提一下CallbackDispatcher的实现机制。它内部开启了一个线程,使用了信号量机制。可以看一下OMX::CallbackDispatcher的属性:Condition mQueueChanged;

可以看出findDispatcher(node)->post(msg)是一个异步操作,只把msg给POST过去,不会等待事件处理完毕就返回了。那么CallbackDispatcher是怎么处理接收到的msg呢?看以下代码:

1
2
3
4
5
6
7
8
OMX::CallbackDispatcher::threadEntry()
 
          dispatch(msg);
 
 
     mOwner->onMessage(msg);
 
mObserver->onMessage(msg);

这个mObserver是哪来的?OMXCodec::Create中初始化IOMX时传入的。

1
2
3
4
5
sp<OMXCodecObserver> observer = new OMXCodecObserver;
 
... ...
 
omx->allocateNode(componentName, observer, &node);

这样算下来,事件最终还是跨越OpenBinder又传到了OMXCodec里面去,交给OMXCodecObserver了。

对节点的操作

NodeInstance的大部分方法的实现,如sendCommand等,都是通过OMX_Core.h中的宏定义间接调用 OMX_Component.h中的OMX_COMPONENTTYPE这个struct中的相应函数指针来完成。在这里提到的OMX_Core.h和 OMX_Component.h都是OpenMAX标准头文件。
原文链接:http://blog.csdn.net/a345017062/archive/2011/02/17/6190905.aspx

你可能感兴趣的:(struct,任务)