【问题标题】:MediaPlayer seekTo() doesn't update SurfaceViewMediaPlayer seekTo() 不更新 SurfaceView
【发布时间】:2014-05-02 00:13:21
【问题描述】:

我已经看到很多关于 Android 的MediaPlayer 问题的问题,其中大部分是因为seekTo() 功能。现在我尝试使用它,它按预期工作:糟糕!

这个函数似乎很不一致,特别是当我们想在视频暂停时提供它的功能时。就我而言,我有 30 到 60 帧的视频,我想一个一个地播放它们 - 没有 MediaMetadataRetriever.getFrameAtTime() 提供的延迟。

我面临的问题是当我调用seekTo() 时,它不会更新SurfaceView。它只在第一次工作,之后SurfaceView 保持不变,永远不会再次更新。

我听说seekTo() 只能在 1 秒的最小间隔内工作,但我用更长的视频进行了测试,并且逐秒搜索也没有用。

代码

mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceHolder.addCallback(this);

mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDisplay(mSurfaceHolder);

mMediaPlayer.setOnSeekCompleteListener(new OnSeekCompleteListener() {       
    @Override
    public void onSeekComplete(MediaPlayer mp) {
        // Need this postDelayed(), otherwise the media player always 
        // returns 0 in getCurrentPosition(), don't know why...
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            public void run() {
                mMediaPlayer.pause();
            }
        }, 100);
    }
});

mMediaPlayer.setDataSource(localfile_source);
mMediaPlayer.prepare();

// Set the initial position.
mMediaPlayer.start();
mMediaPlayer.seekTo(500);

/** 
We're assuming that targetMs is within 0 and the video's duration.
Also, targetMs is calculated to always move to the next/previous frame:

Example: currentMs + ( 1000 / framerate)
(if framerate = 20, then it will exist a frame in each 50ms) 
*/
private void seekTo(int targetMs) {
    mMediaPlayer.start();
    mMediaPlayer.seekTo(targetMs);
}

请注意,由于在视频暂停时使用此功能存在已知错误,因此使用了一种解决方法:

  • 开始视频;

  • 致电seekTo()

  • onSeekComplete() 上暂停。

【问题讨论】:

  • SurfaceView 似乎有很多错误。如果您的应用仅支持 4.0+,那么您可以尝试使用 TextureView 而不是 SurfaceView
  • 您要使用什么类型的媒体?视频通常不仅仅是一系列图像。有多种帧类型,但并非所有帧类型都提供了开始播放的基础......这意味着如果没有一些不准确或一些处理,您就无法找到它们。
  • 是手机摄像头录制的.mp4视频。问题不在于不准确或处理时间,它只是没有显示任何内容。
  • 请查看我更新的答案。

标签: java android video android-mediaplayer


【解决方案1】:

来自 [this question]:

"您不能使用 MediaPlayer API 的逐帧搜索 由安卓提供。

如果您真的想逐帧搜索,那么您将拥有 使用 FFMPEG 之类的第 3 方多媒体框架,否则您将需要 实现你自己的。”

我创建了一些测试代码来尝试一下。在使用seekTo() 之前我没有start() 视频——我只是在暂停时使用了seekTo()

当我以 50 毫秒 的增量向前移动时,我看到一系列大约 4-5 帧重复,直到大约 2 秒过去;然后,该组预览帧更改为新的 4-5 帧系列。这似乎与我之前的试验一致,其中我以 2000 毫秒 为增量前进,并看到每个 seekTo() 调用的唯一帧。

总而言之,MediaPlayer 似乎会在每 2 秒的时间间隔内挑选几帧作为视频暂停时的预览帧。

【讨论】:

  • 嗯,这就是我的目的。我猜 MediaPlayer 并没有真正为此做好准备,但我想做的其实很简单,不是火箭科学。它应该是一些能够很容易做到的玩家。另外,我测试了 FFMPEG 的getFrameAtTime(),它也不起作用,获取帧需要太多时间(几秒钟),您可以想象,这不是用户友好的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多