刘星宇这个名字怎么样:Android StageFright之OpenMAX的實現
Android StageFright之OpenMAX的實現
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中的這樣一段代碼:
OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
&OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
};
它把三個OMXNodeInstance類的靜態方法註冊給了kCallbacks。而kCallbacks在哪裡使用呢?看一下OMX.cpp中的allocateNode方法中的代碼:
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呢?看以下代碼:
OMX::CallbackDispatcher::threadEntry()
|
dispatch(msg);
|
mOwner->onMessage(msg);
|
mObserver->onMessage(msg);
這個mObserver是哪來的?OMXCodec::Create中初始化IOMX時傳入的。
sp 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標準標頭檔