分享

Android 9.0 multimedia框架解析(二)setDataSource过程

 开花结果 2020-04-28

概述

setDataSource是使用MediaPlayer播放音乐文件的重要步骤。这个操作会去创建NuplayerDriver,Nuplayer,然后根据传递的参数(文件信息)创建GenericSource。为后续的prepare或者prepareAsync操作作准备。

类说明

1.NuPlayerFactory:工具类。在本章中,它用于构造NuplayerDriver。

2.MediaPlayerFactory:工具类。在本章中,它用于创建NuPlayerFactory和TestPlayerFactory。

3.NuplayerDriver:它是Nuplayer的wrapper。它继承了MediaPlayerInterface接口,然后MediaPlayerInterface继承了MediaPlayerBase。MediaPlayerService对Nuplayer的访问是通过NuplayerDriver的父类MediaPlayerInterface来实现的。所以它相当于一个中转站。

4.Nuplayer::GenericSource:解析模块。从extractor中读取解封装之后的文件数据。它是Nuplayer::Source的子类。

5.Nuplayer::Decoder:解码模块。在播放的时候会调用MediaCodec去获取编解码列表,选择合适解码库。

6.MediaCodec:Decoder的代工。根据Decoder的要求,去MediaCodecList中查找解码器信息,然后选择合适的解码库。负责跟ACodec进行数据交互。

7.MediaCodecList:用于获取编解码信息列表,这些信息是从OmxStore那里获取的。OmxStore是一个HAL server(也就是hidl的server端)。在media.codec进程中,会注册OmxStore和Omx服务,OmxStore先把解码器信息解析出来,然后保存在自己的成员变量中。

8.Nuplayer:这个类主要是扮演操控者的角色,根据NuplayerDriver的指令去控制Decoder和Source,也就是协调解析和解码的工作。

9.ACodec:主要负责解码相关工作。通过IOMXNode去控制解码器:设置参数,获取参数等。将从ACodecBufferChannel获取的解析之后的文件数据送给解析器。

10.MediaPlayerService::Client:它继承于BnMediaPlayer,用于上层对音乐播放流程的控制。

总bouml时序图

  

我把setDataSource,prepareAsync,start这几个重要步骤放在同一张时序图里面。目的是为了对nuplay的工作流程有一个整体上的认识。这一节只讲setDataSource流程,所以只需看setDataSource那一部分就行了。

时序图说明

Nuplayer、Decoder、GenericSource中有些控制块是有颜色的。因为这三个类都有消息发送处理这种异步机制,所以为了更好的表示时序图,我把消息的源和目标都标成同样的颜色。

setDataSource过程可以分解为下面几个子流程:

1.创建NuPlayerDriver和NuPlayer。返回NuPlayerDriver的父类指针MediaPlayerBase指针给MediaPlayerService::Client。

2.通过NuPlayerDriver提供的setDataSource以异步的方式去创建GenericSource,然后把文件描述符等信息保存到GenericSource中。

3.设置NuPlayerDriver状态,为下一个步骤prepareAsync(下一节会讲)做准备。

下面对这三点进行展开讲述

1.创建NuPlayerDriver和NuPlayer

MediaPlayerService::Client在创建NuPlayerDriver的时候并不是直接new NuPlayerDriver,而是通过NuPlayerFactory这一个工具类来创建的。这个类只是让Client多了一个选择而已。在android 6.0中有三个选择StagefrightPlayerFactory、NuPlayerFactory、TestPlayerFactory。

但是高版本已经把StagefrightPlayerFactory去掉了,也就是说AwesomePlayer已经在高版本中消失了。创建出来的NuplayerDriver保存在全局变量sFactoryMap中,并且设置它的索引key为NU_PLAYER=4。在创建的时候会传递pid给NuPlayerDriver,这个pid是调用者的pid。比如我用安卓原生的music播放音乐,那这个pid就是com.android.music的。

创建NuPlayerDriver的时候会去创建NuPlayer,并保存为自己的成员变量mPlayer。由于NuPlayer是继承于AHandler,所以还得给它new 一个ALooper提供一个循环。这个过程没啥操作,这里就不赘述了。

2.创建GenericSource

NuPlayerDriver是以异步的方式设置数据源的。

从总时序图中,可以看出new GenericSource之后的source->setDataSource仅仅是将文件描述符等信息保存到GenericSource中。由于这里的设置源是异步调用,所以需要NuPlayer给NuPlayerDriver答复。

可以看出setDataSource这个操作仅仅是设置数据源信息而已,并没有去加载解析器和解码器。在notifySetDataSourceCompleted中有一个重要的操作就是:当返回的状态OK的时候会设置mState的状态为STATE_UNPREPARED,也就是未准备的状态。所以从这里我们也可以看出下一个操作就是prepare操作了


原文链接:https://blog.csdn.net/qq_27136111/java/article/details/94594673

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

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多