i am just playing a video by using MPMoviePlayerController...my code is
-(void)playMovie:(NSURL *)url
{
moviePlayer =
[[MPMoviePlayerController alloc]
initWithContentURL:url];
if (IDIOM==IPAD) {
[moviePlayer.view setFrame:CGRectMake(22,100, 720, 300)];
}
else
{
(IS_IPHONE_5)? [moviePlayer.view setFrame:CGRectMake(22, 70, 280, 150)]:[moviePlayer.view setFrame:CGRectMake(22, 40, 260, 140)];
}
[_scrollView addSubview:moviePlayer.view];
moviePlayer.scalingMode =MPMovieScalingModeFill;
[moviePlayer prepareToPlay];
[moviePlayer play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerDidEnterFullscreen:) name:MPMoviePlayerDidEnterFullscreenNotification object:Nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerDidExitFullScreen:) name:MPMoviePlayerDidExitFullscreenNotification object:Nil];
}
-(void)moviePlayerDidEnterFullscreen :(id)sender
{
NSLog(#"fullscreen");
[moviePlayer play];
moviePlayer.scalingMode =MPMovieScalingModeFill;
}
- (void) moviePlayerDidExitFullScreen:(id)sender {
NSLog(#"exit full screen");
[moviePlayer play];
moviePlayer.scalingMode =MPMovieScalingModeFill;
}
here when i play initially video will be in "MPMovieScalingModeFill" mode...but my problem is that if i press full screen it shows video on full screen ..when i press exit "full screen" then my video mode goes to "MPMovieScalingModeAspectFit" mode.but i need to be always in "MPMovieScalingModeFill" mode .whats wrong with my code..Please help me...
I believe this will generate the MPMoviePlayerScalingModeDidChangeNotification.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieScalingModeDidChange:)
name:MPMoviePlayerScalingModeDidChangeNotification
object:nil];
Source :Apple Doc
MPMoviePlayerScalingModeDidChangeNotification
Posted when the scaling mode of a movie player has changed. There is no userInfo dictionary.
Scaling mode can change programmatically or by user interaction. To set or retrieve the scaling mode of a movie player, access its scalingMode property. The movie player whose state has changed is available as the object associated with the notification.
First set the ScalingMode to None and then set the ScalingMode to AspectFill
Swift Code :
NSNotificationCenter.defaultCenter().addObserver(self, selector: "moviePlayerExitFullscreen:", name: MPMoviePlayerDidExitFullscreenNotification, object: self.moviePlayer)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "moviePlayerEnterFullscreen:", name: MPMoviePlayerWillEnterFullscreenNotification, object: self.moviePlayer)
func moviePlayerEnterFullscreen (notification : NSNotification)
{
self.moviePlayer.scalingMode = MPMovieScalingMode.None
self.moviePlayer.scalingMode = MPMovieScalingMode.AspectFill
}
func moviePlayerExitFullscreen (notification : NSNotification)
{
self.moviePlayer.scalingMode = MPMovieScalingMode.None
self.moviePlayer.scalingMode = MPMovieScalingMode.AspectFill
}
This isn't the "ideal" solution, but it works! Basically, once you exit full screen the MPMoviePlayerController instance gets all screwed up and resetting the scaling property to MPMovieScalingModeFill won't help no matter where or when you do it (I've tried all sorts of stuff and after an hour gave up). Easiest solution is to remove the MPMoviePlayerController and simply allocate a new instance of MPMoviePlayerController each time full screen is exited (not ideal, but totally works):
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:NO];
if (self.moviePlayer != nil)
[self.moviePlayer.view removeFromSuperview];
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:self.videoURL];
self.moviePlayer.view.frame = CGRectMake(#, #, #, #);
self.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
self.moviePlayer.shouldAutoplay = NO;
[self.moviePlayer setContentURL:self.videoURL];
[self.moviePlayer prepareToPlay];
[self.moviePlayer setScalingMode:MPMovieScalingModeFill];
[self.view addSubview:self.moviePlayer.view];
}
PS: Don't forget to call super on viewDidAppear or suffer all sorts of unforeseeable mayhem (a very common mistake in iOS development)
Related
I have a problem while playing a video in full screen mode using MPMoviePlayerViewController (works perfectly in normal mode).
CODE:
if (PlayV) {
self.previewView.hidden=NO;
self.videoController =[[MPMoviePlayerController alloc] initWithContentURL:self.videoURL];
[self.videoController.view setFrame:self.previewView .frame];
self.videoController.view.center=self.playBtn.center;
[self.previewView addSubview:self.videoController.view];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(videoPlayBackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:self.videoController];
self.videoController.scalingMode = MPMovieScalingModeAspectFit;
self.videoController.controlStyle = MPMovieControlStyleNone;
[self.videoController play];
}
I got the solution. Add this line of code in playBtnAction method:
- (IBAction)playBtnAction:(id)sender {
[self.videoController setFullscreen:YES animated:YES];
}
and then add this line of code in your videoPlayBackDidFinish.
MPMoviePlayerController *player=[notification object];
if ([player respondsToSelector:#selector(setFullscreen:animated:)]) {
[player.view removeFromSuperview];
}
This code will check if the video is in fullscreen mode and bring it back to normal mode.
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:imagepath]]; //moviePlayer declared in .h and set URL
moviePlayer.view.frame = CGRectMake(364, 89, 660, 668); //set custom frame
moviePlayer.controlStyle = MPMovieControlStyleDefault;
moviePlayer.shouldAutoplay = YES;
[self.view addSubview:moviePlayer.view]; //add to view
[moviePlayer setFullscreen:NO animated:YES];
This may help you.
I am using MPMoviePlayerController for playing video files and I am able to apply the natural size of the video with the help of MPMovieNaturalSizeAvailableNotification. But after adding this notification seek bar is not appearing in the controlStyle (all other buttons are present). If I make the video frame hard coded (i.e. without considering the natural height) I will not get this issue.
Here is my code
// Declartion class level
MPMoviePlayerController *moviePlayer;
float naturalHeight;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
moviewPlayer = [[MPMoviePlayerController alloc] initWithContentURL: movieURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieReadyForDisplay:)
name:MPMoviePlayerReadyForDisplayDidChangeNotification
object:moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieNaturalSizeAvailable:)
name:MPMovieNaturalSizeAvailableNotification
object:moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];
[self.view addSubview:moviePlayer.view];
moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
moviePlayer.fullscreen = NO;
moviePlayer.scalingMode = MPMovieScalingModeFill;
moviePlayer.shouldAutoplay = NO;
//I am able to get the seek bar here if I set the static height . But I want natural height here.
// moviePlayer.frame = CGRectMake(0, 0, self.view.frame.size.width , naturalHeight);
}
-(void) movieNaturalSizeAvailable:(NSNotification *)notification{
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMovieNaturalSizeAvailableNotification object:player];
naturalHeight = player.naturalSize.height;
if(naturalHeight > self.view.frame.size.height) {
naturalHeight = self.view.frame.size.height;
}
}
-(void) movieReadyForDisplay:(NSNotification *)notification{
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerReadyForDisplayDidChangeNotification object:player];
NSLog(#">> %f ", naturalHeight); //OK here
[player view].frame = CGRectMake(0, 0, self.view.frame.size.width , naturalHeight);
player.view.center = self.view.center;
[player prepareToPlay];
[player play];
}
- (void)moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player];
[player stop];
[player.view removeFromSuperview];
}
#end
I believe this issue might be because the natural size calculations of
video player occur after it sets its components frames. If I don't use natural size, it works perfectly. How can I fix this issue?
try this
before starting the video
player.controlStyle = MPMovieControlStyleNone;
and when movie starts playing then set
player.controlStyle = MPMovieControlStyleFullscreen;
You can get play callback from MPMediaPlayback protocol.
I am trying to figure out why I am getting a flash of black screen after I play a video through once. I figured out that when the load state is MPMovieLoadStatePlayable there is no black screen and the video plays through smoothly. However, after the video plays through once the load state becomes MPMovieLoadStateUnknown. I noticed that when the load state is unknown there is a flash of black screen, probably because it has to first call prepareToPlay.
Here is is how I am setting up my video:
- (void)setVideo:(PFObject *)aVideo {
video = aVideo;
if(self.moviePlayer) {
self.moviePlayer = nil;
}
// Get the profile image
PFUser *user = [self.video objectForKey:kFTPostUserKey];
PFFile *profilePictureSmall = [user objectForKey:kFTUserProfilePicSmallKey];
NSString *authorName = [user objectForKey:kFTUserDisplayNameKey];
// Get the video file
PFFile *videoFile = [video objectForKey:kFTPostVideoKey];
NSURL *url = [NSURL URLWithString:videoFile.url];
self.moviePlayer = [[MPMoviePlayerController alloc] init];
[self.moviePlayer.view setFrame:CGRectMake(0.0f,0.0f,320.0f,320.0f)];
[self.moviePlayer setControlStyle:MPMovieControlStyleNone];
[self.moviePlayer setScalingMode:MPMovieScalingModeAspectFill];
[self.moviePlayer setMovieSourceType:MPMovieSourceTypeFile];
[self.moviePlayer setContentURL:url];
[self.moviePlayer requestThumbnailImagesAtTimes:#[ #0.1f, #1.0f ] timeOption:MPMovieTimeOptionExact];
[self.moviePlayer setShouldAutoplay:NO];
[self.moviePlayer.view setBackgroundColor:[UIColor clearColor]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieFinishedCallBack)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerStateChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:self.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(loadStateDidChange:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.moviePlayer];
}
Here are the functions:
- (void)didTapVideoPlayButtonAction:(UIButton *)sender{
[self.playButton setHidden:YES];
[self.moviePlayer prepareToPlay];
[self.moviePlayer requestThumbnailImagesAtTimes:#[ #0.1f, #1.0f ] timeOption:MPMovieTimeOptionExact];
[self.moviePlayer play];
}
-(void)movieFinishedCallBack{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
}
-(void)loadStateDidChange:(NSNotification *)notification{
//NSLog(#"loadStateDidChange: %#",notification);
if (self.moviePlayer.loadState == MPMovieLoadStatePlayable) {
NSLog(#"loadState... MPMovieLoadStatePlayable");
}
if (self.moviePlayer.loadState == MPMovieLoadStatePlaythroughOK) {
NSLog(#"loadState... MPMovieLoadStatePlaythroughOK");
}
if (self.moviePlayer.loadState == MPMovieLoadStateStalled) {
NSLog(#"loadState... MPMovieLoadStateStalled");
}
if (self.moviePlayer.loadState == MPMovieLoadStateUnknown) {
NSLog(#"loadState... MPMovieLoadStateUnknown");
//[self.moviePlayer prepareToPlay];
}
}
-(void)moviePlayerStateChange:(NSNotification *)notification{
//NSLog(#"moviePlayerStateChange: %#",notification);
if (self.moviePlayer.playbackState == MPMoviePlaybackStatePlaying){
[self.imageView addSubview:self.moviePlayer.view];
}
if (self.moviePlayer.playbackState == MPMoviePlaybackStateStopped){
NSLog(#"moviePlayer... Stopped");
[self.playButton setHidden:NO];
//[self.moviePlayer.view removeFromSuperview];
[self.moviePlayer prepareToPlay];
}
if (self.moviePlayer.playbackState == MPMoviePlaybackStatePaused){
NSLog(#"moviePlayer... Paused");
[self.moviePlayer stop];
}
f (self.moviePlayer.playbackState == MPMoviePlaybackStateInterrupted){
NSLog(#"moviePlayer... Interrupted");
[self.moviePlayer stop];
}
if (self.moviePlayer.playbackState == MPMoviePlaybackStateSeekingForward){
NSLog(#"moviePlayer... Forward");
}
if (self.moviePlayer.playbackState == MPMoviePlaybackStateSeekingBackward){
NSLog(#"moviePlayer... Backward");
}
}
I think that the solution would be, calling prepareToPlay from within the statement:
if (self.moviePlayer.loadState == MPMovieLoadStateUnknown)
I tried this but it did not prepare the player for play. Any thoughts/advice/help?
The fact that the video can play once but then can't play again later is not some built-in feature of MPMoviePlayerController — I've never had an MPMoviePlayerController of mine behave like that — so you should look for something else that might be happening so as to wreck the state of your MPMoviePlayerController, such as changing its contentURL to a bad value (which is usually the cause of MPLoadStateUnknown. Two things come to mind:
I notice that the method where you configure your MPMoviePlayerController is no ordinary method; it is, in fact, a setter for a property (video). This could be involved in the problem, because it means that every time any code anywhere says video = //... you are running this method, which means tearing down the entire movie player and making a new one. Now suppose some code somewhere else says video = nil or some other bad value. That would certainly make your movie player view go black and prevent further playing. I suggest breakpointing this method to see if that's happening. And then set up a better architecture: A setter should just set the property and no more. The configuration of your movie player should happen just once and needs to happen in a method of its own.
Watch out for a situation where you accidentally generate more than on MPMoviePlayerController. There is a law that "There Can Be Only One" - if another MPMoviePlayerController comes along and calls prepareToPlay, all other MPMoviePlayerControllers are disabled.
(Finally, although this is not the direct source of your problem, note that you are determining the load state incorrectly. You are using equality, but this can easily fail, because the load state is a bit mask; you have to use logical-and to compare masks.)
I'm playing a video from an MPMoviePlayer (not fullscreen), when I enter fullscreen the video keeps playing and fullscreen is shown.
But when I close fullscreen again, I can only see the black background on the place the 'small' video was playing. It doesnt respond to touches or anything.
I never call stop on my player and there is no viewdiddissapear (or similar) function declared.
The movieplayer also isnt released.
I want the video to continue playing when i close fullscreen. Any thoughts?
**EDIT
It works on an iPad 1, but not on an iPad 2... strange... I need it to function on all though.
Movieplayer initialization:
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
self.moviePlayer = [[MPMoviePlayerController alloc] init];
self.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
self.moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
self.moviePlayer.contentURL = fileURL;
self.moviePlayer.backgroundView.backgroundColor = [UIColor blackColor];
self.moviePlayer.shouldAutoplay = YES;
[self.moviePlayer.view setFrame:CGRectMake(1024, floorf((self.view.bounds.size.height / 2) - (318 / 2)), 425, 318)];
[self.moviePlayer prepareToPlay];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(MPMoviePlayerLoadStateDidChange:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(MPMoviePlayerDidFinish:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:self.moviePlayer];
[self.view addSubview:self.moviePlayer.view];
[self.view bringSubviewToFront:self.moviePlayer.view];
[UIView animateWithDuration:0.25
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:^{
self.moviePlayer.view.transform = CGAffineTransformIdentity;
self.moviePlayer.view.position = CGPointMake(floorf(787 - (self.moviePlayer.view.frame.size.width / 2)),
self.moviePlayer.view.position.y);
}
completion:nil];
Notifications
- (void)MPMoviePlayerLoadStateDidChange:(NSNotification *)notification
{
NSLog(#"Loadstate changed");
if((self.moviePlayer.loadState & MPMovieLoadStatePlaythroughOK) == MPMovieLoadStatePlaythroughOK)
{
[self.moviePlayer play];
}
}
- (void)MPMoviePlayerDidFinish:(NSNotification *)notification
{
MPMovieFinishReason finishReason = (MPMovieFinishReason) [notification.userInfo objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
switch(finishReason)
{
case MPMovieFinishReasonPlaybackError: NSLog(#"Stopped playback due to error");
case MPMovieFinishReasonPlaybackEnded: NSLog(#"I just quitted");
case MPMovieFinishReasonUserExited: NSLog(#"User quitted");
}
}
I am developing an iPad app where I am playing the videos stored within the app itself. I am representing the list of videos in a table view. When I select a row, the video
corresponding to that row plays. But while performing this, sometimes screen goes black , no video is visible but only audio is playing.
I am aware that making the video play in fullscreen mode or using the MPMoviePlayerViewController eliminates this problem. But my requirement is that I don't want to play the movie in fullscreen initially. Please guide me on how this can be achieved.
-(void)playMovie {
MPMoviePlayerController *movieController = [[MPMoviePlayerController alloc] initWithContentURL:movieUrl];
self.moviePalyer = movieController;
[movieController release];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePalyerDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object: self.moviePalyer];
self.moviePalyer.view.frame = CGRectMake(240, 0, 561, 313);
self.moviePalyer.view.backgroundColor = [UIColor clearColor];
[self.moviePalyer prepareToPlay];
[self.view addSubview: self.moviePalyer.view];
[self.moviePalyer play];
}
-(void)moviePalyerDidFinish:(NSNotification*)notification
{
[moviePalyer.view removeFromSuperview];
[moviePalyer stop];
moviePalyer.initialPlaybackTime = -1.0;
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePalyer];
[moviePalyer release];
moviePalyer = nil;
}
NOTE: This is on ipad simulator
I have solved the issue. Previously I was creating the MPMoviePlayerController for each of the row selection, and releasing it in the moviedidfinish notification method .But now, instead of creating movieplayercontroller for every row selection, I am reusing the MPMoviePlayerControler object which has been already created.
Following is the Code snippet:
-(void)playMovie
{
if(self.moviePalyer == nil)
{
MPMoviePlayerController *movieController = [[MPMoviePlayerController alloc] initWithContentURL:url];
self.moviePalyer = movieController;
[movieController release];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePalyerDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:self.moviePalyer];
self.moviePalyer.repeatMode = MPMovieRepeatModeOne;
self.moviePalyer.view.frame = CGRectMake(240, 0, 561, 313);
self.moviePalyer.view.backgroundColor = [UIColor clearColor];
}
else
{
[self.moviePalyer setContentURL:url];
[self stopMovie];
}
[self.view addSubview: self.moviePalyer.view];
[self.moviePalyer play];
}
-(void)stopMovie
{
[self.moviePalyer.view removeFromSuperview];
[self.moviePalyer stop];
self.moviePalyer.initialPlaybackTime = -1.0;
}
I am releasing the moviePlayer object in the dealloc method.
Hope this helps who is having the same issue.