Android MediaPlayer接口及狀態遷移


[時間:2016-09] [狀態:Open]
[關鍵詞:android,mediaplayer,播放接口,播放狀態圖]

引言

本文內容相對簡單,作為后續處理的起點,簡要整理了Android MediaPlayer的接口層,並且這里只會涉及c層的實現,至於上層的JNI/跨進程調用邏輯,建議參考其他資料。
整理本文的目的僅供個人后續參考使用。

MediaPlayer Interface

我們可以在Android源碼中找到MediaPlayerInterface的定義如下:(這里只列出接口信息,詳細內容建議參考源碼)

// from frameworks/av/include/media/MediaPlayerInterface.h
// abstract base class - use MediaPlayerInterface
class MediaPlayerBase : public RefBase
{
public:
    // AudioSink: abstraction layer for audio output
    class AudioSink : public RefBase {...};

    MediaPlayerBase() : mCookie(0), mNotify(0) {}
    virtual             ~MediaPlayerBase() {}
    virtual status_t    initCheck() = 0;
    virtual bool        hardwareOutput() = 0;

    virtual status_t    setUID(uid_t /* uid */);

    virtual status_t    setDataSource(
            const sp<IMediaHTTPService> &httpService,
            const char *url,
            const KeyedVector<String8, String8> *headers = NULL) = 0;
    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) = 0;
    virtual status_t    setDataSource(const sp<IStreamSource>& /* source */);
    virtual status_t    setDataSource(const sp<DataSource>& /* source */);

    // pass the buffered IGraphicBufferProducer to the media player service
    virtual status_t    setVideoSurfaceTexture(
                                const sp<IGraphicBufferProducer>& bufferProducer) = 0;

    virtual status_t    prepare() = 0;
    virtual status_t    prepareAsync() = 0;
    virtual status_t    start() = 0;
    virtual status_t    stop() = 0;
    virtual status_t    pause() = 0;
    virtual bool        isPlaying() = 0;
    virtual status_t    setPlaybackSettings(const AudioPlaybackRate& rate);
    virtual status_t    getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
    virtual status_t    setSyncSettings(const AVSyncSettings& sync, float /* videoFps */);
    virtual status_t    getSyncSettings(AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */);
    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    setLooping(int loop) = 0;
    virtual player_type playerType() = 0;
    virtual status_t    setParameter(int key, const Parcel &request) = 0;
    virtual status_t    getParameter(int key, Parcel *reply) = 0;

    // default no-op implementation of optional extensions
    virtual status_t setRetransmitEndpoint(const struct sockaddr_in* /* endpoint */);
    virtual status_t getRetransmitEndpoint(struct sockaddr_in* /* endpoint */);
    virtual status_t setNextPlayer(const sp<MediaPlayerBase>& /* next */);

    virtual status_t    invoke(const Parcel& request, Parcel *reply) = 0;
    virtual status_t    getMetadata(const media::Metadata::Filter& /* ids */, Parcel* /* records */);

    void        setNotifyCallback(void* cookie, notify_callback_f notifyFunc);
    void        sendEvent(int msg, int ext1=0, int ext2=0, const Parcel *obj=NULL);

    virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const;

private:
    friend class MediaPlayerService;

    Mutex               mNotifyLock;
    void*               mCookie;
    notify_callback_f   mNotify;
};

// Implement this class for media players that use the AudioFlinger software mixer
class MediaPlayerInterface : public MediaPlayerBase
{
public:
    virtual             ~MediaPlayerInterface() { }
    virtual bool        hardwareOutput() { return false; }
    virtual void        setAudioSink(const sp<AudioSink>& audioSink) { mAudioSink = audioSink; }
protected:
    sp<AudioSink>       mAudioSink;
};

// Implement this class for media players that output audio directly to hardware
class MediaPlayerHWInterface : public MediaPlayerBase
{
public:
    virtual             ~MediaPlayerHWInterface() {}
    virtual bool        hardwareOutput() { return true; }
    virtual status_t    setVolume(float leftVolume, float rightVolume) = 0;
    virtual status_t    setAudioStreamType(audio_stream_type_t streamType) = 0;
};

通常我們的調用邏輯是,構造函數->setDataSource->SetVideoSurfaceTexture->prepare/prepareAsync->start->stop->reset->析構函數,按照實際需求還會調用pause、isPlaying、getDuration、getCurrentPosition、setLooping、seekTo等。
各個接口具體含義參考下表:

方法 說明
setDataSource 設置多媒體數據來源(位置)
setVideoSurfaceTexture 設置用SurfaceHolder來顯示多媒體
prepare 准備(同步)
prepareAsync 准備(異步)
start 開始播放
stop 停止播放
reset 重置MediaPlayer對象為剛剛創建的狀態
getCurrentPosition 得到當前播放位置
getDuration 得到文件的時間
isPlaying 是否正在播放
pause 暫停
seekTo 指定播放的位置(以毫秒為單位的時間)
setLooping 設置是否循環播放

MediaPlayer狀態圖

MediaPlayer的狀態圖如下:
MediaPlayer state diagram

這個狀態圖對應的java層的MediaPlayer。不過可以參考,在實際的源碼實現時,不會完全參考這個狀態圖,可能有更多的內部狀態和簡化狀態。
比如,你可以不調用prepare,直接調用start。
圖中各個狀態的遷移,建議參考MediaPlayer的官方文檔。

參考資料

  1. Google Android MediaPlayer
  2. Android多媒體MediaPlayer使用詳解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM