帕特侬咨询 安永:Android-StageFright之decode

来源:百度文库 编辑:偶看新闻 时间:2024/04/29 06:56:37

Android-StageFright之decode

上一篇“数据流的封装“中,最后得到的两个MediaSource其实是两个OMXCodec。AwesomePlayer和mAudioPlayer都是从MediaSource 中得到数据进行播放的。AwesomePlayer得到的是最终需要渲染的原始视频数据,而mAudioPlayer读取的是最终需要播放的原始音频数据。也就是说,从OMXCodec中读到的数据已经是原始数据了。下面分析一下OMXCodec是怎么把数据源经过parse、decode两步以后转化成原始数据的。

从OMXCodec::Create这个构造方法开始,先看一下它的参数:

IOMX &omx

经过层层追踪,跨过OpenBinder机制,我们发现它是其实是一个OMXNodeInstance对象的实例。

MetaData &meta

这个参数由MediaSource.getFormat获取得到。这个对象的主要成员就是一个KeyedVector mItems,里面存放了一些代表MediaSource格式信息的名值对。

bool createEncoder

指明这个OMXCodec是编码还是解码。

MediaSource &source

是一个MediaExtractor。

char *matchComponentName

指定一种Codec用于生成这个OMXCodec。

先使用findMatchingCodecs寻找对应的Codec,找到以后为当前IOMX分配节点并注册事件监听器:omx->allocateNode(componentName, observer, &node)。

最后,把IOMX封装进一个OMXCodec:

1234567
sp codec = new OMXCodec(                     omx, node, quirks,                     createEncoder, mime, componentName,                     source);

这样就得到了OMXCodec。

AwesomePlayer中得到这个OMXCodec后,首先调用mVideoSource->start()进行初始化。OMXCodec初始化主要是做两件事:

1、向OpenMAX发送开始命令。mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle)

2、调用allocateBuffers()分配两个缓冲区,存放在Vector mPortBuffers[2]中,分别用于输入和输出。

AwesomePlayer开始播放后,通过mVideoSource->read(&mVideoBuffer, &options)读取数据。

mVideoSource->read(&mVideoBuffer, &options)具体是调用OMXCodec.read来读取数据。而OMXCodec.read主要分两步来实现数据的读取:

1、通过调用drainInputBuffers()对mPortBuffers[kPortIndexInput]进行填充,这一步完成parse。由OpenMAX从数据源把demux后的数据读取到输入缓冲区,作为OpenMAX的输入。

2、通过fillOutputBuffers()对mPortBuffers[kPortIndexOutput]进行填充,这一步完成decode。由OpenMAX对输入缓冲区中的数据进行解码,然后把解码后可以显示的视频数据输出到输出缓冲区。

AwesomePlayer通过mVideoRenderer->render(mVideoBuffer)对经过parse和decode 处理的数据进行渲染。一个mVideoRenderer其实就是一个包装了IOMXRenderer的AwesomeRemoteRenderer:

12345678910111213
mVideoRenderer = new AwesomeRemoteRenderer(                 mClient.interface()->createRenderer(                         mISurface, component,                         (OMX_COLOR_FORMATTYPE)format,                         decodedWidth, decodedHeight,                         mVideoWidth, mVideoHeight,                         rotationDegrees));