stagefright继承于MediaPlayerInterface
通过VideoView对MediaPlayer的调用关系,分析一下MediaPlayer的接口层
VideoView:openVideo(){
mMediaPlayer = new MediaPlayer();
//设定回调函数
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
mMediaPlayer.setOnInfoListener(mInfoListener);
mDuration = -1;
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mCurrentBufferPercentage = 0;
//传入URL
mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
//与Surface建立链接
mMediaPlayer.setDisplay(mSurfaceHolder);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setScreenOnWhilePlaying(true);
//异步Prepare
mMediaPlayer.prepareAsync();
}
这里主要介绍setDataSource和prepareAsync,这是初始化的关键
注:创建Player,真正实现是MediaPlayerService创建的client,比较简单,不做介绍。
setDataSource有三种输入
const sp<IStreamSource> &source
int fd, int64_t offset, int64_t length
const char *uri, const KeyedVector<String8, String8> *headers
这里主要介绍URI方式,因为比较容易理解
setDataSource主要是保存URI
mStats.mFd = -1;
mStats.mURI = mUri;
prepareAsync:
status_t AwesomePlayer::prepareAsync_l() {
//创建onPrepareAsyncEvent事件,并post到TimedEventQueue中
mAsyncPrepareEvent = new AwesomeEvent(
this, &AwesomePlayer::onPrepareAsyncEvent);
mQueue.postEvent(mAsyncPrepareEvent);
}
AwesomePlayer::onPrepareAsyncEvent() {
//创建extractor
status_t err = finishSetDataSource_l();
//创建video decoder
status_t err = initVideoDecoder();
//创建audio decoder
status_t err = initAudioDecoder();
if (isStreamingHTTP()) {
//如果是网络流,调用onBufferingUpdate Event
postBufferingEvent_l();
} else {
//本地流,通知应用层,prepare完成
finishAsyncPrepare_l();
}
}
Prepare完成后,开始继续进入正常播放状态
当通知应用层prepare完成,最终调用
Videoview:mPreparedListener: onPrepared() {
//最主要的功能是调用
start();
}
后续在正常播放中,就会调用
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t pause() = 0;
virtual status_t seekTo(int msec) = 0;
完成实际操作
下面是所有继承MediaPlayerInterface的接口
virtual status_t initCheck() = 0;
virtual bool hardwareOutput() = 0;
virtual status_t setUID(uid_t uid) {
return INVALID_OPERATION;
}
virtual status_t setDataSource(
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) {
return INVALID_OPERATION;
}
// pass the buffered ISurfaceTexture to the media player service
virtual status_t setVideoSurfaceTexture(
const sp<ISurfaceTexture>& surfaceTexture) = 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 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;
// Right now, only the AAX TX player supports this functionality. For now,
// provide a default implementation which indicates a lack of support for
// this functionality to make life easier for all of the other media player
// maintainers out there.
virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) {
return INVALID_OPERATION;
}
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
//
// @param request Parcel that is positioned at the start of the
// data sent by the java layer.
// @param[out] reply Parcel to hold the reply data. Cannot be null.
// @return OK if the call was successful.
virtual status_t invoke(const Parcel& request, Parcel *reply) = 0;
// The Client in the MetadataPlayerService calls this method on
// the native player to retrieve all or a subset of metadata.
//
// @param ids SortedList of metadata ID to be fetch. If empty, all
// the known metadata should be returned.
// @param[inout] records Parcel where the player appends its metadata.
// @return OK if the call was successful.
virtual status_t getMetadata(const media::Metadata::Filter& ids,
Parcel *records) {
return INVALID_OPERATION;
};
void setNotifyCallback(
void* cookie, notify_callback_f notifyFunc) {
Mutex::Autolock autoLock(mNotifyLock);
mCookie = cookie; mNotify = notifyFunc;
}
void sendEvent(int msg, int ext1=0, int ext2=0,
const Parcel *obj=NULL) {
Mutex::Autolock autoLock(mNotifyLock);
if (mNotify) mNotify(mCookie, msg, ext1, ext2, obj);
}
virtual status_t dump(int fd, const Vector<String16> &args) const {
return INVALID_OPERATION;
}