5

我的问题似乎只发生在 android 4.2.2

我走这种方式空闲状态->初始化状态->prepareAsync()->并在onPrepared中调用seekTo,但是在这个android版本上,媒体播放器返回

“尝试查找文件末尾:request = {int>0},durationMs = 0”

并从头开始播放,因为我无法捕捉到这一点,也没有任何听众,它只是将此消息写入日志,我无法对此做出真正的反应。

更奇怪的是,如果我在 onPrepared() 中调用 mediaPlayer.getDuration(),它会返回正确的值而不是 0。

您认为这是一个媒体播放器错误还是有更好的地方可以调用 seekTo ?或者可能是一种如何知道 seekTo 失败的方法?我想避免定期检查当前位置是否小于所需位置并尝试调用 seek to 因为这种方法有很多不同的问题。

这是一个流畅的流媒体视频内容

4

3 回答 3

5

我目前正在尝试找到解决同一问题的方法。到目前为止,我想出的最好的如下。

在 4.2 上,我注意到收到以下回调:

1) onVideoSizeChanged() - 高度和宽度 = 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() 事件,但这并不理想。

如果有人有一个适用于所有操作系统版本的更好的解决方案,我很想听听。

于 2013-04-11T11:09:53.533 回答
2

这是 NuPlayer 实现的问题。NuPlayer 没有适当的准备状态实现,这与使用 AwesomePlayer 的本地播放不同。仅当调用 start() 时才建立网络连接,之后知道持续时间。如果duration为0,可以通过绕过duration检查来解决这个问题,我之前尝试过。

于 2013-06-07T05:53:49.010 回答
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() 让媒体播放器实例强制初始化持续时间字段。否则,请尝试在 seekTo() 之前调用 start(),甚至在 start() 之后的某个时间调用 seekTo()。

于 2013-04-09T09:50:58.430 回答