OpenMAX/IL: OMX IL 学习笔记【3】- 头文件、数据结构与接口

参考自:https://blog.csdn.net/blue_xx/article/details/46778133

1. 导读

该篇文章对OpenMAX的数据结构和接口进行概要描述,包括OpenMAX的一些官方定义的头文件介绍,以及各种结构体数据介绍:比如OpenMAX组件结构体描述、PORT端口结构体描述。并对组件内部线程的大概结构以及组织方式进行介绍,本文章的目标是可以实现一个有基本功能的组件。

该文章中提到的IL Client可以看作是组件的使用者,负责组件的创建、销毁、命令控制等等。注意本文章需要结合例程代码去看,否则会觉得本文不知所云。代码参考OpenMAX/IL: OMX IL 学习笔记【2】- 组件一文中的OpenMAX IL sample下载链接

2. 头文件

[头文件下载地址]:https://www.khronos.org/files/openmax/headers/omx_il_v1/omx_il_v1.zip

OpenMAX官方提供了一系列的头文件,里面定义了包括组件结构体、音视频相关结构体、命令控制API等等。这些定义可以使得Client控制音频(audio)、视频(video)、图像(image)等类型的多媒体组件。其它(other)域则提供了一些额外的组件功能,比如音视频同步(可以用clock实现)。

文件描述
OMX_Types.h数据类型,里面定义了组件类型、输入输出等
OMX_Core.hIL层的核心API,有命令枚举、状态枚举、组件注册/初始化等等
OMX_Component.h组件相关的API,有端口类型与定义、组件回调函数成员定义等
OMX_Audio.h与音频相关的常量和结构体定义
OMX_IVCommon.h图像与视频通用的一些常量和结构体定义
OMX_Video.h视频相关的常量和结构体定义
OMX_VideoExt.h视频相关的常量和数据结构,是对OMX_Video.h的补充扩展
OMX_Image.h图像相关的常量和结构体定义
OMX_Other.h其它部分的结构体定义 (包含A/V同步)
OMX_Index.hOpenMAX定义的数据结构索引
OMX_IndexExt.hOpenMax 定义的数据结构扩展索引
OMX_ContentPipe.h内容的管道定义

值得注意的是,在OMX_Types.h文件里面有这么几个定义:OMX_INOMX_OUTOMX_INOUT,分别代表了仅输入、仅输出、输入输出。这些宏定义并没有对应的值,只是个空的定义,常用于标识函数的参数传递方向,便于函数调用者(一般是IL Client)搞清楚哪些参数是输入的,哪些参数是输出的,避免一些低级的编程错误。这种形式的用法在其它的编程当中也可以借鉴,有了标识的函数参数会使得函数调用者更加地省心,避免在函数使用的时候出现一些不必要的错误。

提示:OpenMax标准只有头文件,没有标准的库,设置没有定义函数接口。对于实现者,需要实现的主要是包含函数指针的结构体。

3. 数据结构

3.1 数据类型(OMX_Core.h)

主要是一些枚举变量结构体原型,其类型主要如下所示:

在这里插入图片描述

OMX_Types枚举变量

可以看出来,其主要分为以下类型:

  • OMX_BUFFERSUPPLIERTYPE:用于组件内部端口数据流标识。

  • OMX_COMMANDTYPE:命令相关的枚举,用于Client对组件的命令控制。

  • OMX_STATETYPE:组件状态相关的枚举,用于组件状态标识。

  • OMX_ERRORTYPE:错误相关的枚举,类似于C库的错误状态集,用于标识组件内部或者Client的出错状态。

  • OMX_EVENTTYPE:事件相关的枚举,用于组件内部向Client发送事件通知。

3.2 OMX_COMMANDTYPE

枚举成员意义参数
OMX_CommandStateSet改变组件的状态OMX_STATETYPE-要转换的状态
OMX_CommandFlush冲洗组件内部某个端口的buffer队列OMX_U32-端口号
OMX_CommandPortDisable禁止使能组件内部的某个端口OMX_U32-端口号
OMX_CommandPortEnable使能组件内部某个端口OMX_U32-端口号
OMX_CommandMarkBuffer标记一个buffer并指定哪个组件会触发收到的事件标记OMX_U32-端口号(还有命令数据OMX_MARKTYPE*-buffer与组件)

对于Client来说,命令的发送是非阻塞的,当Client把命令发送给组件时,组件会把收到的命令放到一个命令队列(或管道)里面,然后函数就会立刻返回了。当组件内部取出某个命令并执行完毕之后会进行一个事件回调来通知Client某个命令已经执行完毕,并返回命令执行的状态(失败/成功)。

根据OMX标准,定义了如下所示的组件状态集,并且它们之间还有如下的状态转换条件:

在这里插入图片描述

组件状态转换

对于这几种状态的说明如下:

  • OMX_StateLoaded:组件已经被加载,但是还没有分配相关的资源。

  • OMX_StateIdle:组件已经分配了相关的全部资源,但是没有传输buffer,也不处理buffer。

  • OMX_StateExecuting:组件开始传输buffer,并且处理buffer(如果buffer可用的话)。

  • OMX_StatePause:组件暂停buffer处理(有可能从暂停的地方恢复数据的处理),该状态没有定义数据是否暂停传输,所以可以依照具体的组件实现来定,可以传输也可以不传输。

  • OMX_StateWaitForResources:组件正等待资源可用(此时资源还未被分配)。

  • OMX_StateInvalid:组件发生了不可修复的错误,此时需要转入该状态。

举例说明下传输buffer、处理buffer、拥有资源三者的区别:

  • 拥有资源:buffer的缓存(内存空间),比如视频数据,在进行数据传输处理之前需要分配相应数量的buffer内存空间用来存放传输的数据,当相应的内存被分配之后,就说该组件拥有资源(has resources)。

  • 传输buffer:组件之间开始传递buffer,比如将buffer从解码组件传输到显示组件,完成数据的组件间转移,称之为传输buffer。

  • 处理buffer:这是对单一组件内部来说的,比如编码组件,它需要接收buffer,然后对接收到的buffer进行编码,这个编码的过程称之为处理buffer,解码组件可同理推之。

