MPMoviePlayerViewController with embedded video within UITabBarController

5.7k views Asked by At

I am trying to get an embedded video playback properly implemented within a tab-bar navigation. In my specific case, the video shall be displayed in a non-fullscreen manner on a UIView that is hosted by a UIViewController, managed by a UITabBarController.

For simplifying the example, lets say I have two tabs within my tabbar. First one shows some random stuff, second one shows the viewcontroller that hosts the embedded video.

Once the user selects the second tab, the video is loading and playing properly.

For initializing the player, I am using the following code from within my UIView derived class, triggered by the initializer (initWithFrame):

- (void)initPlayback
{
     self.movieViewController = [[MPMoviePlayerViewController alloc] init];
     movieViewController_.wantsFullScreenLayout = NO;
     movieViewController_.moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
     [self addSubview:self.movieViewController.view];
}

For starting the playback, I am using the following code, triggered by the viewWillAppear method of my UIViewController derived class:

- (void)playVideo
{
     [movieViewController_.moviePlayer setContentURL:fileURL_];
}

If then, the user selects the first tab (while the video is still playing), I am making sure that the video is stopped as it would continue playing if that was not done:

- (void)stopVideo
{
     [movieViewController_.moviePlayer stop];
}

Once the user selects the second tab again, the view stays blank, nothing is loaded or played even though the playVideo-method is invoked.

What am I missing, why is the video playback failing when reselecting the second tab?

==========new attempt=============

This time I stopped relying on shouldAutoplay (as suggested) but that did not make a difference.

Adapted and added code for this;

- (void)MPMoviePlayerLoadStateDidChange:(NSNotification *)notification
{
    if (movieViewController_.moviePlayer.loadState == MPMovieLoadStatePlayable &&
        movieViewController_.moviePlayer.playbackState != MPMoviePlaybackStatePlaying)
    {
        [movieViewController_.moviePlayer play];
    }
}

- (void)deregisterFromNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                                                    name:MPMoviePlayerLoadStateDidChangeNotification 
                                                  object:nil];

}


- (void)registerForNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(MPMoviePlayerLoadStateDidChange:) 
                                                 name:MPMoviePlayerLoadStateDidChangeNotification 
                                               object:nil];
}

- (void)initPlayback
{
    NSLog(@"playback init...");
    self.movieViewController = [[MPMoviePlayerViewController alloc] init];
    movieViewController_.wantsFullScreenLayout = NO;
    movieViewController_.moviePlayer.shouldAutoplay = NO;
    movieViewController_.moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
    movieViewController_.moviePlayer.currentPlaybackTime = 0.0f;
    [self addSubview:movieViewController_.view];
}

- (void)playVideo
{
    NSLog(@"playback starting...");
    [self registerForNotifications];
    [movieViewController_.moviePlayer setContentURL:fileURL_];
}

- (void)stopVideo
{
    NSLog(@"playback stopping...");
    [movieViewController_.moviePlayer stop];
    [self deregisterFromNotifications];
}
3

There are 3 answers

0
Till On BEST ANSWER

Adding [movieViewController_.moviePlayer prepareToPlay] to my playVideo method does the trick (when working with remote streams).

4
Mark Adams On

MPMoviePlayerViewController is a subclass of UIViewController. If the second tab is dedicated to displaying video why not just use an instance of it as the root view controller for the second tab?

2
Walter On

In playVideo I think it should be
[movieViewController_.moviePlayer setContentURL:fileURL_]; [movieViewController_.moviePlayer play];

I assume that it works the first time because autoplay defaults to YES