I already saw a lot of questions regarding issues about Android's MediaPlayer, most of them because of the seekTo()
function. 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.
The problem I'm facing is when I call seekTo()
, it doesn't update the SurfaceView
. It only works in the first time, after that the SurfaceView
just stays the same, it never gets updated again.
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.
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()
;- Pause it on
onSeekComplete()
.