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] initWithContentURL: 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With