当然,在实际的编程实现当中在组件内部也不必拘泥于这几种状态,比如可以新增一些状态或者去掉一些状态,比如很大可能OMX_StateWaitForResources状态就用不到,因为资源分配总是可以在Loaded或者Idle状态中分配完成,而这两个状态中间没必要增加OMX_StateWaitForResources这样一个状态。另外对于各个状态下的数据处理也可以灵活运用,比如OMX_StatePause状态下就可以选择传输或者不传输buffer,如果传输的话就需要把buffer缓存起来,等待组件恢复运行时继续处理(可能会发生缓冲区满的情况,需要做相应的措施)。

3.3 OMX_ERRORTYPE

OMX所有的API返回错误值都在该枚举类型里面定义,该枚举类型里面包含了绝大多数的错误状态类型(实际应用当中基本够用)。当然,如果觉得还是需要自己定义错误值的话也可以,从0x90000000到0x9000FFFF这个范围内就是自定义错误的枚举值范围。

举例部分错误值的意义(错误值定义比较多),其余的在头文件里面可以看到相关错误值的详细意义注释:

  • OMX_ErrorNone:没有错误,正确返回。

  • OMX_ErrorInvalidComponent:组件没有初始化函数或者初始化函数调用返回出错。

  • OMX_ErrorUnderflow:buffer为空。

3.4 OMX_EVENTTYPE

组件通过回调机制向IL Client发送事件消息,事件消息的类型如下:

  • OMX_EventCmdComplete:组件命令执行完毕,每一个来自Client的命令被执行完毕之后,组件都会向Client返回一个事件,以此表明命令的执行结果。注意:OMX_StateInvalid状态不会产生此事件消息。

  • OMX_EventError:组件发生了一个错误。错误值会作为一个参数返回给Client,错误值就是错误枚举类型里面的成员。

  • OMX_EventMark:一个buffer标记以及到达指定的组件,此时组件会返回给Client一个此事件消息,并且Client还会通过私有的结构体指针成员获取到相关的数据信息。

  • OMX_EventPortSettingsChanged:组件改变端口的设置。比如编码组件在运行的过程中发现要编码的数据流宽高发生了变化,此时就会改变端口的宽高设置。

  • OMX_EventBufferFlag:检测到bit流结束时由组件内部产生。当输出端口检测到buffer的nFlags被设置为OMX_BUFFERFLAG_EOS,在返回的参数中,nData1指定输出端口的portindex,nData2则是传递nFlags给Client。如果组件是sink类型的(数据流终点),则nData1传递的是输入端口的portindex。

  • OMX_EventResourcesAcquired:组件已经接收到了相关资源(资源分配),此时状态正从OMX_StateWaitForResources转换为OMX_StateIdle state。

3.5 OMX_BUFFERSUPPLIERTYPE

用来指明tunnel(建立隧道链接)的port中哪个是数据提供者(buffer supplier port),buffer提供者port可能有属于自己的独立分配的buffer内存空间,也可能与同一组件内部其它的port共享同一个buffer内存空间,由此可见该枚举类型用于隧道链接的建立设置(tunnel setup)。该枚举类型成员有如下几个:

  • OMX_BufferSupplyUnspecified:未指定buffer提供者端口,或者根本就没有(不需要)buffer提供者。

  • OMX_BufferSupplyInput:输入端口充当buffer提供者。

  • OMX_BufferSupplyOutput:输出端口充当buffer提供者。

4. 组件实例相关结构体

4.1 OMX_COMPONENTREGISTERTYPE

原型:

typedef struct OMX_COMPONENTREGISTERTYPE
{
  const char          * pName;       /* Component name, 128 byte limit (including '\0') applies */
  OMX_COMPONENTINITTYPE pInitialize; /* Component instance initialization function */
} OMX_COMPONENTREGISTERTYPE;

该结构体负责组件的注册工作,pName是组件的名字,通常是唯一的,pInitialize是组件的初始化函数,该成员类型的定义是:typedef OMX_ERRORTYPE (* OMX_COMPONENTINITTYPE)(OMX_IN OMX_HANDLETYPE hComponent); 由此可见hComponent被提前分配,然后被传递给初始化回调函数,在初始化回调函数里面进行整个组件资源分配、环境的初始化工作。

通常情况下,该结构体总是以数组成员的方式被定义在一个OMX_ComponentRegistered[]类型的数组当中,属于全局、静态的。要创建一个组件时需要根据组件的名字来在数组里面进行匹配,如果匹配到相关的数组成员,就调用初始化回调函数正式初始化创建组件。

4.2 OMX_COMPONENTTYPE

在OMX_Component.h文件中定义了OMX_COMPONENTTYPE类型数据结构,OMX IL 用它来描述一个component,其中包含了可供调用的函数方法。

