概述
先来回顾一下上文讲的MediaPlayerService::Client的setDataSource流程:首先创建NuplayerDriver和Nuplayer;然后通过NuplayerDriver以异步的方式设置数据源,在设置的过程中会构造GenericSource,把文件描述符等信息保存在GenericSource中;最后Nuplayer会通知NuplayerDriver我已经设置完数据源了,并且把NuplayerDriver中的状态设置为STATE_UNPREPARED,也就是未准备状态。由于setDataSource已经把状态设置为unprepare状态,所以下一个操作就是prepare操作了。我这里以prepareAsync为入口分析multimedia的处理流程。
类说明
1.RemoteMediaExtractor:binder server。RemoteMediaExtractor跟RemoteDataSource的作用是相似的,它也是将MediaExtractor保存为私有变量中,它的binder client通过它可以访问到MediaExtractor,间接解析多媒体文件。
2.MediaExtractor:extractor组件需继承它。在8.0版本中,它是一个binder server;而在9.0的版本中,它只是一个类而已,通过其他binder服务来调用它,间接binder化。通过它可以获得解析器的音频轨或者视频轨的信息。
3.RemoteMediaSource:binder server。为MediaSource提供跨进程访问的接口。
4.MediaSource:extractor组件需要集成它。通过它可以读取文件的数据。
5.剩下的一些类说明可以参考Android 9.0 multimedia框架解析(一)加载media extractor组件过程
.
总bouml时序图
下面的蓝色边框内的时序就是prepare相关的。
时序图说明:
prepare过程中有以下几个重要过程:
1.创建DataSource。前面的setDataSource仅仅是设置文件信息而已,这里才是真正的创建相关的数据源。
2.加载对应的解析器。并通过解析器创建解析器的source,这个source是MediaTrack格式,用于获取解析之后的文件数据。
3.从解析器中读取出已经解析完毕的数据,准备发送给ACodec解码。
创建DataSource
在上一节的分析中,我们知道了setDataSource过程的是:创建NuPlayerDriver、Nuplayer,然后调用它们的相关接口去创建GenericSource并把文件描述符等信息保存到GenericSource中。这个过程并没有创建DataSource,其实创建DataSource的真正过程是在这里。
在setDataSource结束的时候,设置了NuPlayerDriver的mState状态为STATE_UNPREPARED。这个mState在prepareAsync中会做判断,如果是STATE_UNPREPARED,则调用NuPlayer的prepareAsync。
status_t NuPlayerDriver::prepareAsync() {
switch (mState) {
case STATE_UNPREPARED: //setDataSource的时候会设置这个状态
mState = STATE_PREPARING;
mIsAsyncPrepare = true;
mPlayer->prepareAsync();
return OK;
case STATE_STOPPED:// this is really just paused. handle as seek to start
mAtEOS = false;
mState = STATE_STOPPED_AND_PREPARING;
mIsAsyncPrepare = true;
mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,true /* needNotify */);
return OK;
};
}
由于之前创建GenericSource的时候把GenericSource的父类指针Source传递给NuPlayer的mSource了,所以NuPlayer可以调用mSource来直接操作GenericSource。从NuPlayerDriver的prepareAsync到GenericSource的onPrepareAsync过程有两个消息发送接受过程,这样过程我不会去贴代码赘述,直接看bouml时序图,根据控制块的颜色来区分调用就行。
我们直接来看GenericSource的onPrepareAsync过程。
void NuPlayer::GenericSource::