6

The movie plays just fine but there is a quick black flash right before it plays. Is this a quirk resulting from setting the controlstyle to MPMovieControlStyleNone?

NSString *url = [[NSBundle mainBundle] pathForResource:@"00" ofType:@"mov"];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] 
    initWithContentURL:[NSURL fileURLWithPath:url]];

[[NSNotificationCenter defaultCenter]
    addObserver:self
    selector:@selector(movieFinishedCallback:)
    name:MPMoviePlayerPlaybackDidFinishNotification
    object:player];

//---play video in implicit size---
player.view.frame = CGRectMake(80, 64, 163, 246);
[self.view addSubview:player.view];

// Hide video controls
player.controlStyle =  MPMovieControlStyleNone;

//---play movie---
[player play];
Marsman
  • 825
  • 1
  • 10
  • 20

8 Answers8

19

I just had this problem and fixed it by adding an observer to the default NSNotificationCenter to find out when the movie was completely ready to play, and THEN adding the view as a subview to my main view.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkMovieStatus:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil];

...

if(moviePlayer.loadState & (MPMovieLoadStatePlayable | MPMovieLoadStatePlaythroughOK))
{
    [pageShown.view addSubview:moviePlayer.view];
    [moviePlayer play];
}
Marty
  • 5,926
  • 9
  • 53
  • 91
  • I thought of something similar, thanks for fast-tracking my ideas... all other suggestions above doesnt work for my legacy code, +1 ~!! – dklt Jul 18 '12 at 10:52
  • although, maybe it would work better to call `play` first, and then add the subview? I don't know if there's enough delay after play is called, or if it would help. – Marty Jul 18 '12 at 21:27
  • Does this work? I tried this 2 times now, and it doesn't work for me. – coolcool1994 Aug 14 '15 at 08:23
  • you need to call prepareToPlay to actually get the MPMoviePlayerLoadStateDidChangeNotification (change since iOS6?) – Lorenz03Tx Jul 27 '16 at 20:50
7

In IOS 6 mpmoviewplayer added a new property :readyForDisplay

this is what I'm playing around with and so far so good:

  1. create mpmovieplayer ,add to stage, hide it.
  2. add notification for play state on the movieController
  3. wait for the displayState to Change and once its ready show the video controller:

    - (void)moviePlayerPlayState:(NSNotification *)noti {
    
    if (noti.object == self.movieController) {
    
        MPMoviePlaybackState reason = self.movieController.playbackState;
    
         if (reason==MPMoviePlaybackStatePlaying) {
    
                 [[NSNotificationCenter defaultCenter] removeObserver:self name: MPMoviePlayerPlaybackStateDidChangeNotification object:nil];
    
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    
                while (self.movieController.view.hidden)
                {
                    NSLog(@"not ready");
                    if (self.movieController.readyForDisplay) {
    
                     dispatch_async(dispatch_get_main_queue(), ^(void) {
                         NSLog(@"show");
                         self.movieController.view.hidden=NO;
                     });
    
                    }
                    usleep(50);
                }
            });
         }
    
    }
    

    }

When the play state changes to MPMoviePlaybackStatePlaying we start checking for the readyDisplayState to change.

yeahdixon
  • 6,647
  • 1
  • 41
  • 43
6

Evidently there is a flash of black in the movie rect until enough movie loads so it can start playback. Here is my workaround:

  1. Create a UIImageView and put the MPMoviePlayerController in it. That way you can set the alpha to 0.

  2. As soon as you call [player play]; to play the video, set up a .5 second timer.

  3. When the time is done, change the alpha to 1.

This will make the player invisible for 1/2 second (which hides the black flash).

Marsman
  • 825
  • 1
  • 10
  • 20
  • 1
    I had this problem me too. But this solution is tricky since you don't know the time that MPMovilePlayerController need to render the video. So it will hides certainly the black flash but also the beginning of the video. A better answer: http://stackoverflow.com/a/28079496/2327367 – LastMove Sep 09 '15 at 10:34
3

Create video without addSubview and play instructions:

    NSString *filepath   =   [[NSBundle mainBundle] pathForResource:@"video" ofType:@"mp4"];
    NSURL    *fileURL    =   [NSURL fileURLWithPath:filepath];
    MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
    [moviePlayerController.view setFrame:CGRectMake(80, 64, 163, 246)];
    moviePlayerController.controlStyle = MPMovieControlStyleNone;

Prepare video to play and add notification:

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkMovieStatus:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil];
    [moviePlayerController prepareToPlay];

Create function checkMovieStatus with addSubview and play instructions:

- (void)checkMovieStatus:(NSNotification *)notification {
    if(moviePlayerController.loadState & (MPMovieLoadStatePlayable | MPMovieLoadStatePlaythroughOK)) {
        [self.view addSubview:moviePlayerController.view];
        [moviePlayerController play];
    }
}
Alessandro Pirovano
  • 2,509
  • 28
  • 21
  • you need to call prepareToPlay in order to get the MPMoviePlayerLoadStateDidChangeNotification callback (change since iOS6?) – Lorenz03Tx Jul 27 '16 at 20:51
2

I believe the black flash may be related to the movieSourceType property of MPMoviePlayerController.

If you don't set it, it defaults to MPMovieSourceTypeUnknown which causes the UI to be delayed until the file is loaded.

Try adding this line:

player.movieSourceType = MPMovieSourceTypeFile;

Right after initializing player.

talkol
  • 12,564
  • 11
  • 54
  • 64
2

Or simply change the color of the view, that is what your actually seeing...

player.view.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0];

ddeaco
  • 74
  • 2
  • I used [UIColor clearColor] which does the same thing, and it worked perfectly. I can now see the UIImageView I had in the background and no black flash. – christophercotton Oct 14 '11 at 01:37
1

To avoid the black flash, use a MPMoviePlayerViewController instead of a MPMoviePlayerController. I think that this class creates the background on view display, rather than on video load (like MPMoviePlayerController does).

Before adding the moviePlayerViewController.moviePlayer.view to your display view, you have to add a white subview (or a subview appropriate for your content) to the backgroundView, like this:

[moviePlayerViewController.moviePlayer.view setFrame:[displayView bounds]];

UIView *movieBackgroundView = [[UIView alloc] initWithFrame:[displayView bounds]];
movieBackgroundView.backgroundColor = [UIColor whiteColor];
[moviePlayerViewController.moviePlayer.backgroundView addSubview:movieBackgroundView];
[movieBackgroundView release];
Ricardo Sanchez-Saez
  • 9,466
  • 8
  • 53
  • 92
1

Fond solution here http://joris.kluivers.nl/blog/2010/01/04/mpmovieplayercontroller-handle-with-care/ from iOS 6 you need to use [self.moviePlayer prepareToPlay]; and catch MPMoviePlayerReadyForDisplayDidChangeNotification to use [self.moviePlayer play];

  • This was the solution for me. Using the proper event seems like the right way to approach this problem, I'll write up a tutorial and post it here on how to implement this. – newshorts Aug 05 '15 at 18:58
  • UPDATE - here's a link to a tutorial explaining this in more detail: http://iwearshorts.com/blog/mpmovieplayercontroller-black-screen-when-fading/ – newshorts Aug 05 '15 at 19:14