typedef struct OMX_COMPONENTTYPE
{
    /** The size of this structure, in bytes.  It is the responsibility
        of the allocator of this structure to fill in this value.  Since
        this structure is allocated by the GetHandle function, this
        function will fill in this value. */
    OMX_U32 nSize;

    /** nVersion is the version of the OMX specification that the structure
        is built against.  It is the responsibility of the creator of this
        structure to initialize this value and every user of this structure
        should verify that it knows how to use the exact version of
        this structure found herein. */
    OMX_VERSIONTYPE nVersion;

    /** pComponentPrivate is a pointer to the component private data area.
        This member is allocated and initialized by the component when the
        component is first loaded.  The application should not access this
        data area. */
    OMX_PTR pComponentPrivate;

    /** pApplicationPrivate is a pointer that is a parameter to the
        OMX_GetHandle method, and contains an application private value
        provided by the IL client.  This application private data is
        returned to the IL Client by OMX in all callbacks */
    OMX_PTR pApplicationPrivate;

    /** refer to OMX_GetComponentVersion in OMX_core.h or the OMX IL
        specification for details on the GetComponentVersion method.
     */
    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);

    /** refer to OMX_SendCommand in OMX_core.h or the OMX IL
        specification for details on the SendCommand method.
     */
    OMX_ERRORTYPE (*SendCommand)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_COMMANDTYPE Cmd,
            OMX_IN  OMX_U32 nParam1,
            OMX_IN  OMX_PTR pCmdData);

    /** refer to OMX_GetParameter in OMX_core.h or the OMX IL
        specification for details on the GetParameter method.
     */
    OMX_ERRORTYPE (*GetParameter)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_INDEXTYPE nParamIndex,
            OMX_INOUT OMX_PTR pComponentParameterStructure);

    /** refer to OMX_SetParameter in OMX_core.h or the OMX IL
        specification for details on the SetParameter method.
     */
    OMX_ERRORTYPE (*SetParameter)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_INDEXTYPE nIndex,
            OMX_IN  OMX_PTR pComponentParameterStructure);

    /** refer to OMX_GetConfig in OMX_core.h or the OMX IL
        specification for details on the GetConfig method.
     */
    OMX_ERRORTYPE (*GetConfig)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_INDEXTYPE nIndex,
            OMX_INOUT OMX_PTR pComponentConfigStructure);

    /** refer to OMX_SetConfig in OMX_core.h or the OMX IL
        specification for details on the SetConfig method.
     */
    OMX_ERRORTYPE (*SetConfig)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_INDEXTYPE nIndex,
            OMX_IN  OMX_PTR pComponentConfigStructure);

    /** refer to OMX_GetExtensionIndex in OMX_core.h or the OMX IL
        specification for details on the GetExtensionIndex method.
     */
    OMX_ERRORTYPE (*GetExtensionIndex)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_STRING cParameterName,
            OMX_OUT OMX_INDEXTYPE* pIndexType);

    /** refer to OMX_GetState in OMX_core.h or the OMX IL
        specification for details on the GetState method.
     */
    OMX_ERRORTYPE (*GetState)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_OUT OMX_STATETYPE* pState);

    /** The ComponentTunnelRequest method will interact with another OMX
        component to determine if tunneling is possible and to setup the
        tunneling.  The return codes for this method can be used to
        determine if tunneling is not possible, or if tunneling is not
        supported.

        Base profile components (i.e. non-interop) do not support this
        method and should return OMX_ErrorNotImplemented

        The interop profile component MUST support tunneling to another
        interop profile component with a compatible port parameters.
        A component may also support proprietary communication.

        If proprietary communication is supported the negotiation of
        proprietary communication is done outside of OMX in a vendor
        specific way. It is only required that the proper result be
        returned and the details of how the setup is done is left
        to the component implementation.

        When this method is invoked when nPort in an output port, the
        component will:
        1.  Populate the pTunnelSetup structure with the output port's
            requirements and constraints for the tunnel.

        When this method is invoked when nPort in an input port, the
        component will:
        1.  Query the necessary parameters from the output port to
            determine if the ports are compatible for tunneling
        2.  If the ports are compatible, the component should store
            the tunnel step provided by the output port
        3.  Determine which port (either input or output) is the buffer
            supplier, and call OMX_SetParameter on the output port to
            indicate this selection.

        The component will return from this call within 5 msec.

        @param [in] hComp
            Handle of the component to be accessed.  This is the component
            handle returned by the call to the OMX_GetHandle method.
        @param [in] nPort
            nPort is used to select the port on the component to be used
            for tunneling.
        @param [in] hTunneledComp
            Handle of the component to tunnel with.  This is the component
            handle returned by the call to the OMX_GetHandle method.  When
            this parameter is 0x0 the component should setup the port for
            communication with the application / IL Client.
        @param [in] nPortOutput
            nPortOutput is used indicate the port the component should
            tunnel with.
        @param [in] pTunnelSetup
            Pointer to the tunnel setup structure.  When nPort is an output port
            the component should populate the fields of this structure.  When
            When nPort is an input port the component should review the setup
            provided by the component with the output port.
        @return OMX_ERRORTYPE
            If the command successfully executes, the return code will be
            OMX_ErrorNone.  Otherwise the appropriate OMX error will be returned.
        @ingroup tun
    */

    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);

    /** refer to OMX_UseBuffer in OMX_core.h or the OMX IL
        specification for details on the UseBuffer method.
        @ingroup buf
     */
    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);

    /** refer to OMX_AllocateBuffer in OMX_core.h or the OMX IL
        specification for details on the AllocateBuffer method.
        @ingroup buf
     */
    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);

    /** refer to OMX_FreeBuffer in OMX_core.h or the OMX IL
        specification for details on the FreeBuffer method.
        @ingroup buf
     */
    OMX_ERRORTYPE (*FreeBuffer)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_U32 nPortIndex,
            OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);

    /** refer to OMX_EmptyThisBuffer in OMX_core.h or the OMX IL
        specification for details on the EmptyThisBuffer method.
        @ingroup buf
     */
    OMX_ERRORTYPE (*EmptyThisBuffer)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);

    /** refer to OMX_FillThisBuffer in OMX_core.h or the OMX IL
        specification for details on the FillThisBuffer method.
        @ingroup buf
     */
    OMX_ERRORTYPE (*FillThisBuffer)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);

    /** The SetCallbacks method is used by the core to specify the callback
        structure from the application to the component.  This is a blocking
        call.  The component will return from this call within 5 msec.
        @param [in] hComponent
            Handle of the component to be accessed.  This is the component
            handle returned by the call to the GetHandle function.
        @param [in] pCallbacks
            pointer to an OMX_CALLBACKTYPE structure used to provide the
            callback information to the component
        @param [in] pAppData
            pointer to an application defined value.  It is anticipated that
            the application will pass a pointer to a data structure or a "this
            pointer" in this area to allow the callback (in the application)
            to determine the context of the call
        @return OMX_ERRORTYPE
            If the command successfully executes, the return code will be
            OMX_ErrorNone.  Otherwise the appropriate OMX error will be returned.
     */
    OMX_ERRORTYPE (*SetCallbacks)(
            OMX_IN  OMX_HANDLETYPE hComponent,
            OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
            OMX_IN  OMX_PTR pAppData);

    /** ComponentDeInit method is used to deinitialize the component
        providing a means to free any resources allocated at component
        initialization.  NOTE:  After this call the component handle is
        not valid for further use.
        @param [in] hComponent
            Handle of the component to be accessed.  This is the component
            handle returned by the call to the GetHandle function.
        @return OMX_ERRORTYPE
            If the command successfully executes, the return code will be
            OMX_ErrorNone.  Otherwise the appropriate OMX error will be returned.
     */
    OMX_ERRORTYPE (*ComponentDeInit)(
            OMX_IN  OMX_HANDLETYPE hComponent);

    /** @ingroup buf */
    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);

}

