到目前工作了将近两年时间了,虽然从研究生阶段开始就迷恋上了博客,但因为种种原因从未写过一次,基本是记录在word文档中,现在翻来看看确实有点乱。今天偶然机会看到一同事的博客之路,甚为触动,遂决定将工作经历慢慢记录下来,希望能够坚持!!

从参加工作开始吧,研究生期间也参加了几个项目,但想想实用性不大。我第一份工作(目前仍是)是做android系统开发的,主要是针对framework层的开发,进公司首先接触的就是MediaPlayer框架,这里就把我对它的简单理解记录下来,作为我的处女博,还望大家支持。

1.概述下MediaPlayer框架

android系统中的MediaPlayer主要包括应用层、Framework层、JNI层、框架中的C、C++层以及HAL层等部分组成。下面我们主要研究框架中的Framework层、JNI层和C、C++层的工作流程,MediaPlayer整体框架如下图所示。

MediaPlayer android mediaplayer Android 分割_java

Android的媒体播放功能可以分成两部分,一部分是媒体播放应用,一部分是媒体播放服务,这两部分分别运行在不同的进程中。媒体播放应用包括Java程序和部分C、C++代码,媒体播放服务主要是C++代码。整个框架采取了C\S结构来进行对MediaPlayer的处理,服务器与客户端之间使用binder通信机制。媒体播放服务对外提供多个接口,其中有两个重要的接口:IMediaPlayerService和IMediaPlayer;IMediaPlayerService用于创建和管理播放实例,而IMediaPlayer接口则是播放接口,用于实现指定媒体文件的播放以及播放过程的控制。媒体播放应用向媒体播放服务提供的一个接口:IMediaPlayerClient,用于接收notify()。这些接口需要跨进程调用,涉及到binder机制。每个接口包括两部分实现,一部分是接口功能的真正实现(BnInterface),这部分运行在接口提供进程中;另一部分是接口的proxy(BpInterface),这部分运行在调用接口的进程中。


2.MediaPlayer工作流程

整个MediaPlayer在运行时,可以大致上分成Client和Server两个部分,它们分别在两个进程中运行,它们之间使用Binder机制实现进程间通讯。整个MediaPlayer运行流程如下图所示。

MediaPlayer android mediaplayer Android 分割_android_02


MediaPlayer大致流程可以分为以下几步:

首先,mediaserver 启动后就会把media相关的体制添加到servicemanager中,在应用程序启动前,体系中就有了MediaPlayerService管理体制。

第二,MediaPlayer的应用程序就会调用mediaplayer.java,利用其native_setup方法通过jni调用android_media_mediaplayer.cpp中相应的方法android_media_MediaPlayer_native_setup(),在其中调用mediaplayer.cpp中的方法通过new MediaPlayer()创建一个Mediaplayer对象,并将其指针保存返回给Java层保存在mNativeContext中。

第三,在android_media_mediaplayer.cpp中定义了JNINativeMethod类的数组gMethods,所以mediaplayer.java在调用MediaPlayer类的setDataSource()时便可找到对应的C++函数,传入多媒体数据路径(url、uri)。

第四,函数status_t MediaPlayer::setDataSource()根据url通过调用getMediaPlayerService()得到当前的BpMediaPlayerService,然后通过sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId))新建一个IMediaPlayer对象,对MediaPlayerService发出创建mediaplayer的请求。

第五,在MediaPlayerService.cpp中,通过create函数创建了BnMediaPlayer。BnMediaPlayerService则在获取IPC的调用请求后,在sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId)中创建一个MediaPlayerService::Client实例,作为另一个Binder通信服务端用于消息回调。

最后,完成了数据源的设置之后,到达Initialized状态,接着完成Prepare动作之后,到达对应Framework层的Prepared状态,然后就是进入对应Framework层的Started状态。


而我的主要工作是基于Android原生框架针对DVB等数字电视相关业务进行研究,设计一套可以实现电视节目正常播放及控制功能的DVB媒体播放框架。大致思路是在原生媒体框架MediaPlayerService服务中创建子服务DvbPlayer,按照Framework层、JNI层、C/C++层顺序搭建自身框架实现DVB媒体播放及控制功能,具体细节不便详述。希望我的浅显理解对你有所帮助。。