您的位置:华清远见教育科技集团 >> Android资料 >> Android原生层媒体播放过程  
 
Android原生层媒体播放过程
分享到:

在Android中,为了更好的支持音频、视频等媒体的播放并提供统一的接口,Android引入了媒体播放服务(Media Player Service)的概念。在整个媒体播放框架中采用的仍然是C/S架构,在本节中将着重介绍原生层的媒体播放。下图显示了媒体播放的类图。


媒体播放类图

其中IMediaPlayerService为封装起来的媒体播放服务接口,BnMediaPlayerService为IMediaPlayerService的本地对象,BpMediaPlayerService为远程IMediaPlayerService对象在本地进程中的代理。在Froyo中,目前能够提供的播放媒体类型为PV_PLAYER(PVPlayer)、SONIVOX_PLAYER(MidiFile)、VORBIS_PLAYER(VorbisPlayer)、STAGEFRIGHT_PLAYER(StagefrightPlayer)等。

下图所示为原生服务部分的状态切换关系。


原生服务状态切换关系

IMediaPlayerClient为封装起来的媒体播放客户端接口,BnMediaPlayerClient为IMediaPlayerClient的本地对象,BpMediaPlayerClient为远程IMediaPlayerClient对象在本地进程中的代理。

IMediaPlayer 为封装起来的本地媒体播放客户端接口,BnMediaPlayer为IMediaPlayer的本地对象,BpMediaPlayer为远程IMediaPlayer对象在本地进程中的代理。

为了使上层代码能够利用媒体播放服务,需要向服务管理器注册媒体播放服务,媒体播放服务的注册过程为:

void MediaPlayerService::instantiate()
    {
    defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());
    }

获取媒体播放服务的实现如下:

代码:MediaPlayer::getMediaPlayerService()的实现

const sp< IMediaPlayerService>& MediaPlayer::getMediaPlayerService()
    {
     Mutex::Autolock _l(sServiceLock);
     if (sMediaPlayerService.get()==0) {
     sp< IServiceManager> sm=defaultServiceManager();//服务管理器
     sp< IBinder> binder;
     do {
      binder=sm->getService(String16("media.player"));//获取媒体播放服务
      if (binder !=0)
      break;
      LOGW("MediaPlayerService not published, waiting...");
      usleep(500000); // 0.5s
    } while(true);
    if (sDeathNotifier==NULL) {
      sDeathNotifier=new DeathNotifier();//僵死通知器
    }
    binder->linkToDeath(sDeathNotifier);
    sMediaPlayerService=interface_cast< IMediaPlayerService>(binder);
    }
    LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?");
    return sMediaPlayerService;
    }

媒体服务为Java层提供的Java JNI接口位于android_media_MediaPlayer.cpp文件中。主要的接口包括:setDataSource、_setVideoSurface、prepare、prepareAsync、_start、_stop、getVideoWidth 、getVideoHeight、seekTo、_pause、isPlaying、getCurrentPosition、getDuration、_release、_reset、setAudioStreamType、setAudioStreamType、setLooping 、isLooping、setVolume、getFrameAt、native_invoke、native_setMetadataFilter、native_getMetadata、native_init、native_setup、native_finalize、snoop等。

媒体播放的基本过程如下图所示。


媒体播放的基本过程

流程说明:

在系统启动时,register_android_media_MediaPlayer()将会被调用,完成媒体播放服务在服务管理器上的注册。

当进行媒体播放时,需首先创建一个Java层的MediaPlayer对象。通过System.loadLibrary()方法加载“media_jni”共享库,然后完成原生MediaPlayer对象的初始化工作。在构造Java层的MediaPlayer对象过程中,需要创建一个JNIMediaPlayerListener对象并添加到原生MediaPlayer对象中。

为了进行媒体播放,在创建好MediaPlayer对象后,需要为MediaPlayer对象设定数据源。如果原生服务对象不存在,则创建一个原生服务客户端对象并建立与服务器端对象的联系,原生媒体播放服务将会根据数据源的类型提供相应的播放服务。目前支持的媒体类型包括mid、midi、smf、xmf、imy(iMelody Ringtone Format)、rtttl(Ring Tone Text Transfer Language)、rtx、ota、ogg、oga等。

在建立C/S连接后,如果播放的是视频文件,需要为视频文件设置播放的Surface,同时设置流媒体类型是音乐、来电铃声、提示音还是闹钟等。

在完成基于异步的准备工作后,即可执行媒体播放任务了,通过调用android_media_MediaPlayer_start()原生方法即可进行媒体播放工作。

如果需要进行暂停,需要调用android_media_MediaPlayer_pause()方法;如果需要停止媒体的播放,需要调用android_media_MediaPlayer_stop()原生方法。

除了这些基本的方法外,Android还提供了android_media_MediaPlayer_setVolume原生方法来设置音量;提供了android_media_MediaPlayer_getDuration原生方法来获得已播时间;提供了android_media_MediaPlayer_isPlaying()原生方法来获得播放状态;提供了android_media_MediaPlayer_seekTo()原生方法来设置进度。

 更多相关文章

·Android 视频解码过程详解
·Android 视频编码源码分享
·Android 双缓冲局部渲染
·Android Overlay硬件加速
·Android OpenGL ES渲染方式