EmptyThisBufferFillThisBuffer 是驱动组件运行的基本的机制,前者表示让组件消耗缓冲区,表示对应组件输入的内容;后者表示让组件填充缓冲区,表示对应组件输出的内容。

UseBufferAllocateBufferFreeBuffer 为和端口相关的缓冲区管理函数,对于组件的端口有些可以自己分配缓冲区,有些可以使用外部的缓冲区,因此有不同的接口对其进行操作。

SendCommand 表示向组件发送控制类的命令。

GetParameterSetParameterGetConfigSetConfig 几个接口用于辅助的参数和配置的设置和获取。

ComponentTunnelRequest 用于组件之间的隧道化连接,其中需要制定两个组件及其相连的端口。

ComponentDeInit 用于组件的反初始化。

提示:OpenMax函数的参数中,经常包含OMX_IN和OMX_OUT等宏,它们的实际内容为空,只是为了标记参数的方向是输入还是输出。

4.3 OMX_BUFFERHEADERTYPE

该结构体是buffer的抽象化实例对象。前面的几篇文章当中也提到过,在OpenMAX组件当中,buffer的传递经常是以buffer的描述符(往往包含buffer的地址、长宽、格式等信息)来传递的,而不是实际的buffer本身,当需要处理的时候才真正地去访问实际的buffer内存,这是为了减少大buffer的拷贝,降低CPU的负载。事实上Linux内核里面的V4L2架构也是采用buffer描述符的形式来传递buffer数据,这种设计理念与原则可以延伸到所有涉及到大量的buffer操作的系统当中,参考意义非常大。

OpenMAX中提到的buffer在大部分情况下就是说的这个结构体实例,buffer的传递就指的是该结构体实例的传递,buffer的处理才是真正访问内存的部分。

原型:

typedef struct OMX_BUFFERHEADERTYPE
{
    OMX_U32 nSize;              /**< size of the structure in bytes */
    OMX_VERSIONTYPE nVersion;   /**< OMX specification version information */
    OMX_U8* pBuffer;            /**< Pointer to actual block of memory
                                     that is acting as the buffer */
    OMX_U32 nAllocLen;          /**< size of the buffer allocated, in bytes */
    OMX_U32 nFilledLen;         /**< number of bytes currently in the
                                     buffer */
    OMX_U32 nOffset;            /**< start offset of valid data in bytes from
                                     the start of the buffer */
    OMX_PTR pAppPrivate;        /**< pointer to any data the application
                                     wants to associate with this buffer */
    OMX_PTR pPlatformPrivate;   /**< pointer to any data the platform
                                     wants to associate with this buffer */
    OMX_PTR pInputPortPrivate;  /**< pointer to any data the input port
                                     wants to associate with this buffer */
    OMX_PTR pOutputPortPrivate; /**< pointer to any data the output port
                                     wants to associate with this buffer */
    OMX_HANDLETYPE hMarkTargetComponent; /**< The component that will generate a
                                              mark event upon processing this buffer. */
    OMX_PTR pMarkData;          /**< Application specific data associated with
                                     the mark sent on a mark event to disambiguate
                                     this mark from others. */
    OMX_U32 nTickCount;         /**< Optional entry that the component and
                                     application can update with a tick count
                                     when they access the component.  This
                                     value should be in microseconds.  Since
                                     this is a value relative to an arbitrary
                                     starting point, this value cannot be used
                                     to determine absolute time.  This is an
                                     optional entry and not all components
                                     will update it.*/
 OMX_TICKS nTimeStamp;          /**< Timestamp corresponding to the sample
                                     starting at the first logical sample
                                     boundary in the buffer. Timestamps of
                                     successive samples within the buffer may
                                     be inferred by adding the duration of the
                                     of the preceding buffer to the timestamp
                                     of the preceding buffer.*/
  OMX_U32     nFlags;           /**< buffer specific flags */
  OMX_U32 nOutputPortIndex;     /**< The index of the output port (if any) using
                                     this buffer */
  OMX_U32 nInputPortIndex;      /**< The index of the input port (if any) using
                                     this buffer */
}
  • nSize:buffer的总大小。
  • pBuffer:buffer的数据存储地址。
  • nAllocLen:分配的buffer的总大小,包括有效数据空间与未使用的内存空间。
  • nFilledLen:有效的数据长度,其起始地址由pBuffer与nOffset共同决定。
  • nOffset:有效数据的起始偏移值,相对于pBuffer来说的。
  • pAppPrivate:指向IL Client的私有数据。
  • hMarkTargetComponent:在接收到带有标记的buffer之后,处理完毕时需要发送OMX_EventMark 事件的组件句柄。
  • pMarkData:指向IL Client特定的数据,等于说是一个特定的标记,不同的buffer可以由该成员来打上不同的标记数据,进而产生不同的处理结果。IL Client在发送OMX_CommandMarkBuffer命令的时候把标记数据的指针传递给组件,组件会把相关的标记数据拷贝到该成员中,最后传递给hMarkTargetComponent
  • nFlags:该标志位包含了buffer的特定标志,比如EOS(流结束)标志等,以下是不同标志位的定义:
#define OMX_BUFFERFLAG_EOS 0x00000001
#define OMX_BUFFERFLAG_STARTTIME 0x00000002 //由数据源组件产生,此时buffer的nTimeStamp就是起始基准值
#define OMX_BUFFERFLAG_DECODEONLY 0x00000004
#define OMX_BUFFERFLAG_DATACORRUPT 0x00000008 //由IL Client产生,表明此buffer是坏的
#define OMX_BUFFERFLAG_ENDOFFRAME 0x00000010

举例来说明下各个成员的作用,比如说编码组件需要对一个1280x720大小的帧进行编码,那么它可能预先需要申请一个1280*720*3/4大小的buffer(原始数据的四分之三),由于编码出来的数据大小不一定,所以nFilledLennAllocLen大小就不一致,如果编码出来的数据需要加上一个前缀(比如表示其是H264还是其它的编码之类的),那么nOffset就不会为0了:

