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:
这样就得到了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:
|
|