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.
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()
;
onSeekComplete()
.From [this question]:
"You cannot do frame by frame seeking by using the MediaPlayer API's provided by Android.
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."
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.
When I moved forward in 50ms increments, I saw a series of about 4-5 frames repeat until roughly 2 seconds had elapsed; then, the set of preview frames changed to a new series of 4-5 frames. 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With