在这里插入图片描述

编码的Buffer结构

4.4 OMX_CALLBACKTYPE

在OpenMAX中,有一个很重要的点就是回调机制,回调机制提供了组件到IL Client的单向数据传递,组件里面的回调常用于通知IL Client某些命令已经执行完毕(比如状态设置),下面几种情况下会触发组件的回调机制:

  • 当一个异步的命令被执行完毕(成功、失败或错误)时就需要产生一个回调事件以通知IL Client命令的执行情况。

  • 组件发生一些错误的时候(这些错误不是IL Client产生的命令执行过程产生的)。比如组件内部产生不可恢复的错误并且需要转换到OMX_StateInvalid状态时就会触发回调机制。

该结构体的原型如下:

typedef struct OMX_CALLBACKTYPE
{
    /** The EventHandler method is used to notify the application when an
        event of interest occurs.  Events are defined in the OMX_EVENTTYPE
        enumeration.  Please see that enumeration for details of what will
        be returned for each type of event. Callbacks should not return
        an error to the component, so if an error occurs, the application
        shall handle it internally.  This is a blocking call.

        The application should return from this call within 5 msec to avoid
        blocking the component for an excessively long period of time.

        @param hComponent
            handle of the component to access.  This is the component
            handle returned by the call to the GetHandle function.
        @param pAppData
            pointer to an application defined value that was provided in the
            pAppData parameter to the OMX_GetHandle method for the component.
            This application defined value is provided so that the application
            can have a component specific context when receiving the callback.
        @param eEvent
            Event that the component wants to notify the application about.
        @param nData1
            nData will be the OMX_ERRORTYPE for an error event and will be
            an OMX_COMMANDTYPE for a command complete event and OMX_INDEXTYPE for a
            OMX_PortSettingsChanged event.
         @param nData2
            nData2 will hold further information related to the event. Can be OMX_STATETYPE for
            a OMX_CommandStateSet command or port index for a OMX_PortSettingsChanged event.
            Default value is 0 if not used. )
        @param pEventData
            Pointer to additional event-specific data (see spec for meaning).
      */

   OMX_ERRORTYPE (*EventHandler)(
        OMX_IN OMX_HANDLETYPE hComponent,
        OMX_IN OMX_PTR pAppData,
        OMX_IN OMX_EVENTTYPE eEvent,
        OMX_IN OMX_U32 nData1,
        OMX_IN OMX_U32 nData2,
        OMX_IN OMX_PTR pEventData);

    /** The EmptyBufferDone method is used to return emptied buffers from an
        input port back to the application for reuse.  This is a blocking call
        so the application should not attempt to refill the buffers during this
        call, but should queue them and refill them in another thread.  There
        is no error return, so the application shall handle any errors generated
        internally.

        The application should return from this call within 5 msec.

        @param hComponent
            handle of the component to access.  This is the component
            handle returned by the call to the GetHandle function.
        @param pAppData
            pointer to an application defined value that was provided in the
            pAppData parameter to the OMX_GetHandle method for the component.
            This application defined value is provided so that the application
            can have a component specific context when receiving the callback.
        @param pBuffer
            pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer
            or AllocateBuffer indicating the buffer that was emptied.
        @ingroup buf
     */
    OMX_ERRORTYPE (*EmptyBufferDone)(
        OMX_IN OMX_HANDLETYPE hComponent,
        OMX_IN OMX_PTR pAppData,
        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);

    /** The FillBufferDone method is used to return filled buffers from an
        output port back to the application for emptying and then reuse.
        This is a blocking call so the application should not attempt to
        empty the buffers during this call, but should queue the buffers
        and empty them in another thread.  There is no error return, so
        the application shall handle any errors generated internally.  The
        application shall also update the buffer header to indicate the
        number of bytes placed into the buffer.

        The application should return from this call within 5 msec.

        @param hComponent
            handle of the component to access.  This is the component
            handle returned by the call to the GetHandle function.
        @param pAppData
            pointer to an application defined value that was provided in the
            pAppData parameter to the OMX_GetHandle method for the component.
            This application defined value is provided so that the application
            can have a component specific context when receiving the callback.
        @param pBuffer
            pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer
            or AllocateBuffer indicating the buffer that was filled.
        @ingroup buf
     */
    OMX_ERRORTYPE (*FillBufferDone)(
        OMX_OUT OMX_HANDLETYPE hComponent,
        OMX_OUT OMX_PTR pAppData,
        OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
}

上面三个回调函数成员需要IL Client实现,并在OMX_GetHandle函数里面设置填充到组件的自定义结构体成员里面然后就可以在组件内部去调用这些回调函数了。

  • EventHandler:
    组件通过该回调方法向IL Client发送各种事件,在IL Client端的该方法实现中可以对感兴趣的消息进行分发处理(可以用switch语句实现),OMX_EVENTTYPE枚举定义了组件可以产生的事件种类。nData1参数一般会放置OMX_COMMANDTYPE枚举类型(该命令被组件处理完毕)或者OMX_ERRORTYPE枚举类型(组件处理命令时发生错误或其它错误);nData2可以放置一些额外的参数(比如状态转换命令时的目的状态OMX_STATETYPE枚举)。pEventData是与事件相关的特定类型的数据,类型由IL Client与组件进行协商规定,该回调是加锁调用的,所以IL Client实现该回调的时候需要在5ms之内返回。下表给出了几种事件和与之对应的各个参数组合:
eEventnData1nData2pEventData
OMX_EventCmdCompleteOMX_CommandStateSet要到达的状态
OMX_CommandFlush端口号
OMX_CommandPortDisable端口号
OMX_CommandPortEnable端口号
OMX_CommandMarkBuffer端口号
OMX_EventError错误码0
OMX_EventMark00与mark相关的数据
OMX_EventPortSettingsChanged端口号0
OMX_EventBufferFlag端口号nFlags
OMX_EventResourcesAcquired00
  • EmptyBufferDone
    该回调函数用于组件从输入端口(Input Port)拿出一帧数据还回给IL Client(可以看出这种状态下默认IL Client送给组件的数据已经被拷贝到组件私有内存空间了,所以可以直接还回),但是很多时候组件并不会自己再次开辟一个内存空间,而是与IL Client公用同一个内存空间,这时IL Client需要对buffer进行引用计数,并且在组件处理完毕数据之前是不应该还回数据的,所以这个回调函数很多时候并不用实现。
  • FillBufferDone
    组件调用该回调从组件的输出端口(Output Port)拿出一帧数据还回给IL Client,道理同上。需要注意的是,这三个回调函数都是在加锁的情况下被调用,所以IL Client在实现这些函数的时候要保证能够在5ms之内返回。

4.5 端口定义相关的数据类型

  • OMX_PORT_PARAM_TYPE
typedef struct OMX_PORT_PARAM_TYPE {
    OMX_U32 nSize;              /**< size of the structure in bytes */
    OMX_VERSIONTYPE nVersion;   /**< OMX specification version information */
    OMX_U32 nPorts;             /**< The number of ports for this component */
    OMX_U32 nStartPortNumber;   /** first port number for this type of port */
} OMX_PORT_PARAM_TYPE;

用于指定组件端口的数量(nPorts)与起始标号(nStartPortNumber)。

  • OMX_PARAM_PORTDEFINITIONTYPE
typedef struct OMX_PARAM_PORTDEFINITIONTYPE {
    OMX_U32 nSize;                 /**< Size of the structure in bytes */
    OMX_VERSIONTYPE nVersion;      /**< OMX specification version information */
    OMX_U32 nPortIndex;            /**< Port number the structure applies to */
    OMX_DIRTYPE eDir;              /**< Direction (input or output) of this port */
    OMX_U32 nBufferCountActual;    /**< The actual number of buffers allocated on this port */
    OMX_U32 nBufferCountMin;       /**< The minimum number of buffers this port requires */
    OMX_U32 nBufferSize;           /**< Size, in bytes, for buffers to be used for this channel */
    OMX_BOOL bEnabled;             /**< Ports default to enabled and are enabled/disabled by
                                        OMX_CommandPortEnable/OMX_CommandPortDisable.
                                        When disabled a port is unpopulated. A disabled port
                                        is not populated with buffers on a transition to IDLE. */
    OMX_BOOL bPopulated;         /**< Port is populated with all of its buffers as indicated by
                                    nBufferCountActual. A disabled port is always unpopulated.
                                    An enabled port is populated on a transition to OMX_StateIdle
                                    and unpopulated on a transition to loaded. */
    /**< Domain of the port. Determines the contents of metadata below. */
    OMX_PORTDOMAINTYPE eDomain;
    union {
        OMX_AUDIO_PORTDEFINITIONTYPE audio;
        OMX_VIDEO_PORTDEFINITIONTYPE video;
        OMX_IMAGE_PORTDEFINITIONTYPE image;
        OMX_OTHER_PORTDEFINITIONTYPE other;
    } format;
    OMX_BOOL bBuffersContiguous;
    OMX_U32 nBufferAlignment;
} OMX_PARAM_PORTDEFINITIONTYPE;

端口的实例化对象,一个该结构体类型的变量就用于代表组件的一个端口。

  1. nPortIndex:只读,表明该端口的索引号,对于同一个组件来说,其端口号是各不相同的,而不同的组件的端口号可以相同。
  2. eDir:指定端口的数据流向,(OMX_DirInput-输入,OMX_DirOutput-输出)。
  3. bEnabled:表明端口是否被使能。OMX_CommandPortEnable或者OMX_CommandPortDisable
  4. eDomain:表示该端口所在的域,有OMX_PortDomainAudioOMX_PortDomainVideoOMX_PortDomainImageOMX_PortDomainOther四种枚举。
  5. format:共用体类型,根据eDomain指定的域来选择相应的结构体来填充。

5. 组件相关的宏定义

下面列举部分OpenMAX官方提供的宏定义,专门用来帮助IL Client来完成对组件的各种操作,具体宏定义的原型就不再详述了,可以根据名字参照OpenMAX提供的头文件代码查看并使用。

  • OMX_SendCommand:向指定的组件发送命令。
  • OMX_CommandStateSet:设置指定组件的状态。
  • OMX_Get/SetParameter:获取/设置指定组件的参数。
  • OMX_Get/SetConfig:获取/设置指定组件的配置。
  • OMX_EmptyThisBuffer:向指定组件传递buffer数据,传递buffer数据到组件的输入端口。
  • OMX_FillThisBuffer:向指定组件还回buffer数据,传递buffer数据到组件的输出端口。
  • OMX_Init/OMX_Deinit:组件的初始化/销毁。
  • OMX_GetHandle:获取组件的实例化对象(句柄)。
  • OMX_SetupTunnel:在两个组件之间建立连接(tunnel)。

1)OMX_SendCommand 宏向组件发送命令。该调用是非阻塞调用。组件应该检查参数,然后将命令排队到组件线程中执行。组件线程应该在命令结束时发送 EventHandler() 回调。这个宏将直接从应用程序到组件(通过一个核心宏)。

