架構#
MediaCodec 的 Decoder 現在有兩種方式,分別為 OMX 和 Codec2,Android 目前全面在替換 OMX。
OMX#
開放多媒體加速層(Open Media Acceleration,縮寫為 OpenMAX)。一個免費的跨平台抽象軟體層,用於加速在嵌入式和移動設備上的多媒體應用程式中捕獲和呈現音頻、視頻和圖像。
分層#
OpenMAX AL (應用層)#
OpenMAX-AL 提供了應用程式和多媒體中介軟體之間的標準化介面,其中多媒體中介軟體提供了執行預期 API 功能所需的服務。
The OpenMAX AL 1.1 Reference Guide.
OpenMAX IL (整合層)#
OpenMAX IL(整合層)API 定義了一個標準化的媒體元件介面,使開發人員和平台提供商能夠與硬體或軟體中實現的多媒體編解碼器進行整合和通信。
OpenMAX DL (開發層)#
OpenMAX-DL 定義的 API,包含一套全面的音頻、視頻和圖像功能,這些功能可以由晶片供應商在新處理器上實現和優化,然後由編解碼器供應商用來編寫各種編解碼器功能。
Android 實現#
主要是實現 OpenMax IL 層:
- 編解碼驅動程式
- 根據 OpenMax IL 層的標準頭檔實現不同功能的元件,Android 封裝了後實現了 OpenMax 的適配層介面,供多媒體引擎調用
OpenMAX IL 介面與實現#
// frameworks/native/headers/media_plugin/media/openmax
OMX_Types.h: OpenMax IL 的資料類型定義
OMX_Core.h: OpenMax IL 核心 API
OMX_Compoenet.h: OpenMax IL 元件相關的 API
OMX_Audio.h: 音頻相關的常數和資料結構
OMX_IVCommon.h: 圖像和視頻公共的常數和資料結構
OMX_Image.h: 圖像相關的常數和資料結構
OMX_Video.h: 視頻相關的常數和資料結構
OMX_Other.h: 其他資料結構(av 同步)
OMX_Index.h: OpenMax IL 定義的資料結構索引
OMX_ContentPipe.h 內容的管道定義
重點看 OMX_Compoenet.h
中的 OMX_COMPONENTTYPE 結構體
typedef struct OMX_COMPONENTTYPE
{
/* 結構體大小 */
OMX_U32 nSize;
/* 版本號 */
OMX_VERSIONTYPE nVersion;
/* 元件的私有資料指針 */
OMX_PTR pComponentPrivate;
/* IL Client 設置的指針,用於保存它的私有資料,傳回所有的回調函數 */
OMX_PTR pApplicationPrivate;
/* 獲取元件的版本 */
OMX_ERRORTYPE (*GetComponentVersion)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_OUT OMX_STRING pComponentName,
OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
OMX_OUT OMX_UUIDTYPE* pComponentUUID);
/* 發送命令 */
OMX_ERRORTYPE (*SendCommand)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_COMMANDTYPE Cmd,
OMX_IN OMX_U32 nParam1,
OMX_IN OMX_PTR pCmdData);
/* 獲取參數 */
OMX_ERRORTYPE (*GetParameter)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_INOUT OMX_PTR pComponentParameterStructure);
/* 設置參數 */
OMX_ERRORTYPE (*SetParameter)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentParameterStructure);
/* 獲取配置 */
OMX_ERRORTYPE (*GetConfig)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_INOUT OMX_PTR pComponentConfigStructure);
/* 設置配置 */
OMX_ERRORTYPE (*SetConfig)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentConfigStructure);
/* 轉換成OMX結構的索引 */
OMX_ERRORTYPE (*GetExtensionIndex)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_STRING cParameterName,
OMX_OUT OMX_INDEXTYPE* pIndexType);
/* 獲取元件當前的狀態 */
OMX_ERRORTYPE (*GetState)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_OUT OMX_STATETYPE* pState);
/* 用於連接到另一個元件 */
OMX_ERRORTYPE (*ComponentTunnelRequest)(
OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_U32 nPort,
OMX_IN OMX_HANDLETYPE hTunneledComp,
OMX_IN OMX_U32 nTunneledPort,
OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup);
/* 為某個端口使用 Buffer */
OMX_ERRORTYPE (*UseBuffer)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
OMX_IN OMX_U32 nPortIndex,
OMX_IN OMX_PTR pAppPrivate,
OMX_IN OMX_U32 nSizeBytes,
OMX_IN OMX_U8* pBuffer);
/* 為某個端口分配 Buffer */
OMX_ERRORTYPE (*AllocateBuffer)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer,
OMX_IN OMX_U32 nPortIndex,
OMX_IN OMX_PTR pAppPrivate,
OMX_IN OMX_U32 nSizeBytes);
/* 將某個端口 Buffer 釋放 */
OMX_ERRORTYPE (*FreeBuffer)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_U32 nPortIndex,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
/* 讓元件消耗這個 Buffer */
OMX_ERRORTYPE (*EmptyThisBuffer)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
/* 讓元件填充這個 Buffer */
OMX_ERRORTYPE (*FillThisBuffer)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
/* 設置回調函數 */
OMX_ERRORTYPE (*SetCallbacks)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_CALLBACKTYPE* pCallbacks,
OMX_IN OMX_PTR pAppData);
/* 反初始化元件 */
OMX_ERRORTYPE (*ComponentDeInit)(
OMX_IN OMX_HANDLETYPE hComponent);
/* 使用 EGL Image */
OMX_ERRORTYPE (*UseEGLImage)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
OMX_IN OMX_U32 nPortIndex,
OMX_IN OMX_PTR pAppPrivate,
OMX_IN void* eglImage);
OMX_ERRORTYPE (*ComponentRoleEnum)(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_OUT OMX_U8 *cRole,
OMX_IN OMX_U32 nIndex);
} OMX_COMPONENTTYPE;
OpenMAX 適配層#
// frameworks/av/media/libmedia/include/media/IOMX.h
class IOMXNode : public IInterface {
public:
DECLARE_HYBRID_META_INTERFACE(OMXNode, IOmxNode);
typedef IOMX::buffer_id buffer_id;
virtual status_t freeNode() = 0;
virtual status_t sendCommand(
OMX_COMMANDTYPE cmd, OMX_S32 param) = 0;
virtual status_t getParameter(
OMX_INDEXTYPE index, void *params, size_t size) = 0;
virtual status_t setParameter(
OMX_INDEXTYPE index, const void *params, size_t size) = 0;
virtual status_t getConfig(
OMX_INDEXTYPE index, void *params, size_t size) = 0;
virtual status_t setConfig(
OMX_INDEXTYPE index, const void *params, size_t size) = 0;
virtual status_t setPortMode(
OMX_U32 port_index, IOMX::PortMode mode) = 0;
virtual status_t prepareForAdaptivePlayback(
OMX_U32 portIndex, OMX_BOOL enable,
OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) = 0;
virtual status_t configureVideoTunnelMode(
OMX_U32 portIndex, OMX_BOOL tunneled,
OMX_U32 audioHwSync, native_handle_t **sidebandHandle) = 0;
virtual status_t getGraphicBufferUsage(
OMX_U32 port_index, OMX_U32* usage) = 0;
virtual status_t setInputSurface(
const sp<IOMXBufferSource> &bufferSource) = 0;
virtual status_t allocateSecureBuffer(
OMX_U32 port_index, size_t size, buffer_id *buffer,
void **buffer_data, sp<NativeHandle> *native_handle) = 0;
virtual status_t useBuffer(
OMX_U32 port_index, const OMXBuffer &omxBuf, buffer_id *buffer) = 0;
virtual status_t freeBuffer(
OMX_U32 port_index, buffer_id buffer) = 0;
virtual status_t fillBuffer(
buffer_id buffer, const OMXBuffer &omxBuf, int fenceFd = -1) = 0;
virtual status_t emptyBuffer(
buffer_id buffer, const OMXBuffer &omxBuf,
OMX_U32 flags, OMX_TICKS timestamp, int fenceFd = -1) = 0;
virtual status_t getExtensionIndex(
const char *parameter_name,
OMX_INDEXTYPE *index) = 0;
virtual status_t dispatchMessage(const omx_message &msg) = 0;
};
MediaCodec#
初始化 MediaCodec
ACodec 的狀態圖#
OMX 架構基於這個狀態圖來完成相關操作。