概述
MediaPlayer的start过程会调用到MediaPlayerService::Client的start函数,再调用Nuplayer对Decoder和MediaCodec进行初始化,然后找到解码器开始进行解码的工作。
类说明
1.Nuplayer::Decoder:解码模块。在播放的时候会调用MediaCodec去获取编解码列表,选择合适解码库。
2.MediaCodec:Decoder的代工。根据Decoder的要求,去MediaCodecList中查找解码器信息,然后选择合适的解码库。负责跟ACodec进行数据交互。
3…ACodec:主要负责解码相关工作。通过IOMXNode去控制解码器:设置参数,获取参数等。将从ACodecBufferChannel获取的解析之后的文件数据送给解析器。
总bouml时序图
下图的橙色边框内的时序就是start过程相关的
start过程可以分为下面几个流程:
1.启动解析器,启动GenericSource的start过程,从MP3Source中读取解析后的数据。
2.创建Nuplayer::Decoder,初始化Decoder。
3.根据mine类型查找并创建解码器。
start解析器
MediaPlayerService::Client的start函数经过层层调用会调用到NuPlayer::onStart,这个过程从时序图就可以看出来了,比较简单。NuPlayer::onStart函数一进来就对mSourceStarted进行判断,如果还没有启动则调用GenericSource::start。下面是相关代码。
咦,postReadBuffer不就是prepare流程会调用到的函数吗,它会发送kWhatReadBuffer给自己的消息处理函数,然后启动onReadBuffer的操作,从解析器的source,比如MP3Source中读取64帧的buffer。这个过程上一节已经分析过了,这里就不分析了。
初始化Decoder
Decoder是Nuplayer的一个内部类,它在start流程中的instantiateDecoder被初始化。start流程是如何调用到instantiateDecoder,可以直接看时序图。
获取格式信息
先来看看mSource->getFormat是如何获取到格式信息的。mSource是Nuplayer::Source类型的,前面已经知道了mSource保存的是Nuplayer::Source的子类Nuplayer::GenericSource对象。由于GenericSource没有实现getFormat,所以这里先调用了Source::getFormat。
接着调用了子类GenericSource的getFormatMeta,getFormatMeta再去调用到getFormatMeta_l。
我们上一节已经知道了mAudioTrack.mSource就是MP3Source wrapper的binder调用。所以这里source->getFormat()最终调用的是 MP3Source::getFormat。这个函数会返回MetaDataBase mMeta,这个是一个存储类,用于保存文件的详细信息,比如采样率,比特流,通道数量等等。
这里我们知道了原来获取格式就是去获取MetaData,但是在返回调用的时候又调用了convertMetaDataToMessage。顾名思义,这个函数的作用就是把MetaData转换成AMessage,AMessage也是信息存储的一个类。
配置Decoder
获得格式信息之后,会调用一个比较重要的函数NuPlayer::Decoder::onConfigure,我们来看看这个函数做了什么。
可以看出函数onConfigure会先去创建MediaCodec,来看看CreateByType会去做什么操作
MediaCodecList::findMatchingCodecs的过程有点绕,直接来看时序图。
从时序图可以看出这个过程会去通过MediaPlayerService获取server端的MediaCodecList。如果没有已存在的解码器列表,会去重新获取,从omxStore中去获取列表。omxStore是一个驻留在Main_codecservice中的服务,它会在开机的时候使用MediaCodecsXmlParser去解析xml文件 ,获取到编解码器列表。omx相关的东西后续会开一节来讲解。
来看看codec->init(componentName)操作。componentName是一个形如OMX.google.vorbis.decoder的AString。
到了这里ACodec已经创建完毕了,并且已经保存在MediaCodec的成员mCodec中了,往后就是通过MediaCodec来控制ACodec,继而控制解码器了。来梳理一下decoder初始化流程:
1.NuPlayer创建Decoder,保存在NuPlayer的sp<DecoderBase> mAudioDecoder成员中。
2.在创建MediaCodec之前会去查找编解码列表,找到匹配的omx组件。
3.创建MediaCodec,保存在Decoder的sp<MediaCodec> mCodec成员中。配置MediaCodec时把匹配到的omx组件传递给它。
4.在MediaCodec::init中创建ACodec,保存在MediaCodec的sp<CodecBase> mCodec成员中。
接下来就是ACodec从ACodecBufferChannel获取解析后的数据流,然后传给真正的解码器去解码了。这个过程后面整理好相关逻辑再来讲…
原文链接:https://blog.csdn.net/qq_27136111/java/article/details/94594719
联系客服