第二部分 MediaPlayer的接口与架构

2.1 整体框架图         MediaPlayer的各个库之间的结构比较复杂,可以用下图的表示

    在各个库中,libmedia.so位于核心的位置,它对上层的提供的接口主要是MediaPlayer类,类libmedia_jni.so通过调用MediaPlayer类提供对JAVA的接口,并且实现了android.media.MediaPlayer类。 libmediaplayerservice.so是Media的服务器,它通过继承libmedia.so的类实现服务器的功能,而libmedia.so中的另外一部分内容则通过进程间通讯和libmediaplayerservice.so进行通讯。libmediaplayerservice.so的真正功能通过调用OpenCore Player来完成。     MediaPlayer部分的头文件在frameworks/base/include/media/目录中,这个目录是和libmedia.so库源文件的目录frameworks/base/media/libmedia/相对应的。主要的头文件有以下几个:
IMediaPlayerClient.h mediaplayer.h IMediaPlayer.h IMediaPlayerService.h MediaPlayerInterface.h
    在这些头文件mediaplayer.h提供了对上层的接口,而其他的几个头文件都是提供一些接口类(即包含了纯虚函数的类),这些接口类必须被实现类继承才能够使用。     整个MediaPlayer库和调用的关系如下图所示:

整个MediaPlayer在运行的时候,可以大致上分成Client和Server两个部分,它们分别在两个进程中运行,它们之间使用Binder机制实现IPC通讯。从框架结构上来看,IMediaPlayerService.h、IMediaPlayerClient.h和MediaPlayer.h三个类定义了MeidaPlayer的接口和架构,MediaPlayerService.cpp和mediaplayer.coo两个文件用于MeidaPlayer架构的实现,MeidaPlayer的具体功能在PVPlayer(库libopencoreplayer.so)中的实现。

2.2 头文件IMediaPlayerClient.h   
        IMediaPlayerClient.h用于描述一个MediaPlayer客户端的接口,描述如下所示:
class IMediaPlayerClient: public IInterface
{
public:
    DECLARE_META_INTERFACE(MediaPlayerClient);
    virtual void notify(int msg, int ext1, int ext2) = 0;
};

class BnMediaPlayerClient: public BnInterface<IMediaPlayerClient>
{
public:
    virtual status_t  onTransact( uint32_t code,
                                  const Parcel& data,
                                  Parcel* reply,
                                  uint32_t flags = 0);
};
        在定义中,IMediaPlayerClient类继承IInterface,并定义了一个MediaPlayer客户端的接口,BnMediaPlayerClient继承了BnInterface<IMediaPlayerClient>,这是为基于Android的基础类Binder机制实现在进程通讯而构建的。事实上,根据BnInterface类模版的定义BnInterface<IMediaPlayerClient>类相当于双继承了BnInterface和ImediaPlayerClient。这是Android一种常用的定义方式。

2.3 头文件mediaplayer.h
        mediaplayer.h是对外的接口类,它最主要是定义了一个MediaPlayer类:
class MediaPlayer : public BnMediaPlayerClient
{
public:
    MediaPlayer();
    ~MediaPlayer();
    void onFirstRef();
    void disconnect();
    status_t    setDataSource(const char *url);
    status_t    setDataSource(int fd, int64_t offset, int64_t length);
    status_t    setVideoSurface(const sp<Surface>& surface);
    status_t    setListener(const sp<MediaPlayerListener>& listener);
    status_t    prepare();
    status_t    prepareAsync();
    status_t    start();
    status_t    stop();
    status_t    pause();
    bool        isPlaying();
    status_t    getVideoWidth(int *w);
    status_t    getVideoHeight(int *h);
    status_t    seekTo(int msec);
    status_t    getCurrentPosition(int *msec);
    status_t    getDuration(int *msec);
    status_t    reset();
    status_t    setAudioStreamType(int type);
    status_t    setLooping(int loop);
    status_t    setVolume(float leftVolume, float rightVolume);
    void    notify(int msg, int ext1, int ext2);
    static    sp<IMemory>    decode(const char* url, uint32_t *pSampleRate, int* pNumChannels);
    static    sp<IMemory>    decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels);
//……
}
    从接口中可以看出MediaPlayer类刚好实现了一个MediaPlayer的基本操作,例如播放(start)、停止(stop)、暂停(pause)等。
    另外的一个类DeathNotifier在MediaPlayer类中定义,它继承了IBinder类中的DeathRecipient类:
class DeathNotifier: public IBinder:: DeathRecipient
{
public:
    DeathNotifier() {}
    virtual ~DeathNotifier();
    virtual void binderDied(const wp<IBinder>& who);
};
        事实上,MediaPlayer类正是间接地继承了IBinder,而MediaPlayer:: DeathNotifier类继承了IBinder:: DeathRecipient,这都是为了实现进程间通讯而构建的。

2.4 头文件IMediaPlayer.h
        IMediaPlayer.h主要的的内容是一个实现MediaPlayer功能的接口,它的主要定义如下所示:
