0

在播放ConcatenatingMediaSource播放列表中的视频时,我希望播放器在新项目开始时自动暂停,例如。不会自动播放。

使用演示应用程序,我修改onPositionDiscontinuity了函数来检测当前项目的变化:

int currentPosition = 0;
@Override
public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
    if (inErrorState) {
        // This will only occur if the user has performed a seek whilst in the error state. Update
        // the resume position so that if the user then retries, playback will resume from the
        // position to which they seeked.
        updateResumePosition();
    }
    if (player.getCurrentWindowIndex() != currentPosition) {
        currentPosition = player.getCurrentWindowIndex();
        player.setPlayWhenReady(false);
    }
}

虽然这段代码暂停了播放器,但它并没有清除播放器使用的表面视图,因此我们仍然看到上一个视频的最后一帧。我想这个回调被调用得太快了,但这是我发现的唯一一个总是在播放列表项更改时调用的回调(onPlayerStateChanged可能不会被调用)。

如何显示新当前项目的第一帧而不是上一个项目的最后一帧?

我的弱解决方法是延迟 200 毫秒的调用Handler().postDelayed({ mPlayer?.playWhenReady = false }, 200)

4

1 回答 1

0

这还不支持

使用事件侦听器的问题在于,无法确保在显示新播放列表项的第一帧时处理暂停事件侦听器的请求。

如果在大约正确的帧处停止就可以了,那么您在位置不连续处暂停播放器的解决方案看起来不错,但我认为无法保证视频渲染器会跟上播放器的位置,这就是为什么您仍然会从暂停播放器时的前一个来源。值得一提的是,在我的测试中,视频渲染器确实在处理暂停请求之前前进到了下一个播放列表项的第一帧。

其他几个建议:

  • 您可以尝试自定义您的 MediaSource 以在每个周期的开头插入位置不连续性。我想你会在每个项目的开头得到 onRenderedFirstFrame 。如果您在那里暂停播放器,您可以保证在新播放列表项中的某一帧处暂停播放器。
  • 为了让它完美地工作,在显示新播放列表项的第一帧并且播放器在显示任何其他帧之前暂停的意义上,有必要协调显示帧并阻止进一步渲染(在播放线程上) 暂停播放器(在您的应用程序用来与付款人交互的线程上)。这将需要一些代码,但我认为可能大致如下:子类 MediaCodecVideoRenderer 并覆盖 onStreamChanged 以获取新播放列表项的时间偏移量。然后覆盖 processOutputBuffer。在这种方法中,您可以检测新流的第一帧何时被渲染(基于时间偏移),然后阻止处理任何输出帧,直到您暂停应用程序线程上的播放器。

我们也可以考虑直接在播放器中支持这一点,但至少目前它可能是一个低优先级。

于 2018-03-26T08:18:40.167 回答