Search code examples
iphoneiosmpmovieplayercontrollermovie

MPMoviePlayerController switching movies causes white flash


I have a small UIView that displays a repeated movie. When the user taps a button another movie is loaded and displayed in the same UIView.

The problem is that there is a half second "flash" between the removing of the first movie and the displaying of the second. Is there any to remove this?

- (void) setUpMovie:(NSString*)title {
NSString *url = [[NSBundle mainBundle] pathForResource:title ofType:@"mp4"];

MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];
[[player view] setFrame:self.movieView.bounds];
[self.movieView addSubview:player.view];
if ([title isEqualToString:@"Bo_idle_02"]) {
    [player setRepeatMode:MPMovieRepeatModeOne];
} else {
    [player setRepeatMode:MPMovieRepeatModeNone];
}
[player setControlStyle:MPMovieControlStyleNone];
[player play];
}

- (void) startDanceAnimation { [self setUpMovie:@"Bo_dance_02"]; return; }

Solution

  • I managed to get my movies changing without the white flash using the AVFoundation as suggested previously. sudo code below, hope it helps someone :)

    Apples reference docs can be found here and I used them to get most of my information: http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40010188-CH1-SW3

    The first thing I did was to add the following class, called PlayerView (can't remember where I got it sorry) to my project. Its a subclass of UIView and its the view that the movie will be displayed in. Once you add it to your project open UI Builder, add a new view to an existing xib and change its class to PlayerView. Connect this using an IBOutlet. Again remember this is the view that will display the movie.

    PlayerView.h

    
    #import 
    #import 
    #import 
    
    @interface PlayerView : UIView {
        AVPlayer *player;
    }
    
    @property (nonatomic,retain) AVPlayer *player;
    
    @end
    

    PlayerView.m

    
    #import "PlayerView.h"
    
    
    @implementation PlayerView
    @synthesize player;
    
    + (Class)layerClass {
        return [AVPlayerLayer class];
    }
    - (AVPlayer*)player {
        return [(AVPlayerLayer *)[self layer] player];
    }
    - (void)setPlayer:(AVPlayer *)player {
        [(AVPlayerLayer *)[self layer] setPlayer:player];
    }
    
    - (void) dealloc {
        [super dealloc];
        [player release];
    }
    
    @end
    

    In the ViewContoller that displays the movies I have the following:

    DisplayMovies.h

    
    #import 
    #import 
    @class PlayerView;
    
    @interface DisplayMovies : UIViewController {
    IBOutlet AVPlayer *player;
    AVPlayerItem *movieOneItem;
    AVPlayerItem *movieTwoItem;
    }
    @property (nonatomic, retain) AVPlayer *player;
    @property (retain) AVPlayerItem *movieOneItem;
    @property (retain) AVPlayerItem *movieTwoItem;
    

    DisplayMovies.m

    
    @implementation DisplayMovies
    @synthesize player, movieOneItem, movieTwoItem;
    
    - (void)viewDidLoad {
    // load the two movies
    NSURL *movieOneItemURL = [[NSBundle mainBundle] URLForResource:@"movieOne" withExtension:@"mp4"];
        AVURLAsset *movieOneItemAsset = [AVURLAsset URLAssetWithURL:movieOneItemURL options:nil];
        self.movieOneItem = [AVPlayerItem playerItemWithAsset:movieOneItemAsset];
    
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(movieOneItemDidReachEnd:)
                                                     name:AVPlayerItemDidPlayToEndTimeNotification
                                                   object:self.movieOneItem];
    
    NSURL *movieTwoItemURL = [[NSBundle mainBundle] URLForResource:@"movieTwo" withExtension:@"mp4"];
        AVURLAsset *movieTwoItemAsset = [AVURLAsset URLAssetWithURL:movieTwoItemURL options:nil];
        self.movieTwoItem = [AVPlayerItem playerItemWithAsset:movieTwoItemAsset];
    
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(movieTwoItemDidReachEnd:)
                                                     name:AVPlayerItemDidPlayToEndTimeNotification
                                                   object:self.movieTwoItem];
        [self.player play];
    }
    
    
    - (void) movieOneItemDidReachEnd:(NSNotification*)notification {
    // play movie two once movie one finishes
        [self.player seekToTime:kCMTimeZero];
        [self.player replaceCurrentItemWithPlayerItem:self.movieTwoItem];
        [self.player play];
    }
    
    - (void) movieTwoItemDidReachEnd:(NSNotification*)notification {
    // play movie one once movie two finishes
        [self.player seekToTime:kCMTimeZero];
        [self.player replaceCurrentItemWithPlayerItem:self.movieOneItem];
        [self.player play];
    }