bashan bashan - 2 months ago 23
Objective-C Question

MPMoviePlayerController strange behaviour with setCurrentPlaybackTime

I use:

MPMoviePlayerController
to show video.

Below I put list of thumbs from the video.
When pressing a thumb I want to jump to a specific place in the video using:
setCurrentPlaybackTime
.

I also have a timer updating the selected thumb according to the location of the video using:
currentPlaybackTime
.

My problem: when calling:
setCurrentPlaybackTime
, the player keeps giving the seconds before seeking to the specific second. It take few seconds to the player to reflect the new seconds. In the mean time the experience of the user is bad: Pressing a thumb shows it selected for a show time, then the timer updates to the previous thumb, then it jumps back to the thumb I selected.

I tried using (in the timer):

if (moviePlayer.playbackState != MPMoviePlaybackStatePlaying && !(moviePlayer.loadState & MPMovieLoadStatePlaythroughOK)) return;


In order to prevent from the timer to update the selected thumb as long the player is in a transition phase between showing the previous thumb and the new thumb, but it doesn't seem to work. The "playbackState" and "loadState" seems to be totally inconstant and unpredictable.

Any ideas?

Answer

For solving this issue, this how I have implemented this nasty state coverage in one of my projects. This is nasty and fragile but worked good enough for me.

I used two flags and two time intervals;

BOOL seekInProgress_; 
BOOL seekRecoveryInProgress_;
NSTimeInterval seekingTowards_;
NSTimeInterval seekingRecoverySince_;

All of the above should be defaulted to NO and 0.0.

When initiating the seek:

//are we supposed to seek?
if (movieController_.currentPlaybackTime != seekToTime)
{   //yes->
    movieController_.currentPlaybackTime = seekToTime;
    seekingTowards_ = seekToTime;
    seekInProgress_ = YES;
}

Within the timer callback:

//are we currently seeking?
if (seekInProgress_)
{   //yes->did the playback-time change since the seeking has been triggered?
    if (seekingTowards_ != movieController_.currentPlaybackTime)
    {   //yes->we are now in seek-recovery state
        seekingRecoverySince_ = movieController_.currentPlaybackTime;
        seekRecoveryInProgress_ = YES;
        seekInProgress_ = NO;
        seekingTowards_ = 0.0;
    }
}
//are we currently recovering from seeking?
else if (seekRecoveryInProgress_)   
{   //yes->did the playback-time change since the seeking-recovery has been triggered?
    if (seekingRecoverySince_ != movieController_.currentPlaybackTime)
    {   //yes->seek recovery done!
        seekRecoveryInProgress_ = NO;
        seekingRecoverySince_ = 0.0;
    }
}

In the end, MPMoviePlayerController simply is not really meant for such "micro-management". I had to throw in at least half a dozen flags for state coverage in all kinds of situations and I would never recommend to repeat this within other projects. Once you reach this level, it might be a great idea to think about using AVPlayer instead.

Comments