一般的命令有:

typedef enum OMX_COMMANDTYPE
{
    OMX_CommandStateSet,    /**< Change the component state */
    OMX_CommandFlush,       /**< Flush the data queue(s) of a component */
    OMX_CommandPortDisable, /**< Disable a port on a component. */
    OMX_CommandPortEnable,  /**< Enable a port on a component. */
    OMX_CommandMarkBuffer,  /**< Mark a component/buffer for observation */
    /**< Reserved region for introducing Khronos Standard Extensions */
    OMX_CommandKhronosExtensions = 0x6F000000,
    /**< Reserved region for introducing Vendor Extensions */
    OMX_CommandVendorStartUnused = 0x7F000000,
    OMX_CommandMax = 0X7FFFFFFF
} OMX_COMMANDTYPE;
#define OMX_SendCommand(                                    \
         hComponent,                                        \
         Cmd,                                               \
         nParam,                                            \
         pCmdData)                                          \
     ((OMX_COMPONENTTYPE*)hComponent)->SendCommand(         \
         hComponent,                                        \
         Cmd,                                               \
         nParam,                                            \
         pCmdData)                          /* Macro End */

当该命令为“OMX_CommandStateSet”时,组件将队列状态转换到nParam中标识的新状态。

当命令为“OMX_CommandFlush”时,为了刷新端口的缓冲区队列,该命令将强制组件按照接收缓冲区的顺序返回所有当前未被处理的缓冲区给应用程序。

