简体   繁体   English

MediaPlayer seekTo()不更新SurfaceView

[英]MediaPlayer seekTo() doesn't update SurfaceView

I already saw a lot of questions regarding issues about Android's MediaPlayer , most of them because of the seekTo() function. 我已经看到很多关于Android的MediaPlayer问题的问题,其中大部分都是因为seekTo()函数。 Now I tried to use it, and it worked just as expected: badly! 现在我尝试使用它,它的效果与预期的一样:非常糟糕!

This function seems to be very inconsistent, specially when we want to provide its functionality while the video is paused. 此功能似乎非常不一致,特别是当我们想要在视频暂停时提供其功能时。 In my case, I have videos of 30 to 60 frames and I want to play them one by one - without that delay that MediaMetadataRetriever.getFrameAtTime() provides. 在我的情况下,我有30到60帧的视频,我想逐个播放它们 - 没有MediaMetadataRetriever.getFrameAtTime()提供的延迟。

The problem I'm facing is when I call seekTo() , it doesn't update the SurfaceView . 我遇到的问题是当我调用seekTo() ,它不会更新SurfaceView It only works in the first time, after that the SurfaceView just stays the same, it never gets updated again. 它只在第一次工作,之后SurfaceView保持不变,它永远不会再次更新。

I heard a rumor that seekTo() only works with a minimum interval of 1 second, but I tested with a longer video and seeking second by second didn't work either. 我听说有传言说seekTo()只能以1秒的最小间隔工作,但是我用较长的视频进行了测试,并且在第二秒寻找也没有用。

Code

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);
}

Note that because of a known bug regarding using this function while the video is paused, is used a workaround: 请注意,由于在视频暂停时使用此功能的已知错误,使用了一种解决方法:

  • Start the video; 开始播放视频;

  • Call seekTo() ; 调用seekTo() ;

  • Pause it on onSeekComplete() . onSeekComplete()上暂停它。

From [ this question ]: 来自[ 这个问题 ]:

"You cannot do frame by frame seeking by using the MediaPlayer API's provided by Android. “你不能通过使用Android提供的MediaPlayer API逐帧搜索。

If you really want implement frame by frame seeking then you will have to use a 3rd party multimedia framework like FFMPEG or you will need to implement your own." 如果您真的想逐帧实施,那么您将不得不使用像FFMPEG这样的第三方多媒体框架,否则您将需要实现自己的。“

I created some test code to try it out anyway. 无论如何,我创建了一些测试代码来试用它。 I did not start() the video before using seekTo() —I just used seekTo() while paused. 在使用seekTo()之前我没有start()视频 - 我只是在暂停时使用了seekTo()

When I moved forward in 50ms increments, I saw a series of about 4-5 frames repeat until roughly 2 seconds had elapsed; 当我以50ms的增量向前移动时,我看到一系列约4-5帧重复,直到大约2秒钟过去; then, the set of preview frames changed to a new series of 4-5 frames. 然后,预览帧集改变为4-5帧的新系列。 This seems to align with my previous trial wherein I moved forward in increments of 2000ms and saw a unique frame for each seekTo() call. 这似乎与我先前的试验一致,其中我以2000ms的增量向前移动并且为每个seekTo()调用看到了一个唯一的帧。

In summary, it appears that MediaPlayer picks several frames in each 2-second interval to be used as preview frames when the video is paused. 总之,当视频暂停时,MediaPlayer会在每2秒间隔中选择几个帧作为预览帧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM