(ipad 1, iOs 4.3)
I have encountered this bug on ipad: when i add a MPMoviePlayerController to my view and put it on full screen mode all movie player controller don't work (i can see but if i touch it don't work), and i can't exit full screen mode
my code:
//Player video
self.player = [[MPMoviePlayerController alloc]
initWithContentURL:[NSURL fileURLWithPath:self.attachment.path]];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[self.player setFullscreen:NO];
[self.view addSubview:self.player.view];
[self.player play];
Any suggestion?
Related
I'm building a very simple iOS iPad app that consists of a view and 4 buttons.
So basically you have in the Storyboard:
->ViewController
->View (this is added just for alignment and position sake, nothing else)
->View
->Button1
->Button2
->Button3
->Button4
When you press a button a movie will play in fullscreen mode, the same for all 4 buttons.
Once the movie is done, either because it finished or the user pressed "done",
[moviePlayer.view removeFromSuperview] is used to remove the movie, and everything returns to the initial state of the app, with the 4 buttons.
this is the code that plays the movie when a button is pressed
- (void) playMovie:(NSString *)fileName
ofType:(NSString *)fileType
{
NSString *filePath=[[NSBundle mainBundle] pathForResource:fileName ofType:fileType];
NSURL *fileUrl=[NSURL fileURLWithPath:filePath];
self.moviePlayer=[[MPMoviePlayerController alloc] initWithContentURL:fileUrl];
[self.view addSubview:self.moviePlayer.view];
self.moviePlayer.fullscreen = YES;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerWillExitFullscreenNotification
object:self.moviePlayer];
[self.moviePlayer prepareToPlay];
[self.moviePlayer play];
}
And this is the code I use to stop and remove the movie:
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerWillExitFullscreenNotification
object:player];
if ([player respondsToSelector:#selector(setFullscreen:animated:)])
{
[player stop];
[player setFullscreen:NO animated:YES];
[player.view removeFromSuperview];
}
}
The problem I encounter is this, after [player.view removeFromSuperview]; is performed, I return to the initial view, with no background image (it turns black) and no response from any of the buttons.
if I remove the view that contains the buttons, and add the buttons to the main view, it works as expected.
Sorry if this isn't too clear, I've been through books and lots of websites but don't seem to be able to get my head around this.
Cheers!
It looks like you are removing the "player" from the superview, but what you orginally added was a "movieplayer"...try removing that from the superview.
I changed the MPMoviePlayerController for a MPMoviePlayer*View*Controller and referenced the movie player within it, without using the setFullScreen and everything started working as expected.
So basically adding a view to the superview and the MPMoviePlayerController setFullScreen=YES are no good in this case.
I want to play play video on current viewcontroller with full screen.
so i am using MPMoviePlayerViewController to play full screen video but problem is that it does not play smooth.
it lag little bit while playing video.
Here is My code which i am using to play full screen video which is store in my documents directory of phone/ipad
-(void)PlayVideo:(NSString *)videoFilePath
{
NSURL *videoURL = [NSURL fileURLWithPath:videoFilePath];
NSLog(#"videoURL: %#", videoURL);
MPMoviePlayerViewController *playerVC = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];
// Remove the movie player view controller from the "playback did finish" notification observers
[[NSNotificationCenter defaultCenter] removeObserver:playerVC
name:MPMoviePlayerPlaybackDidFinishNotification
object:playerVC.moviePlayer];
// Register this class as an observer instead
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:playerVC.moviePlayer];
// Set the modal transition style of your choice
playerVC.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
// Present the movie player view controller
[self presentViewController:playerVC animated:NO completion:nil];
// Start playback
[playerVC.moviePlayer prepareToPlay];
[playerVC.moviePlayer play];
}
- (void)movieFinishedCallback:(NSNotification*)aNotification
{
// Obtain the reason why the movie playback finished
NSNumber *finishReason = [[aNotification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
// Dismiss the view controller ONLY when the reason is not "playback ended"
if ([finishReason intValue] != MPMovieFinishReasonPlaybackEnded)
{
MPMoviePlayerController *moviePlayer = [aNotification object];
// Remove this class from the observers
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
// Dismiss the view controller
[self dismissViewControllerAnimated:YES completion:Nil];
}
}
Didn't find any issue with the code except in
[[NSNotificationCenter defaultCenter] removeObserver:playerVC
name:MPMoviePlayerPlaybackDidFinishNotification
object:playerVC.moviePlayer];
removeObserver should be self and not playerVC.
But ya, that will not cause any problem like you have mentioned.
I would suggest you try profiling your app, which might direct you to the code causing the issue. Probably there might be something that you are doing in the background when the video is playing which is causing it to lag.
I am facing problem of memory leak and other MoviePlayer new initiation as my MoviePlayer doesn't respond to function, in which I am releasing that player on my done button.
(void) playMovieAtURL
{
MPMoviePlayerViewController *mpViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:videoURL]];
mpViewController.view.backgroundColor = [UIColor blackColor];
[self presentMoviePlayerViewControllerAnimated:mpViewController];
[mpViewController.view setCenter:self.view.center];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myMovieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:mpViewController];
}
// When the movie is done,release the controller. (Doesn't come in it.)
-(void)myMovieFinishedCallback:(NSNotification*)aNotification
{
MPMoviePlayerController* theMovie=[aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:theMovie];
// Release the movie instance created in playMovieAtURL
[theMovie release];
}
Not sure it's your case, but this is what documentation says about MPMoviePlayerPlaybackDidFinishNotification:
This notification is not sent in cases
where the movie player is displaying
in fullscreen mode and the user taps
the Done button. In that instance, the
Done button causes movie playback to
pause while the player transitions out
of fullscreen mode. If you want to
detect this scenario in your code, you
should monitor other notifications
such as
MPMoviePlayerDidExitFullscreenNotification.
It seems that MPMoviePlayerPlaybackDidFinishNotification is called just when the movie stops by itself.
If you are using the Done button, you should use MPMoviePlayerDidExitFullscreenNotification instead.
I tried to solve it by passing nil and now it is returning me callbacks but still the movie won't releases, I will try ur suggestion also. Anyways my new code
-(void) playMovieAtURL
{
MPMoviePlayerViewController *mpViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:videoURL]];
mpViewController.view.backgroundColor = [UIColor blackColor];
[self presentMoviePlayerViewControllerAnimated:mpViewController];
[mpViewController.view setCenter:self.view.center];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myMovieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
}
// When the movie is done,release the controller.
-(void)myMovieFinishedCallback:(NSNotification*)aNotification
{
MPMoviePlayerController* theMovie=[aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
// Release the movie instance created in playMovieAtURL
[theMovie release];
}
I have a button that triggers a mpmovieplayercontroller to play out some streaming audio. When the controller is playing everything works as expected and I see the grey quicktime background.
However, when I stop the player and press the button again, I still hear the audio, but the background is now black. And, if I switch to a video stream before playing the mp3 the quicktime background reappears.
Does any one know how to stop the quicktime background disappearing.
Any help is greatly appreciated.
-(IBAction) playmp3 {
NSString *medialink = #"http://someWebAddress.mp3";
self.player = [[[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:medialink]] autorelease];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerDidFinish:) name:#"MPMoviePlayerPlaybackDidFinishNotification" object:self.player];
[self.player play];
}
- (void)moviePlayerDidFinish:(NSNotification *)obj {
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"MPMoviePlayerPlaybackDidFinishNotification" object:self.player];
self.player = nil;
}
Found the answer basically it has to do with the player not stopping correctly. You need to alter the DidFinish function to the following
- (void)moviePlayerDidFinish:(NSNotification *)obj {
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"MPMoviePlayerPlaybackDidFinishNotification" object:self.player];
self.player.initialPlaybackTime = -1.0;
[self.player stop];
self.player = nil;
}
I have a couple of views that access the movie player. I've put the following code in a method in AppDelegate for these views. They send in the filename to play. The code works fine but I know a release is required somewhere. If I add the last line as a release or autorelease, the app will crash once the user presses done on the movieplayer.
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc]
initWithContentURL:[NSURL fileURLWithPath:moviePath]];
moviePlayer.movieControlMode = MPMovieControlModeDefault;
[moviePlayer play];
//[moviePlayer release];
I get this error:
objc[51051]: FREED(id): message videoViewController sent to freed object=0x1069b30
Program received signal: “EXC_BAD_INSTRUCTION”.
How should I be releasing the player?
What I've found is that the MPMoviePlayerController has to be sent the stop message before you can safely release it. So I do it in handlePlaybackEnd - first I stop it, then I autorelease it. Calling release doesn't seem to work too well:
- (void) moviePlayBackDidFinish : (NSNotification *) notification
{
VideoPlayerController * player = notification.object;
[player stop];
[player autorelease];
}
The whole thing becomes a bit trickier in that the MPMoviePlayerPlaybackDidFinishNotification can get sent more than once, but calling stop/autorlease twice won't do you any good either. So you need to guard against that somehow.
Lastly, it seems to take a few iterations of the main run loop until you can safely create a new MPMoviePlayerController instance. If you do it too quickly, you'll get sound but no video. Great fun, huh?
To answer 4thSpace's comment on the answer above, you can remove the notification observer so you don't receive it multiple times:
- (void)moviePlayBackDidFinish:(NSNotification *)notification {
MPMoviePlayerController *theMovie = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:theMovie];
[theMovie stop];
[theMovie release];
}
for iphone os 3.2
you need to call
[moviePlayer pause];
before calling
[moviePlayer stop];
Stopping and releasing was not enough for me if the player did not reach to its end.
My solution is setting the moviePlayer.initialPlaybackTime = -1
at the moviePlayBackDidFinish: before releasing it:
-(void)playMovie: (NSString *)urlString{
movieURL = [NSURL URLWithString:urlString];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
moviePlayer.initialPlaybackTime = 0;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDidFinish: ) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer] ;
moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
moviePlayer.movieControlMode = MPMovieControlModeDefault;
moviePlayer.backgroundColor = [UIColor blackColor];
[moviePlayer play];
}
-(void)moviePlayBackDidFinish: (NSNotification*)notification{
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer] ;
moviePlayer.initialPlaybackTime = -1;
[moviePlayer stop];
[moviePlayer release];
}
I had the same problem and I just realized I set the notification method with object:nil (it was a copy paste).
I was having multiple notifications although I shouldn't have had any notifications at all.
Here is my new notification set up code that fixed all (see the object:moviePlayer):
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlaybackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
Hope that helps. Now all my code is working properly.
This seemed to reduce the memory significantly. However for IOS 4.1 it seems fine.
- (void)videoFinishedCallback:(NSNotification *)aNotification
{
thePlayer = [aNotification object];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification object:thePlayer];
thePlayer.initialPlaybackTime = -1;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
[thePlayer pause];
#endif
[thePlayer stop];
[thePlayer release];
}