邪恶漫画之女仆少爷:Android Opencore OpenMAX学习(4)

来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 06:09:53

Android Opencore OpenMAX学习(4)

文章分类:移动开发

3 OMX组件输入输出缓冲协商
3 S; `2 d# y1 ^, m: d4 @& Y 在任何数据交换前,输入输出缓冲需要进行协商。PV框架需要做以下工作:、6 h( s: [7 V) a4 D
1)调用OMX_GetParameter获取输入端口缓冲参数(最小/实际缓冲数,缓冲区大小等等)
1 g: D% |# Q1 ^% Q% ^) [3 | 2)检查有效的输入缓冲参数(修改一些参数,比如帧的长度和宽度,以及缓冲区的数目等等)) {4 W* v) D! c" d, g& q# E
3)调用OMX_SetParameter函数设置输入缓冲参数
+ [$ r+ O0 U" Y( N. T* |+ ^0 a* u6 N. \ 4)调用OMX_GetParameter获取输出端口缓冲参数(最小/实际缓冲数,缓冲区大小等等)
  ^* Y. a+ f, `# }* P0 M0 p0 Y 5)检查有效的输出缓冲参数(修改一些参数,比如帧的长度和宽度,以及缓冲区的数目等等)
: a; c. C1 d6 T- g 6)调用OMX_SetParameter函数设置输出缓冲参数6 T. O  ]8 O% j0 p0 j2 e5 a
过程如图三(省略)# j3 B: s; p& @  B8 x$ J
一些设想:$ K' Y' @$ x4 Y9 v
1)缓冲区尺寸的设想:3 h, d: b" D6 k1 s; z
对于编码器组件,最终分配的输出缓冲区尺寸可能小于profile/level/target比特率所要求的最大帧尺寸。出于内存消耗考虑,OMX编码器组件应当能够输出frame或NAL的比特流划分到多个输出缓冲区去。老调重弹,最后一个部分缓冲区使用 “OMX_BUFFERFLAG_ENDOFFRAME”标记结尾。3 s) c1 h5 ?% {
对于解码器组件,最终分配的输入缓冲区尺寸可能小于profile/level/target比特率所要求的最大帧尺寸。出于内存消耗考虑,PV框架在适当的时候提供采用“OMX_BUFFERFLAG_ENDOFFRAME”标记结尾的输入缓冲区。如果输入缓冲包含完整帧(H264也可能是NAL单元)或多帧,“OMX_BUFFERFLAG_ENDOFFRAME”将会用来标记一帧的结尾。如果完整的frame/NAL不能放入一个输入缓冲区,则会被拆分放入多个缓冲区。包含部分信息的缓冲区,“OMX_BUFFERFLAG_ENDOFFRAME”标记位将会被置为0。一帧数据的最后一个缓冲区中 “OMX_BUFFERFLAG_ENDOFFRAME”才会被置为1。通过这种做法,组件可以方便的重构一帧数据。
' K) G" ^- V# _9 I' u7 E! U 如果OMX解码器组件不兼容组长部分帧,PV框架将负责做这件事情。' i8 O+ E! t" Q, v* h6 _6 l$ A! y
2)输入/输出缓冲区数量。* A" _$ y. }4 X  L/ t3 G9 @% L5 I' f
框架或许希望分配比OMX要求更多的的输入/输出缓冲区以提供更优的性能(比如解码器输出缓冲或编码器输入缓冲——缓冲更多的数据可以提高性能)。尽管性能提升了,但无法送到OMX组件去(不太理解,应该还是协商不好的意思)。8 I$ b5 T6 I6 r8 }9 ~$ X9 ~
4 OMX状态变换 加载->空闲 " G4 l" o& o5 B
如果部分已分配的缓冲区进入空闲状态,缓冲区分配将挂起。在变化过程中,PV框架将“5 n$ M( s. ~, |' y
1)通过“OMX_SendCommand”调用发送命令给OMX组件,将状态由OMX_StateLoaded改变为OMX_StateIdle, S# Z" c; @, h! T
2)调用一系列“OMX_UseBuffer” 或者“OMX_AllocateBuffer”通知OMX组件。这些调用使用NumInputBuffer记录输入输入端口的数目,使用NumOutputBuffer记录输入输入端口的数目。
! o: O2 L( N; y3 z9 [# f; c+ ?9 z 3)等待OMX组件的EventHandler事件回调,通知框架状态变换完成(OMX_EventCmdComplete)
+ J: _0 x2 L. Z+ F" F0 C2 N 一些设想与推荐参数:, v1 d6 b/ ^8 }: C
根据OMX规范,兼容的OMX组件必须同时支持OMX_UseBuffer 和 OMX_AllocateBuffer调用。然而,出于一些内在原因,完全实现是不可能的,组件应当通知PV框架其所具有的功能。7 Q: M& ]; j, [! |' }
推荐将INPUT缓冲分配在OMX组件外部,这样可以减少额外的内存拷贝(也就是说输入缓冲使用OMX_UseBuffer)。
& G) y+ J: g/ w2 C 5 变换到“执行”状态与数据交换
: D$ H! u( Q  p- z/ g1 Q% | 状态变化到执行时才开始真正处理数据。本步骤中,PV框架将:+ m0 }$ s) L! @
1)通过“OMX_SendCommand”调用发送命令给OMX组件,将状态由OMX_StateIdle改变为OMX_StateExecuting。+ |5 M# ?# d& G) f2 U9 x0 \9 G
2)等待OMX组件的EventHandler事件回调,通知框架状态变换完成(OMX_EventCmdComplete)。. C9 o" M- }3 H7 e6 k. R8 Y* g7 y0 h
3)通过OMX_EmptyThisBuffer调用将输入缓冲发送给OMX组件,通过OMX_FillThisBuffer调用将输出缓冲发送给OMX组件,组件使用合适的回调函数返回缓冲区。
9 L* t- e1 B4 B! F5 t 过程如图5
3 L1 n" {; f1 u6 U4 Z. g 注意:1 C- J$ c! v( d% {2 i
1)在任意时刻OMX组件如果拥有所有输入缓冲区(也就是所有的输入缓冲都通过EmptyThisBuffer调用传给了OMX组件),此时将不能再传递任何输入缓冲区给OMX组件,知道OMX通过EmptyBufferDone释放一个缓冲。对于输出缓冲区同样。, H( z) W+ a/ O4 k, R1 Z4 D2 m
2)如果PV框架没有及时将缓冲区发给OMX框架,OMX组件不会多次返回同一个缓冲区(也就是一旦OMX框架返回一个缓冲区,只有PV框架再次调用这个缓冲,OMX组件才可使用)。这是OMX缓冲交换APSs所规定的基本规则。0 f7 m7 L. l: `# M* w( T. _
6 暂停 * O; k$ c& |/ N+ v( w' t
PV框架常见的功能包括暂停和恢复,PV框架将:
6 u: D/ @/ t% E7 p& T8 v! c 1)通过“OMX_SendCommand”调用发送命令给OMX组件,将状态由OMX_StateExecuting改变为OMX_StatePause。5 r. G. `8 Q0 t& N
2)等待OMX组件的EventHandler事件回调,通知框架状态变换完成(OMX_EventCmdComplete)。1 C# Y1 d( M2 d* J7 H
PV框架向OMX组件发送暂停命令后,立刻停止发送输入输出缓冲。
# ?% _- W7 W$ @0 m9 C! S6 D# s 有暂停就有恢复,PV框架将:! y/ d7 n; p% @& W8 k
1)通过“OMX_SendCommand”调用发送命令给OMX组件,将状态由OMX_StatePause改变为OMX_StateExecuting。, C% L) W$ c+ u2 N
2)等待OMX组件的EventHandler事件回调,通知框架状态变换完成(OMX_EventCmdComplete)。
! b- {  ]8 S+ T# q- {) L PV框架的状态恢复到执行后,将恢复发送OMX输入输出缓冲。4 ?" Z" u9 ]7 U7 {" M
过程如图6
. C) M- c8 T1 w8 N6 `+ I5 N 7 端口刷新(如果可用)
1 F) p( ~+ l0 C8 A 端口刷新调用一般用于重新配置解码器组件,这样会清空所有数据。在此情况下,PV框架将:# s/ i4 i0 h8 A, K' P: Q+ O
1)通过“OMX_SendCommand”调用发送刷新全部端口指令。
: C- ]- k8 [( H: k9 n. L 2)等待输入缓冲的输出缓冲的两个EventHandler事件回调,通知框架状态变换完成(OMX_EventCmdComplete)。' z  G/ s/ [# K; E- j1 I) x
刷新命令来了之后,PV框架立刻停止向OMX组件发送输入/输出缓冲。当组件接收到2个回调函数后,PV框架开始恢复发送输入/输出缓冲。$ Q, X/ ?# D6 J8 Y  Z
端口刷新的顺序和通告并不相关。
1 ~8 \& A% d* r9 P. E" N 过程如图7。: J/ Y$ o3 p" C6 u4 l7 U! F' j
为了防止动态端口被重复配置,也可以先于OMX IL用户关闭OMX组件端口调用端口刷新指令。
+ r; ]3 A9 i; }3 ~& ]% L+ H4 w& O$ c7 S 8 停止/变化到“IDLE”状态
/ V0 B3 _/ L" d' c3 V! j+ A
为了停止处理过程,PV框架将:
* r/ P) P+ E9 _+ c6 M 1)通过“OMX_SendCommand”调用发送命令给OMX组件,将状态由OMX_StatePause改变为OMX_StateIdle。
" M0 d8 H( d: i& Q9 } 2)等待OMX组件的EventHandler事件回调,通知框架状态变换完成(OMX_EventCmdComplete)。
; A! U- c8 I2 O9 m! w+ q9 b- w 过程见图8。! U2 X, c4 X! A$ g
一些设想:
  [5 x) z+ Y# e0 G" [4 y# o1 V 当命令完成“IDEL”态的回调后,PV框架假设所有输入输出缓冲按照OMX规范要求那样返回。* N% O" J% ~) ]" z
9 OMX组件状态转换 IDLE->Loaded State和 De-initialization 6 `4 B+ s( I/ q7 {; G' x
当PV框架结束与一个OMX组件的所有交互后,将:7 F: w# F4 {6 G6 N5 V( s
1)通过“OMX_SendCommand”调用发送命令给OMX组件,将状态由OMX_StateIdle改变为OMX_StateLoaded。
; v9 u: n# e/ _: M1 Y/ h 2)向OMX组件发送一系列“OMX_FreeBuffer”调用。
3 g$ k) o" x4 b9 b 3)等待OMX组件的EventHandler事件回调,通知框架状态变换完成(OMX_EventCmdComplete)。使用NumInputBuffer记录输入输入端口的数目,使用NumOutputBuffer记录输入输入端口的数目。
( R! N) }" i8 B2 R+ R 4)对OMX核心执行OMX_FreeHandle调用,释放组件句柄。5 z2 Q6 Z* Q; o+ E" S
流程图见图9
6 L$ _6 B2 l7 j9 v9 ^ 注意:在向OMX组件发送卸载命令之前,PV框架一直在等待OMX组件返回的输入输出缓冲。由于回调的过程的不同步性,一些 EmptyBufferDone/FillBufferDone的回调有可能在OMX组件状态由“executing” 到 “idle”之后才到达。9 c3 M6 G- V- ]0 M4 O. E0 L
10 OMX Core 卸载
4 h1 f) D  A  p PV框架调用函数OMX_Deinit()。