AwesomePlayer类的seek操作介绍
1.执行音频seek的地方(mAudioPlayer->seekTo)只有两处,一处是在seekAudioIfNecessary_l函数中,另外一处是在finishSeekIfNecessary函数中。
2.执行seekAudioIfNecessary_l函数的地方有两处,一处是在seekTo_l函数中,另外一处是在play_l函数中。
(1)在seekTo_l函数中,seekAudioIfNecessary_l是无条件执行的。
(2)在play_l函数中,只有当deferredAudioSeek为true时,才执行seekAudioIfNecessary_l函数。
而deferredAudioSeek变量只有在执行创建对象mAudioPlayer时才会被赋值为true,所以只会在开始播放时执行一次,当先播放,暂停然后再播放时不会执行。
3.执行finishSeekIfNecessary函数的地方有三处,都是在onVideoEvent函数中被执行的。
finishSeekIfNecessary函数的参数是视频的时间,所以此函数是与视频有关的。函数定义为:
参数设置为-1,则把音频seek到实际seek的位置,代码如下:
代码如下:
与(1)中第一次调用类似,此时把音频seek到实际seek的位置。
代码如下:
mObserver->postAudioSeekComplete();
1.执行音频seek的地方(mAudioPlayer->seekTo)只有两处,一处是在seekAudioIfNecessary_l函数中,另外一处是在finishSeekIfNecessary函数中。
2.执行seekAudioIfNecessary_l函数的地方有两处,一处是在seekTo_l函数中,另外一处是在play_l函数中。
(1)在seekTo_l函数中,seekAudioIfNecessary_l是无条件执行的。
(2)在play_l函数中,只有当deferredAudioSeek为true时,才执行seekAudioIfNecessary_l函数。
而deferredAudioSeek变量只有在执行创建对象mAudioPlayer时才会被赋值为true,所以只会在开始播放时执行一次,当先播放,暂停然后再播放时不会执行。
3.执行finishSeekIfNecessary函数的地方有三处,都是在onVideoEvent函数中被执行的。
finishSeekIfNecessary函数的参数是视频的时间,所以此函数是与视频有关的。函数定义为:
void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs)
(1)第一处是在mVideoBuffer为NULL,执行mVideoSource的read函数读取视频buffer返回错误时,调用了finishSeekIfNecessary(-1)操作
参数设置为-1,则把音频seek到实际seek的位置,代码如下:
// If we don't have a video time, seek audio to the originally
// requested seek time instead.
if (mRTSPController == NULL)
{
mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
mAudioPlayer->resume();
}
(2)第二处是在从mVideoBuffer中取得video的时间戳,然后把音频seek到vidoe的时间戳的位置,应该是为了保持音视频同步才这样处理。
代码如下:
int64_t timeUs;
CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
{
Mutex::Autolock autoLock(mMiscStateLock);
mVideoTimeUs = timeUs;
}
bool wasSeeking = mSeeking;
finishSeekIfNecessary(timeUs);
(3)第三处是在初始化视频的render失败时调用的。
与(1)中第一次调用类似,此时把音频seek到实际seek的位置。
代码如下:
if (mVideoRendererIsPreview || mVideoRenderer == NULL || mNewSurfaceIsSet) {
mVideoRendererIsPreview = false;
mNewSurfaceIsSet = false;
status_t err = initRenderer_l();
if (err != OK) {
finishSeekIfNecessary(-1);
mFlags |= VIDEO_AT_EOS;
LOGV("video stream ended err1:%d !",err);
postStreamDoneEvent_l(err);
return;
}
}
4. (1)AudioPlayer执行实际的seek操作之前,执行了以下操作,通知MeidaPlayer seek完成。
mObserver->postAudioSeekComplete();
此时读取数据时,就从seek到的时间点开始读取数据,即seek完成了。
其中mObserver是AudioPlayer的类成员变量,类型为AwesomePlayer。
通过调用AwesomePlayer::onCheckAudioStatus()函数,用于通知MediaPlayer音频seek完成,播放完成消息。
(2)当从source中读取数据失败时,调用了AwesomePlayer的postAudioEOS函数,此函数也会通过postEvent,调用AwesomePlayer::onCheckAudioStatus()函数,用于通知MediaPlayer音频seek完成,播放完成消息。
if (err != OK) {
if (mObserver && !mReachedEOS) {
mObserver->postAudioEOS();
}
mReachedEOS = true;
mFinalStatus = err;
break;
}