OpenMAX框架的学习有两大难点,一是组件的状态切换与buffer的流转过程,这部分内容我们已经在IL Spec中学习过了;二是OMX组件使用的buffer类型与buffer分配过程,这一节我们来重点剖析OMX组件使用的buffer类型。
1、引言
在实际应用中,OMX组件可能需要能够处理多种类型的输入数据。对于编码组件而言,其输入可能包括未压缩的视频流,例如来自设备屏幕的录屏数据或相机录制的原始视频。而对于解码组件,它可能需要处理普通的压缩视频文件,或者是加密的视频流。为了存储不同类型的输入数据,Android定义了不同类型的buffer。待处理的数据以不同的形式存储在这些缓冲区中,因此OMX组件需要明确即将处理的输入缓冲区类型,从而能够正确地解析buffer中的数据。
同样的,OMX组件输出结果时,会把数据填充到不同类型的buffer中,以适应不同的用途。对于编码组件,编码后的数据通常会被填充到一块普通的buffer中,应用获取到buffer后,会读取其中的数据并进行封装;对于解码组件,解码后的数据通常会被发送到surface进行渲染,因此数据需要填充到native window buffer中。为了让组件能够正确地将数据填充到buffer中,我们需要提前配置好需要使用的输出缓冲区类型,从而能够让组件正确地向buffer填充数据。
接下来会有两部分内容需要讨论:
-
Android上有哪些可用的input buffer和output buffer类型?
-
这些buffer的格式是怎样的?
2、Buffer Types
在了解Buffer Types之前,我们先简单说明一下OMXNodeInstance的作用。在之前的学习中,我们提到OMXNodeInstance在框架中扮演的角色是IL Client,它封装了OMX Core提供的低层级接口,并进行了新的抽象。然而,在阅读源码的过程中我们会发现,OMXNodeInstance的接口仍然暴露了过多的细节,使用起来相对困难。因此,Android在OMXNodeInstance之上又进行了封装,这一层就是我们后续要学习的ACodec。查看ACodec对外开放的接口,已经完全没有了OMX框架的身影,所以ACodec的接口算是比较高层级的接口。因为ACodec封装了OMXNodeInstance的调用,所以笔者认为它也算的上是IL Client的一部分。
接下来让我们正式进入主题。
Android并没有直接定义具体的buffer类型,而是通过OMXNodeInstance抽象出的PortMode(端口模式)来指明组件端口所使用的buffer类型及其分配方式。相应地,为组件配置使用的buffer类型的方法就被命名为setPortMode。
PortMode是一个枚举,定义在IOMX.h中:
enum PortMode {
kPortModePresetStart = 0,
kPortModePresetByteBuffer,
kPortModePresetANWBuffer,
kPortModePresetSecureBuffer,
kPortModePresetEnd,
kPortModeDynamicStart = 100,
kPortModeDynamicANWBuffer,
kPortModeDynamicNativeHandle,
kPortModeDynamicEnd,
};
很多读者在看到PortMode时可能会心生疑惑:PortMode是如何体现buffer类型与分配方式的呢?这正是这部分内容显得晦涩难懂的原因所在。
我们将PortMode中的枚举名拆成三部分:kPortMode(前缀,忽略),Preset/Dynamic(分配方式),buffer类型(后缀)。
先来了解与buffer类型(也就是后缀部分)中的关键词:
关注公众号《青山渺渺》阅读全文