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