class IMediaPlayer: public IInterface
{
public:
    DECLARE_META_INTERFACE(MediaPlayer);
    virtual void    disconnect() = 0;
    virtual status_t    setVideoSurface(const sp<ISurface>& surface) = 0;
    virtual status_t    prepareAsync() = 0;
    virtual status_t    start() = 0;
    virtual status_t    stop() = 0;
    virtual status_t    pause() = 0;
    virtual status_t    isPlaying(bool* state) = 0;
    virtual status_t    getVideoSize(int* w, int* h) = 0;
    virtual status_t    seekTo(int msec) = 0;
    virtual status_t    getCurrentPosition(int* msec) = 0;
    virtual status_t    getDuration(int* msec) = 0;
    virtual status_t    reset() = 0;
    virtual status_t    setAudioStreamType(int type) = 0;
    virtual status_t    setLooping(int loop) = 0;
    virtual status_t    setVolume(float leftVolume, float rightVolume) = 0;
};
class BnMediaPlayer: public BnInterface<IMediaPlayer>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,   
                                    Parcel* reply,
                                    uint32_t flags = 0);
};
        在IMediaPlayer类中,主要定义MediaPlayer的功能接口,这个类必须被继承才能够使用。值得注意的是,这些接口和MediaPlayer类的接口有些类似,但是它们并没有直接的关系。事实上,在MediaPlayer类的各种实现中,一般都会通过调用IMediaPlayer类的实现类来完成。

2.5 头文件IMediaPlayerService.h
        IMediaPlayerService.h用于描述一个MediaPlayer的服务,定义方式如下所示:
class IMediaPlayerService: public IInterface
{
public:
    DECLARE_META_INTERFACE(MediaPlayerService);
    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) = 0;
    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
    virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels) = 0;
    virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels) = 0;
};
class BnMediaPlayerService: public BnInterface<IMediaPlayerService>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

由于具有纯虚函数,IMediaPlayerService 以及BnMediaPlayerService必须被继承实现才能够使用,在IMediaPlayerService定义的create和decode等接口,事实上是必须被继承者实现的内容。注意,create的返回值的类型是sp<IMediaPlayer>,这个IMediaPlayer正是提供实现功能的接口。

第二部分 MediaPlayer的接口与架构的更多相关文章

  1. Android Multimedia框架总结(七)C++中MediaPlayer的C/S架构补充及MediaService介绍

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼,文章链接: http://blog.csdn.net/hejjunlin/article/details/52465168 前面一篇主要介绍 ...

  2. was集群下基于接口分布式架构和开发经验谈

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/luozhonghua2014/article/details/34084935    某b项目是我首 ...

  3. 【Android 多媒体开发】 MediaPlayer 状态机 接口 方法 解析

    作者 : 韩曙亮 转载请著名出处 :  http://blog.csdn.net/shulianghan/article/details/38487967 一. MediaPlayer 状态机 介绍 ...

  4. Android接口与架构(驱动开发)翻译官方文档

    Android接口与架构 Android在设备的规格与驱动方面给了你很大的自由来实现.HAL层提供了一个标准的方式来打通Android系统层与硬件层.Android系统是开源的,所以你能够在接口和性能 ...

  5. Android Multimedia框架总结(六)C++中MediaPlayer的C/S架构

    转载请把头部出处链接和尾部二维码一起转载,本文出自: http://blog.csdn.net/hejjunlin/article/details/52435789 前面几节中,都是通过java层调用 ...

  6. 前端笔记之NodeJS(四)MongoDB数据库&Mongoose&自制接口&MVC架构思想|实战

    一.MongoDB数据库 1.1 NoSQL简介 随着互联网web2.0网站的兴起,传统的SQL数据库(关系数据库)在应付web2.0网站,特别是超大规模和高并发的SNS(social network ...

  7. Hibernate(八)__级联操作、struts+hibernate+接口编程架构

    级联操作 所谓级联操作就是说,当你进行主对象某个操作时,从对象hibernate自动完成相应操作. 比如: Department <---->Student 对象关系,我希望当我删除一个d ...

  8. Java SE 第二十二讲----接口interface

    1.接口:interface:接口的地位等同于class,接口中的所有方法都是抽象方法.在声明接口中的方法的时候,可以使用abstract关键字也可以不使用.通常情况下,都会省略掉abstract关键 ...

  9. JAVAEE企业级应用开发浅谈第二辑:MVC和三层架构

    上海尚学堂警句:一份信心,一份努力,一份成功:十分信心,十分努力,十分成功. Step1.情景概要 Hello,小伙伴们,昨天跟大家分享了JAVA EE 企业级应用开发中大家耳熟能详的概念-三层架构, ...

随机推荐

  1. php header头信息 举例

    发布:sunday01   来源:Net     [大 中 小] 转自:http://www.jbxue.com/article/6915.html 用于演示PHP header()函数用法的代码,介 ...

  2. sirius的学习笔记(2)

    原文来自网络,侵权删 if both values of in a or expression are true ,Python will select the first one, and the ...

  3. Android笔记——Bitmap自动取色(纯搬运)

    2015/6/12更新:发现一个更好的,带demo https://github.com/MichaelEvans/ColorArt 说明: 这个是一个老外写的自动自动从bitmap中取主色与第二主色 ...

  4. 【BZOJ 2744 】[HEOI2012]朋友圈

    Description 在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着.一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最 ...

  5. 【BZOJ3524】 [Poi2014]Couriers

    Description 给一个长度为n的序列a.1≤a[i]≤n.m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. ...

  6. python学习笔记22(group)

    正则表达式中,group()用来提出分组截获的字符串,()用来分组 import re a = "123abc456" print re.search("([0-9]*) ...

  7. linux内核分析之内存管理

    1.struct page /* Each physical page in the system has a struct page associated with * it to keep tra ...

  8. E437: terminal capability "cm" required

    执行 vi 的时候出现:E437: terminal capability "cm" required 临时解决: export TERM=xterm

  9. obj转换成数组

    原则上obj是不能转换成数组的.首先array也是obj.只是一个特殊的object. obj一个很关键的点,是拥有成员和方法,撇开方法不说,obj就是一个key-value结构.也就是哈希数组,而j ...

  10. <base target="_blank"/>

    <base target=_blank> 是将基本链接的目标框架都改为新页打开