好贷网好贷款

Opencore and OMX core/component interaction

发布时间:2016-12-5 8:41:10 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"Opencore and OMX core/component interaction",主要涉及到Opencore and OMX core/component interaction方面的内容,对于Opencore and OMX core/component interaction感兴趣的同学可以参考一下。

在这里讲的是Opencore和OMX 的调用sequence,基本来说是根据OMX的API过程来实现的,属于将OMX集成到Opencore的原理 部分 对于omx IL的API,大家可以参考http://omxil.sourceforge.net/docs/modules.html  Opencore and OMX core/component interaction    1 、将一个 CODEC 集成到 PV Opencore multimedia framewok 下的方式主要有三种:作为一个 compressed MIO(media I/O) component ,或者作为个 node ,或者作为一个 Openmax component 集成到 Opencore framework 下的 Openmax codecs nodes 。对于各种codec 尤其是那些包含了 HW acceleratin 的 codec 来说, Openmax IL interface 是最直接的和有效的集成方式,为上层提供统一的接口。 2 、具体 omx component 和 omxcore 的实现在 developer 文档在讨论,在这里只讨论 Opencore 和 omx core/component 的交互作用过程,即 call sequence 。 PVMF 对 omx 的调用大概可以用下面的图来描述:   所有这些过程都是通过 PVMF 来控制的,由 PVMF 发出 command 来控制 Opencore component 的状态转换。 3 、 Opencore 和 OMX core/component 的 interaction 过程分为下面几个过程,所有这些过程都是根据 API 的典型 sequence 来实现的。 3.1 、 PVMF 对 OMX 的调用首先是从对 OMX core 的初始化开始的: @ PVMF 首先调用 OMX_Init 来初始化 omx core @ 然后 PVMF 会向 omx core 请求所有他所拥有的 component ,并根据获得的 component name ,来请求有效 component 的 role, 然后对有效的组件及其 role 建立一个 registry 。 OMX_Init() 用来对 omx core 进行初始化,它必须是进入 omx 前调用的第一个函数,而且在调用 deinit 之前只能被调用一次。 OMX_ComponentNameEnum() 实质上就是检测出 system run - time 时所有的有效 component 。 OMX_GetRolesOfComponent() 实际上根据 component name 来取得 component 所支持的 role 的 number 。 具体流程如下:     3.2 、完成对 omx core 的初始化之后就要根据开始获得的 comonent name ,对 omx component 进行初始化,并且列举出相应 component 的 capabilities 以及获得 port 目录。 PVMF 的工作流程如下: @根据 component name 和 role 使用 OMX_GetHandle 来初始化指定的 omx component 。 @使用所有权 index“PV_OMX_CAPABILITY_TYPE_INDEX” 根据 OMX_GetParameter() 取得 component 的 capabilities ,根据 capabilities 就可以知道 component 是否支持部分祯,是否支持 UseBuffer 或者 AllocateBuffer 等等内容。如果 OMX componentd 对所有权 index 返回“ OMX_ErrorUnsupportedIndex” 或者其他错误信息, PVMF 必须为 component capabilities 指定一组默认的数据 。 @使用 OMX_GetParameter 来获得 Audio/Video component 的有效 port 数[ input/output port ],然后遍历所有的输入输出端口,来获得输入输出端口的索引。 PVMF 对“ PV_OMX_COMPONENT_CAPABILITY_TYPE_INDEX” index 的定义如下: #define PV_OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347 实际上所谓的 index 包括后面获取 Audio/Video component port 数使用的“ OMX_IndexAudioInit” 和“ OMX_IndexAudioInit” index 都是传到 OMX_GetParameter() 函数的第一个参数。 PVMF 需要从 component 取得的 capabilities 被包裹在下面的 structure 中,需要 component 对这个 structure 进行赋值: typedef struct PV_OMXComponentCapabilityFlagsType { OMX_BOOL ilsOMXComponentMultiThreaded; OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc; OMX_BOOL iOMXComponentSupportsExtrenalInputBufferAlloc; OMX_BOOL iOMXComponentSupportsMovableInputBuffers; OMX_BOOL iOMXComponentSupportsPartialFrames; OMX_BOOL iOMXComponentUsesNALStartCode; OMX_BOOL iOMXComponentCanHandleIncompleteFrames; OMX_BOOL iOMXComponentUsesFullAVCFrames; } iIsOMXComponentMultiThread 默认值为 OMX_TRUE, 虽然 OMX component 一般运行在一个独立的线程,但是通过同步调用等方式也可以使其和 PVMF 运行在一个线程。 iOMXComponentSupportExternalOutput/inputBufferAlloc 的默认值为 OMX_TRUE , OMX spec 要求 OMX component 必须支持在外部分配的额外 buffer( 比如 OMX_UseBuffer 调用外部的 buffer) ,如果 Component 不支持这个,它必须将其值设为 OMX_FALSE ,并且和 PVMF 进行协商,从而使 PVMF 使用 OMX_AllocateBuffer 。 IOMXComponentSupportsMovableInputBuffers 这个值默认也是 OMX_TRUE, 他类似于一种动态存储的概念,就是对于 external allocated input buffer ,可以将其的 omx 头部和实际数据进行分离,由 omx 头部的指针来指定实际数据的位置,如果这个指针可变,则 component 的可以访问不同的数据区域。如果 omx component 要求其起 header 总是指向同一个数据区域,则这个值必须设置 成 false 。 iOMXComponentSupportsPartialFrames 这个值的默认值为 OMX_TRUE, 根其字面意义一样,就是 component 是否支持部分桢,当桢 /NAL 的大小大于 buffer 的大小的时候,必须把桢 /NAL 分割成几块, PVMF 会在每个桢的结束位添加“OMX_BUFFERFLAG_ENDOFFRAME”, 从而使桢的组装变得很简单,如果 component 需要由 PVMF 完成对祯 /NAL 的组装并提供给 component 完整的桢 /NAL, 则必须设置这个值为 false ,不支持部分桢会对性能造成很大的影响。 iOMXComponentUsesNALStartCode 这个值默认是 OMX_false ,这个标志位主要影响到 H264 的解码,主要是设计到 H264 NAL 格式的问题,就是说 PVMF 能够重构 H264 的 NAL ,不需要再让 omx component 来解些比特流,如果 OMX H264 component 要求解些比特流,需要提供 0x0001 NAL start codes ,则这个值必须设置为 true 。 iOMXComponentCanHandleIncompleteFrames 这个值默认为 OMX_TRUE ,与对 partial 的支持不同,不完整的桢的是指由于丢包或其他原因导致的桢 /NAL 不完整,即已经被破坏的桢, comopnent 是否能提供恰当的处理,如果 component 不能相应的处理则必须设置这个值为 false 。 iOMXComponentUsesFullAVCFrames 的值默认为 OMX_FALSE ,这个值定义了 PVMF 在使用 AVC 的情况下,以何种模式为 Component 提供数据。在 OMX_FALSE 情况下是采用 NAL mode ,即 PCMF 提供给 comonent 的数据是 NAL 单元,相反的在 OMX_TRUE 情况下采用的是Frame. mode ,在 Frame. mode 情况下 PVMF 必须将 NAL 单元累在一起,然后为 component 提供完整的一桢数据。 OMX_GetHandle() 根据 component name 载入指定的 component 到内存,并根据 component 的方法来为其创建一个 component 的 instance 。 OMX_GetParameter() 这实际是一个宏,用来获得 component 的参数,根据第一个参数 handle pointer 的不同,可能返回值也是不同的。 具体过程如下:     3.3 完成对 omx core 和 omx component 的初始化之后,第三个过程就是对 omx component input/output buffer 的协商。 @首先使用 OMX_GetParameter() 获得 input/output port buffer parameters ,然后对获得的 parameters 进行一个 verify ,最后调用 OMX_SetParameter() 对 input/output port 设置一些 buffer parameters 。 Component input/output port Buffer size 在很大程度上影响着 component 的性能,如果一个 buffer 能载入多个桢 /NAL 就不存在分割的问题, PVMF 在每个 full 桢 /NAL 后面添加一个“ OMX_BUFFERFLAG_ENDOFFRAME” 标记。如果一个 buffer 不够容纳一个桢/NAL ,则不管是在输入还是输出都要把桢 /NAL 分割成多个 buffer ,并在最后一部分上打上一个 end flag 的标记。 看 OMX API 对 OMX_AllocateBuffer 和 OMX_UseBuffer 的定义后觉得,所谓分配 buffer 就是, component 每次都要自己分配一个新的 buffer 和 buffer   header ,而使用 buffer ,是指可以使用其他 component 或者 IL client 分配好的 buffer ,但必须自己分配一个相应的 buffer   header ,两种方式 具体过程如下: 3.4 完成初始化以及对交换区 buffer 的协商之后, OMX component 就被 loaded 了,载入后的 component 首先要进入 Idle 状态。 @首先 PVMF 会通过 OMX_SendCommand 函数向 OMX component 发送状态改变命令 ,将其状态从 OMX_StateLoaded 变为 OMX_StateIdle 。 @然后使用两种分配 buffer 方式 (use or allocate) 的任一种来为所有的 input/output port 分配 buffer ,分配 buffer 的函数会根据 NumInputBuffer 和 NumOutputBuffer 的值被调用多次 [ 这里有点小疑问,这个 Num 是不是就是 port 的数目? ] @当 component 完成 state transition 以后,会通过 envenhandle callback 来通知 PVMF ( OMX_EventCmdComplete )。 根据 OMX spec ,所有的标准 OMX component 必须支持 OMX_UseBuffer/Allocate 两种分配 buffer 的方式,如果由于内部限制等原因不支持的话, component 必须与 PVMF 进行协商。 一般来说 INPUT bufferes 一般分配在 component 外部,这样输入数据就可以省去不必要的 copy 操作。 具体过程如下: 3.5 进入 Idle 状态以后, OMX component 就可以进入执行状态处理数据 ,并与 PVMF 进行数据交换。 @首先 PVMF 还是发送 command 给 omx component 来改变状态,从 OMX_StateIdle 到 OMX_Executing 。 @同样 PVMF 会等待 component 通过 EventHandler callback 返回的 OMX_EventCmdComplete ,表明 component 已经完成状态转换。 @进入执行状态以后, PCMF 会通过 OMX_EmptyThisBuffer() 来向 component 的某个 input port 发送数据,并要求 component 取得 buffer 中的数据进行处理 , 同时通过 OMX_FillThisBuffer() 要求 component 向其的某个 output port 填充解码或者编码完的数据。 Component 会通过 callback 来返回 buffer 。 因为 inputbuffer 和 outputbuffer 的个数都是有限的,一旦使用 emptythisbuffer 将所有的 inputbuffer 都填满数据,如果此时 component 不返回,则就不能再有新的数据能进来。对 outputbuffer 同样,如果所有的 outputbuffer 都被 fillthisbuffer 占用,等待填充数据,在 component 返回之前将不再有新的 buffer 能用来填充输出数据。 在 PCMF 没有重新将 buffer 分配给 omx component 之前, component 不能对一个 buffer 进行多次返回。一旦 component 返回 buffer ,在 PCMF 没有使用 emptythisbuffer 或者 fillthisbuffer 将这个 buffer 的所有权分给 component 之前, component 不能对buffer 进行操作。 [有点小疑问:从上面的原来分析可以看出来,实际上虽然分配了 NumiputBuffer 和 NumoutputBuffer ,但这些 buffer 的所有权并不是 component ,对这个向 "component 发送 buffer “总是无法了解,在分配 buffer 的时候不是根据 port 来进行分配的么,为什么现在所有权不属于 component ,而且好像跟 port 也不是相对应的] 具体过程:     3.6 pausing 和 resuming 是在播放器中经常用到的,从执行状态到暂停,再从暂停回到播放都是通过 OMX_SendCommand 来实现的,过程同前面的状态改变一样 OMX_StateExecuting-----> OMX_StatePause ------> OMX_StateExecuting 。一旦进入停止状态,PVMF 就不再向 component 发送 input/output buffer ,直到收到从 component 发送来的进入执行状态的 callback 。 具体过程:   3.7 port flush 主要用在解码器中,比如说播放器复位的时候,这里的也是通过 OMX_SendCommand 来实现的。另外 port flush 也用在 IL client 释放动态 port 的过程中。[也有个小疑问,这里冲刷的究竟是哪个 buffer 里面的内容呢?] 具体过程:   3.8 在执行和暂停状态都可以通过发送 stop command 使 component 进入 Idle 状态。一旦进入 Idle 状态, PVMF 就会假定 component 已经返回了所有的 buffer 。 具体过程:   3.9 从 Idle 状态进入 Loaded 状态的过程如下: @首先通过 OMX_SendCommand ,将状态从 OMX_StateIdle 转变成 OMX_StateLoaded 。 @然后调用 OMX_FreeBuffer 释放掉 input/output buffers ,调用次数根据 NumInput/outputBuffers 。 @然后等待 comonent 的 call back @最后调用 OMX_FreeHandle 使 OMX core 释放掉所有的 comonent 的 handle 。 在进行状态转换之前, PVMF 会等待 component 返回所有的 input/output buffer ,因为是异步调用, EmptyBufferDone/FillBufferDone call back 可能在 omx component 从 executing 到 idle 状态转变的 call back 之后到达。 具体过程:   3.10 最后 PVMF 调用 OMX_Deinit() 来释放 omx core 。

上一篇:linux内核中的HZ介绍
下一篇:异步消息的传递_回调机制

相关文章

相关评论