当命令为“OMX_CommandPortDisable”或“OMX_CommandPortEnable”时,组件的端口(由nParam的值给出)将被停止或重启。

当命令“OMX_CommandMarkBuffer”被用来标记一个缓冲区时,pCmdData将指向一个包含组件句柄的OMX_MARKTYPE结构,以检查缓冲区链中的标记。nParam1包含应用缓冲区标记的端口的索引。

例子:OMXSAFE(OMX_SendCommand(vrenderer, OMX_CommandPortEnable, 1, 0)); // 停下1对应的端口

2)OMX_GetParameter 宏将从组件获得当前参数设置之一。这个宏不能只在组件处于OMX_StateInvalid状态时被调用。nParamIndex 参数用于指示正在向组件请求哪个结构。在调用此宏之前,应用程序应分配正确的结构,并填写结构大小和版本信息。当该参数应用于端口时,调用者应填写适当的 nPortIndex 值,指示该参数应用于哪个端口。如果该组件没有更改任何设置,则应该为该组件返回一组有效的DEFAULT参数。这是一个阻塞调用。

#define OMX_GetParameter(                                   \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)                        \
    ((OMX_COMPONENTTYPE*)hComponent)->GetParameter(         \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)    /* Macro End */

3)OMX_SetParameter 宏将向组件发送初始化参数结构。在对宏的单独调用中,每次发送一个结构体。这个宏只能在组件处于 OMX_StateLoaded 状态或端口被禁用(当参数应用于端口时)时被调用。nParamIndex参数用于指示传递给组件的结构。在调用这个宏之前,应用程序应该分配正确的结构,并应该填写结构大小和版本信息(以及实际数据)。在调用之后,应用程序可以自由地处理这个结构,因为组件需要复制它应保留的任何数据。这是一个阻塞调用。

#define OMX_SetParameter(                                   \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)                        \
    ((OMX_COMPONENTTYPE*)hComponent)->SetParameter(         \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)    /* Macro End */

4)OMX_GetConfig 宏将从组件获得其中一个配置结构。这个宏可以在组件加载后的任何时候调用。nParamIndex调用参数用于指示正在从组件请求哪个结构。在调用此宏之前,应用程序应分配正确的结构,并填写结构大小和版本信息。如果组件之前没有发送此配置参数,则应该为该组件返回一组有效的DEFAULT值。这是一个阻塞调用。

#define OMX_GetConfig(                                      \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)                           \
    ((OMX_COMPONENTTYPE*)hComponent)->GetConfig(            \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)       /* Macro End */

5)OMX_SetConfig 宏将把其中一个配置结构发送到组件。每个结构每次发送一个,每个都在对宏的单独调用中。这个宏可以在组件加载后的任何时候调用。在调用这个宏之前,应用程序应该分配正确的结构,并应该填写结构大小和版本信息(以及实际数据)。在调用之后,应用程序可以自由地处理这个结构,因为组件需要复制它应保留的任何数据。这是一个阻塞调用。

#define OMX_SetConfig(                                      \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)                           \
    ((OMX_COMPONENTTYPE*)hComponent)->SetConfig(            \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)       /* Macro End */

6)OMX_GetState 宏将调用组件来获取组件的当前状态,并将状态值放置到pState所指向的位置。

#define OMX_GetState(                                       \
        hComponent,                                         \
        pState)                                             \
    ((OMX_COMPONENTTYPE*)hComponent)->GetState(             \
        hComponent,                                         \
        pState)                         /* Macro End */

7)OMX_UseBuffer 宏将请求组件使用另一个组件或IL客户机已经分配的缓冲区(并分配自己的缓冲区头)。这是一个阻塞调用。

#define OMX_UseBuffer(                                      \
           hComponent,                                      \
           ppBufferHdr,                                     \
           nPortIndex,                                      \
           pAppPrivate,                                     \
           nSizeBytes,                                      \
           pBuffer)                                         \
    ((OMX_COMPONENTTYPE*)hComponent)->UseBuffer(            \
           hComponent,                                      \
           ppBufferHdr,                                     \
           nPortIndex,                                      \
           pAppPrivate,                                     \
           nSizeBytes,                                      \
           pBuffer)

8)OMX_AllocateBuffer 宏将请求组件分配一个新的缓冲区和缓冲区头。组件将分配缓冲区和缓冲区头,并返回一个指向缓冲区头的指针。这是一个阻塞调用。

#define OMX_AllocateBuffer(                                 \
        hComponent,                                         \
        ppBuffer,                                           \
        nPortIndex,                                         \
        pAppPrivate,                                        \
        nSizeBytes)                                         \
    ((OMX_COMPONENTTYPE*)hComponent)->AllocateBuffer(       \
        hComponent,                                         \
        ppBuffer,                                           \
        nPortIndex,                                         \
        pAppPrivate,                                        \
        nSizeBytes)                     /* Macro End */

9)OMX_FreeBuffer 宏将从组件中释放一个使用OMX_AllocateBuffer或OMX_UseBuffer分配的缓冲区头。如果组件分配了缓冲区(参见OMX_UseBuffer宏),则组件应该释放缓冲区和缓冲区头。这是一个阻塞调用。

#define OMX_FreeBuffer(                                     \
        hComponent,                                         \
        nPortIndex,                                         \
        pBuffer)                                            \
    ((OMX_COMPONENTTYPE*)hComponent)->FreeBuffer(           \
        hComponent,                                         \
        nPortIndex,                                         \
        pBuffer)                        /* Macro End */

10)OMX_EmptyThisBuffer 宏将发送一个满是数据的缓冲区到组件的输入端口。该缓冲区将被组件清空,并通过EmptyBufferDone回调返回给应用程序。这是一个非阻塞调用,因为组件将记录缓冲区并立即返回,然后稍后在适当的时间清空缓冲区。如预期的那样,这个宏只能在组件处于OMX_StateExecuting中时被调用。如果nPortIndex没有指定输入端口,组件将返回一个错误。

