前台人占空间尺寸:Android-StageFright之decode
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
spcodec = 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));