我的问题似乎只发生在android 4.2.2
上我这样闲置状态 - >初始化状态 - > prepareAsync() - >在onPrepared中调用seekTo,但在这个Android版本上,媒体播放器返回
“尝试寻找过去的文件结尾:request = {int> 0},durationMs = 0”
并从头开始播放,因为我无法捕捉到这一点,也没有任何监听器,它只是将此消息写入日志,我无法真正做出反应。
更奇怪的是,如果我在onPrepared()中调用mediaPlayer.getDuration(),它将返回正确的值而不是0。
您认为这是一个媒体播放器错误还是有更好的地方可以调用seekTo?或者也许是一种如何知道seekTo失败的方法?如果它小于所需位置,我想避免定期检查当前位置,并尝试调用搜索,因为这种方法有很多不同的问题。
这是一个流畅的流媒体视频内容
答案 0 :(得分:5)
我目前正在尝试找到同一问题的解决方案。到目前为止我提出的最好的是如下。
在4.2上我注意到收到了以下回叫:
1)onVideoSizeChanged() - 其中height和width = 0
2)onPrepared()
3)onVideoSizeChanged() - 正确的高度和宽度
你不能在(1)中调用seekTo,因为玩家尚未准备好。
正如您所指出的,如果您在(2)中调用seekTo,则媒体播放器会生成警告“尝试寻找过去的文件末尾”
如果已调用MediaPlayer.start(),您只会收到(3),但此时您可以成功调用seekTo()。
MediaPlayer mMediaPlayer = new MediaPlayer(); // + some initialisation code
boolean mVideoSizeIsSet = false;
boolean mMediaPlayerIsPrepared = false;
public void onPrepared(MediaPlayer mediaplayer) {
Log.d(TAG, "onPrepared called");
mMediaPlayerIsPrepared = true;
if (mVideoSizeIsSet) {
mMediaPlayer.seekTo();
}
mMediaPlayer.start()
}
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.d(TAG, "onVideoSizeChanged called");
if (width == 0 || height == 0) {
Log.d(TAG, "invalid video width(" + width + ") or height(" + height + ")");
} else {
mVideoSizeIsSet = true;
if (mMediaPlayerIsPrepared) {
mMediaPlayer.seekTo();
}
}
}
(我个人不喜欢使用布尔警卫,但是如果你看一下sdk提供的媒体播放器样本,它会做类似的事情。)
在一系列设备/操作系统版本中进行测试,这提供了一种通用解决方案。但是,4.2中存在一个错误。对mMediaPlayer.start()的调用似乎会导致视频的前几帧在seekTo()发生之前开始播放,这对我的情况几乎不可见,但对您来说可能更明显。我目前正在寻找以某种方式隐藏我的表面视图,直到我收到onSeekComplete()事件,但这并不理想。
如果有人有更好的解决方案适用于所有操作系统版本,我很乐意听到它。
答案 1 :(得分:2)
这是NuPlayer实施的问题。与使用AwesomePlayer进行本地回放不同,NuPlayer没有正确的准备状态实现。仅在调用start()时建立网络连接,之后知道持续时间。如果持续时间为0,我可以通过绕过持续时间检查来解决问题,我之前已经尝试过了。
答案 2 :(得分:0)
以下是源代码:
418 status_t MediaPlayer::seekTo_l(int msec)
419 {
420 ALOGV("seekTo %d", msec);
421 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
422 if ( msec < 0 ) {
423 ALOGW("Attempt to seek to invalid position: %d", msec);
424 msec = 0;
425 } else if ((mDuration > 0) && (msec > mDuration)) {
426 ALOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
427 msec = mDuration;
428 }
429 // cache duration
430 mCurrentPosition = msec;
431 if (mSeekPosition < 0) {
432 getDuration_l(NULL);
433 mSeekPosition = msec;
434 return mPlayer->seekTo(msec);
435 }
436 else {
437 ALOGV("Seek in progress - queue up seekTo[%d]", msec);
438 return NO_ERROR;
439 }
440 }
441 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
442 return INVALID_OPERATION;
443 }
我建议你先调用getDuration()让mediaplayer实例强制初始化duration字段。 否则,请尝试在seekTo()之前调用start(),或者甚至在start()之后调用seekTo()。