开发者

Multiple MPMoviePlayerController instances

I'm trying to put two MPMoviePlayerController on a UIView like this

    for (int i = 0; i < 2; i++)
{
    UIView* v = [[UIView alloc] initWithFrame: CGRectMake(0.0f, 300.0f * i, self.view.width, 300.0f)];
    [self.view addSubview: v];

    NSURL* url = [NSURL URLWithString: [urls objectAtIndex: i]];
    MPMoviePlayerController* movieController = [[MPMoviePlayerController alloc] initWithCont开发者_如何学CentURL: url];
    movieController.movieSourceType = MPMovieSourceTypeFile;
    movieController.shouldAutoplay = NO;
    movieController.view.frame = v.bounds;
    [self.view addSubview: movieController.view];
}

But only one view at a time is shown. I know Apple's documentation says

Note: Although you may create multiple MPMoviePlayerController objects and present their views in your interface, only one movie player at a time may play its movie.

but shouldn't the view show all two players at a time? Also only one instance sends MPMoviePlayerLoadStateDidChangeNotification notifications...


You can play multiple videos on the screen by using the AVFoundation framework: AV Foundation Programming Guide

The downside is, that it is not as easy to use as the MPMoviePlayerController, and you shoul create a UIView subclass which contains the AVFoundation classes. This way you can create the necessary controls for it, control the video playback, animate the view (for example animate the transition to fullscreen).

Here it is how I used it:

// Create an AVURLAsset with an NSURL containing the path to the video
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];

// Create an AVPlayerItem using the asset
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];

// Create the AVPlayer using the playeritem
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];

// Create an AVPlayerLayer using the player
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];

// Add it to your view's sublayers
[self.layer addSublayer:playerLayer];

// You can play/pause using the AVPlayer object
[player play];
[player pause];

// You can seek to a specified time
[player seekToTime:kCMTimeZero];

// It is also useful to use the AVPlayerItem's notifications and Key-Value 
// Observing on the AVPlayer's status and the AVPlayerLayer's readForDisplay property
// (to know when the video is ready to be played, if for example you want to cover the 
// black rectangle with an image until the video is ready to be played)
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playerItemDidReachEnd:)
                                             name:AVPlayerItemDidPlayToEndTimeNotification 
                                           object:[player currentItem]];

    [player addObserver:self forKeyPath:@"currentItem.status"
                     options:0
                     context:nil];

    [playerLayer addObserver:self forKeyPath:@"readyForDisplay"
                     options:0
                     context:nil];

You can resize the AVPlayerLayer as you like, even while the video is playing.

If you want to use animations while resizing or repositioning your AVPlayerLayer, you have to alter it's default animations, otherwise you'll see that the player layer's video is not resized in sync with its rect. (Thanks to @djromero for his answer regarding the AVPlayerLayer animation)

Here is a small example for how to alter its default animation. The setup for this example is that the AVPlayerLayer is in a UIView subclass that acts as its container:

// UIView animation to animate the view
[UIView animateWithDuration:0.5 animations:^(){
    // CATransaction to alter the AVPlayerLayer's animation
    [CATransaction begin];
    // Set the CATransaction's duration to the value used for the UIView animation
    [CATransaction setValue:[NSNumber numberWithFloat:0.5] 
                     forKey:kCATransactionAnimationDuration];
    // Set the CATransaction's timing function to linear (which corresponds to the 
    // default animation curve for the UIView: UIViewAnimationCurveLinear)
    [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction 
                             functionWithName:kCAMediaTimingFunctionLinear]];

        self.frame = CGRectMake(50.0, 50.0, 200.0, 100.0);
        playerLayer.frame = CGRectMake(0.0, 0.0, 200.0, 100.0);

    [CATransaction commit];

}];


You won't be able to do this. Internally MPMoviePlayerController seems to use the same view to trade between instances depending on whatever instance is playing. Your only option is to develop your own video player using AVFoundation in order to get multiple instances, or use HTML and UIWebViews. See: http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40010188


Do you require to play both the videos simultaneously?

I guess i have two options:

  1. Add two video thumbnail image buttons on the same screen. According to selection selected video gets played and other gets stopped. So at a time in view only single video will gets played.

  2. Create one separate view controller and add your video into that. Now add that viewcontroller.view in your main view wherever you want.

Let me know if any of these work for you.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