1. 程式人生 > >MediaPlayer-MediaPlayerService-MediaPlayerService::Client的三角關係

MediaPlayer-MediaPlayerService-MediaPlayerService::Client的三角關係

  • 摘要:1.MediaPlayer 是客戶端2.MediaPlayerService和MediaPlayerService::Client是伺服器端。 2.1MediaPlayerService實現IMediaPlayerService定義的業務邏輯,其主要功能是根據 MediaPlayer::setDataSource輸入的URL呼叫create函式建立對應的 Player.2.2MediaPlayerService::Client實現IMediaPlayer定義的業務邏輯,其主要功能包括
  • 1. MediaPlayer是客戶端

     

    2. MediaPlayerService和MediaPlayerService::Client是伺服器端。

     

    2.1 MediaPlayerService實現IMediaPlayerService定義的業務邏輯,其主要功能是根據MediaPlayer::setDataSource輸入的URL呼叫create函式建立對應的Player.

     

    2.2 MediaPlayerService::Client實現IMediaPlayer定義的業務邏輯,其主要功能包括start, stop, pause, resume...,其實現方法是呼叫MediaPlayerService create的Player中的對應方法來實現具體功能。

     

    2.3 它們的三角戀如下圖所示:

     

    MediaPlayer-MediaPlayerService-MediaPlayerService::Client的三角關係

     

    3. IXX是什麼東東?

     

    在一個BnXXX或BpXXX都派生於兩個類,具體情況如下:

     

    class BpXXX : public IXXX, public BpRefBase

     

    class BnXXX : public IXXX, public BBinder

     

    3.1 看到了吧,BpXXX和BnXXX都派生於IXXX,哪IXXX又是做什麼的呢? 明確地告訴你,定義業務邏輯,但在BpXXX與BnXXX中的實現方式不同:

     

    1) 在BpXXX中,把對應的binder_transaction_data打包之後通過BpRefBase中的mRemote(BpBinder)傳送出去,並等待結果

     

    2) 在BnXXX中,實現對應的業務邏輯,通過呼叫BnXXX派生類中的方法來實現,如MediaPlayerService::Client

     

    懂了吧, IXXX定義業務邏輯

     

    3.2 哪另外一個做什麼呢?

     

    從上圖可以看出,是用來進行程序間通訊用的。

     

    BpRefBase中有一個mRemote(BpBinder)用來與Binder驅動互動用的。

     

    BBinder是用來從Binder驅動中接收相關請求,並進行相關處理的。

    4. 不得不說的MediaPlayerService

     

    class MediaPlayerService : public BnMediaPlayerService

     

    它本身用來實現IMediaPlayerService中定義的業務邏輯,可以看看IMediaPlayerService到底定義了些什麼東東?


    class IMediaPlayerService: public IInterface
    {
    public:
    DECLARE_META_INTERFACE(MediaPlayerService);
    virtual sp createMediaRecorder(pid_t pid) = 0;
    virtual sp createMetadataRetriever(pid_t pid) = 0;
    virtual sp create(pid_t pid, const sp &; client, const char* url, const KeyedVector *headers = NULL) = 0;
    virtual sp create(pid_t pid, const sp &; client, int fd, int64_t offset, int64_t length) = 0;
    virtual sp createMediaConfig(pid_t pid ) = 0;
    virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
    virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
    virtual sp getOMX() = 0;
    // Take a peek at currently playing audio, for visualization purposes.
    // This returns a buffer of 16 bit mono PCM data, or NULL if no visualization buffer is currently available.
    virtual sp snoop() = 0;
    };

    從上面可以看出,還說自己是一個MediaPlayerService,而且還向大內總管ServiceManager進行了註冊,就這麼個create 和decode,能做什麼呢? 我們最熟悉的start ,stop, pause, resume...怎麼不見呢?沒有這些東東,MediaPlayer需要的功能如何實現呢?

     

    帶著這麼多疑問,我們先看看MediaPlayerService是如何實現上述功能的,它到底做了些什麼?

     

    還是讓程式碼自己說話吧:


    sp MediaPlayerService::create(
    pid_t pid, const sp &; client, const char* url,
    const KeyedVector *headers)
    {
    int32_t connId = android_atomic_inc(&;mNextConnId);
    sp c = new Client(this, pid, connId, client);
    LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
    if (NO_ERROR != c->setDataSource(url, headers))
    {
    c.clear();
    return c;
    }
    wp w = c;
    Mutex::Autolock lock(mLock);
    mClients.add(w);
    return c;
    }

    原來如此,它負責建立MediaPlayer需要的對應功能,建立了Client(MediaPlayerService),MediaPlayerService::Client的定義如下:

     

    class Client : public BnMediaPlayer, 它實現了IMediaPlayer定義的業務邏輯,哪就看看IMediaPlayer定義了些什麼:


    class IMediaPlayer: public IInterface
    {
    public:
    DECLARE_META_INTERFACE(MediaPlayer);
    virtual void disconnect() = 0;
    virtual status_t setVideoSurface(const sp &; surface) = 0;
    virtual status_t setSurfaceXY(int x,int y) = 0;/*add by h00186041 add interface for surface left-up position*/
    virtual status_t setSurfaceWH(int w,int h) = 0;/*add by h00186041add interface for surface size*/
    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 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;
    virtual status_t suspend() = 0;
    virtual status_t resume() = 0;
    // Invoke a generic method on the player by using opaque parcels
    // for the request and reply.
    // @param request Parcel that must start with the media player
    // interface token.
    // @param[out] reply Parcel to hold the reply data. Cannot be null.
    // @return OK if the invocation was made successfully.
    virtual status_t invoke(const Parcel&; request, Parcel *reply) = 0;
    // Set a new metadata filter.
    // @param filter A set of allow and drop rules serialized in a Parcel.
    // @return OK if the invocation was made successfully.
    virtual status_t setMetadataFilter(const Parcel&; filter) = 0;
    // Retrieve a set of metadata.
    // @param update_only Include only the metadata that have changed
    //since the last invocation of getMetadata.
    //The set is built using the unfiltered
    //notifications the native player sent to the
    //MediaPlayerService during that period of
    //time. If false, all the metadatas are considered.
    // @param apply_filter If true, once the metadata set has been built based
    // on the value update_only, the current filter is
    // applied.
    // @param[out] metadata On exit contains a set (possibly empty) of metadata.
    //Valid only if the call returned OK.
    // @return OK if the invocation was made successfully.
    virtual status_t getMetadata(bool update_only,
    bool apply_filter,
    Parcel *metadata) = 0;
    }

    終於找到了思念已久的start, stop, pause, resume...

     

    所以MediaPlayer::setDataSource返回時,會建立一個與MediaPlayerService::Client對應的BpMediaPlayer,用於獲取MediaPlayerService::Client的各項功能。

     

    4. 1 MediaPlayer又是如何找到MediaPlayerService::Client的呢? 只有MediaPlayerService才向ServiceManager進行了註冊,所以MediaPlayer必須先獲取 BpMediaPlayerService,然後通過BpMediaService的管理功能create,來建立一個 MediaPlayerService::Client.

     

    4.2 為什麼不直接定義一個MediaPlayer向ServiceManager註冊呢?

     

    也 許是為了系統簡化吧,MediaPlayerService包含的功能不只是Client, 還有AudioOutput,AudioCache,MediaConfigClient功能。現在明白了吧,MediaPlayerService就是 一個媒體服務的介面,它先把客人接回來,再根據客人的需求,安排不同的員工去做,就這麼簡單。