架构#
MediaCodec 的 Decoder 现在有两种方式,分别为 OMX 和 Codec2,Android 目前全面在替换 OMX。
OMX#
开放多媒体加速层(Open Media Acceleration,缩写为 OpenMAX). 一个免费的跨平台抽象软件层,用于加速在嵌入式和移动设备上的多媒体应用程序中捕获和呈现音频、视频和图像。
分层#
OpenMAX AL (Application Layer)#
OpenMAX-AL 提供了应用程序和多媒体中间件之间的标准化接口,其中多媒体中间件提供了执行预期 API 功能所需的服务。
The OpenMAX AL 1.1 Reference Guide.
OpenMAX IL (Integration Layer)#
OpenMAX IL(集成层)API 定义了一个标准化的媒体组件接口,使开发人员和平台提供商能够与硬件或软件中实现的多媒体编解码器进行集成和通信。
OpenMAX DL (Development Layer)#
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 架构基于这个状态图来完成相关操作。