#define OMX_EmptyThisBuffer(                                \
        hComponent,                                         \
        pBuffer)                                            \
    ((OMX_COMPONENTTYPE*)hComponent)->EmptyThisBuffer(      \
        hComponent,                                         \
        pBuffer)                        /* Macro End */

11)OMX_FillThisBuffer 宏将发送一个空缓冲区到组件的输出端口。该缓冲区将被组件填充,并通过FillBufferDone回调返回给应用程序。这是一个非阻塞调用,因为组件将记录缓冲区并立即返回,然后稍后在适当的时间填充缓冲区。如预期的那样,这个宏只能在组件处于OMX_ExecutingState时被调用。如果nPortIndex没有指定输出端口,组件将返回一个错误。

#define OMX_FillThisBuffer(                                 \
        hComponent,                                         \
        pBuffer)                                            \
    ((OMX_COMPONENTTYPE*)hComponent)->FillThisBuffer(       \
        hComponent,                                         \
        pBuffer)                        /* Macro End */

12)OMX_UseEGLImage 宏将请求组件使用EGL提供的EGLImage(并分配自己的缓冲区头)。这是一个阻塞调用。

#define OMX_UseEGLImage(                                    \
           hComponent,                                      \
           ppBufferHdr,                                     \
           nPortIndex,                                      \
           pAppPrivate,                                     \
           eglImage)                                        \
    ((OMX_COMPONENTTYPE*)hComponent)->UseEGLImage(          \
           hComponent,                                      \
           ppBufferHdr,                                     \
           nPortIndex,                                      \
           pAppPrivate,                                     \
           eglImage)

14)在OMX_Core.h中定义了Core的API函数,应用程序通过它可以进行初始化、处理handle等操作,具体内容如下:

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void);         // 初始化OMX Core,且应该是OMX中第一个被调用的函数;  

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void);        // 反初始化OMX Core,且应该是OMX中最后一个被调用的函数;  

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(       // 列出系统中所有可用component的名称;  
                                 OMX_OUT OMX_STRING cComponentName,  
                                 OMX_IN  OMX_U32 nNameLength,  
                                 OMX_IN  OMX_U32 nIndex);  

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(    // 根据名称查找component,并调用component的方法来实例化component;  
                                 OMX_OUT OMX_HANDLETYPE* pHandle,   
                                 OMX_IN  OMX_STRING cComponentName,  
                                 OMX_IN  OMX_PTR pAppData,  
                                 OMX_IN  OMX_CALLBACKTYPE* pCallBacks);  

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(  
                                 OMX_IN  OMX_HANDLETYPE hComponent);  

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(         // 在两个component之间建立tunnel连接  
                                 OMX_IN  OMX_HANDLETYPE hOutput,  
                                 OMX_IN  OMX_U32 nPortOutput,  
                                 OMX_IN  OMX_HANDLETYPE hInput,  
                                 OMX_IN  OMX_U32 nPortInput);  

OMX_API OMX_ERRORTYPE  OMX_GetContentPipe(  
                                 OMX_OUT OMX_HANDLETYPE *hPipe,  
                                 OMX_IN OMX_STRING szURI);  

OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole (   
                                 OMX_IN      OMX_STRING role,  
                                 OMX_INOUT   OMX_U32 *pNumComps,  
                                 OMX_INOUT   OMX_U8  **compNames);  

OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent (   
                                 OMX_IN      OMX_STRING compName,   
                                 OMX_INOUT   OMX_U32 *pNumRoles,  
                                 OMX_OUT     OMX_U8 **roles);  

当应用程序需要使用某个component的功能时,其首先需要调用 OMX_Init() 来对OMX Core进行初始化,然后通过 OMX_GetHandle() 来实例化component,取得相应的component handle(组件句柄)。组件句柄用于访问组件的所有公共方法,还包含指向组件私有数据区域的指针。handle实际上是一个指向component对象的void类型指针,其在OMX_Type.h中定义如下:

typedef void* OMX_HANDLETYPE;

OMX_SetupTunnel() 用来在两个component之间建立tunnel连接。

6. 结语

本文主要介绍了OpenMAX官方头文件里面定义的一些数据类型,其中大部分的数据类型是需要我们自己去实现的,就是说OpenMAX只是提供了一个框架与一套API接口,而接口的具体实现则要靠我们自行编写代码去实现,并且也不是完全不可变的,而是根据实际开发的需要来适当改变一些实现方法来更好地满足开发设计需求。

可以看出来组件的设计方法与linux内核里面的media framework非常相似,都是将一个具体的功能模块抽象为一个(元件),模块之间的连接抽象为(走线),而端口就是(管脚),这个跟电路板上面的电路组成十分相似,可以看出来有时候软件设计有时候可以从硬件设计上面获取灵感,以实现更好的效果,或许除了硬件,还可以从更多的地方来获取到软件设计的方法与思想。

### 如何在 IntelliJ IDEA 中配置和使用 Swagger #### 添加 Maven 依赖 为了使 Swagger 能够工作,在 `pom.xml` 文件中需加入特定的依赖项。这可以通过编辑项目的构建文件来完成: ```xml <dependencies> <!-- swagger2 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.8.0</version> </dependency> <!-- swagger ui --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.8.0</version> </dependency> </dependencies> ``` 这些依赖会引入必要的库用于生成 API 文档以及提供交互式的 UI 页面[^4]。 #### 创建 Swagger 配置类 接着创建一个新的 Java 类用来初始化并配置 Swagger 实例。通常命名为类似于 `SwaggerConfig.java` 的名称,并放置于合适的位置,比如 `config` 包内: ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; @Configuration public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .build(); } private ApiInfo apiInfo(){ return new ApiInfoBuilder().title("API文档").description("").termsOfServiceUrl("") .contact(new Contact("", "", "")) .license("").licenseUrl("").version("1.0") .build(); } } ``` 这段代码定义了一个 Spring Bean 来设置 Swagger 的基本信息和其他选项。 #### 启动应用测试 当上述步骤完成后,启动应用程序即可访问默认路径 `/swagger-ui.html` 查看自动生成的 RESTful 接口文档界面。通过浏览器打开该链接可以浏览到所有已暴露出来的 HTTP 请求方法及其参数说明等信息。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值