分享

Android 9.0 multimedia框架解析(四)start过程

 开花结果 2020-04-29

概述

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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多