MPMoviePlayerController Performance Hit - iphone

I use MPMoviePlayerController because I want to play movie.
One question. When I create MPMoviePlayerController, the app stops a little.
This is my code:
NSString *path = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"m4v"];
NSURL *videoURL = [NSURL fileURLWithPath:path];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
moviePlayer.scalingMode=MPMovieScalingModeFill;
moviePlayer.controlStyle=MPMovieControlStyleNone;
moviePlayer.shouldAutoplay=NO;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieRestartCallback:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:nil];
[moviePlayer.view setFrame:CGRectMake(20, 20, 280, 200)];
[self.view addSubview:moviePlayer.view];
`
Why does the app stop?
Is this problem resolution the way?

If you look at the docs for MPMoviePlayerController you'll see that in the example they call prepareToPlay before even adding the movie player to the view.
I would add [mediaPlayer prepareToPlay] where you're setting up the player.
MPMediaPlayback Protocol Reference says:
"to minimize playback delay, call this method before you call play"

I think that you can use multi-threading functions.
NSOperationQueue is thread safe (you can add operations to it from different threads without the need for locks) and enables you to chain NSOperation objects together.
You can use following code snap to use them.
NSOperationQueue *queue = [NSOperationQueue mainQueue];
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
// your code here
}];
[queue addOperation:operation];
I hope that is helpful to you.

Related

App crashes after checking network with this error message : An AVPlayerItem cannot be associated with more than one instance of AVPlayer

I'm getting this error mentioned in title while playing a video from internet.
- (void)viewDidLoad
{
NSString *urlAdress = [NSString stringWithFormat:#"http://www.dailymotion.com/video/x108t8t"];
//NSString *urlAdress = [[NSBundle mainBundle] pathForResource:#"video8" ofType:#"mp4"];in this case video plays.
NSURL *videoURL = [NSURL fileURLWithPath:urlAdress];
self.mpvc = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlaybackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
self.mpvc.moviePlayer.movieSourceType = MPMovieSourceTypeStreaming;
//when using file in resources use MPMovieSourceTypeFile,when online then streaming
[self presentMoviePlayerViewControllerAnimated:mpvc];
[super viewDidLoad];
}
//and here is moviePlaybackDidFinish method
- (void)moviePlayBackDidFinish:(NSNotification *)notification
{
MPMoviePlayerController *theMovie = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:theMovie];
[theMovie stop];
[theMovie.view removeFromSuperview];
NSLog(#" playback finish Called......");
}
this is whole code. i have went through most of tutorials,stackoverflow questions but could not get a single solution
Your URL is not correctly created for the case you quoted.
You are trying to play a remote stream, hence the URL needs to be a remote one.
Local file URLs are created using fileURLWithPath. Remote URLs are created using URLWithString.
Local File URL
NSURL *videoURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"video8" ofType:#"mp4"]];
Remote URL
NSURL *videoURL = [NSURL URLWithString:#"http://www.dailymotion.com/video/x108t8t"];
well this question seems a lot on stack overflow, i got a solution to this. most of the people facing same issue have right code but only problem is we forget to add dailymotion,vimeo frameworks. since they provide their own framework sdks
you can download them from links below and add them to your projects.
http://www.dailymotion.com/doc/api/sdk-objc.html

how to play another video after finishing one video as video names are selected by user in a uipickerview

My objective is to put video files in a uipicker. I have added my video files names in an array and successfully extracting video file name and extensions but now my target is when user taps on row of picker then that selected video from the array will be passed to mpmovieplayercontroller object then that will play movie please let me know how can I write code to play another selected file after completion of one file i.e.in 1mpmovieplaybackfinished`
My code to play single video file is below.
Just let me know how can i play another video from an array:
-(IBAction)play:(id)sender
{
for (i = 0;i<[arrayofvideo count];i++) {<br /> NSLog(#"%d",i);
NSString *fullFileName = [NSString stringWithFormat:#"%#",[arrayofvideo objectAtIndex:i]];
NSString *filename = [fullFileName stringByDeletingPathExtension];
NSLog(#"%#",filename);
NSString *extension = [fullFileName pathExtension];
NSLog(#"%#",extension);
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"filename"
ofType:#"extension"]];
movieplayer = [[MPMoviePlayerController alloc]initWithContentURL:url];
movieplayer.movieSourceType = MPMovieSourceTypeFile;
movieplayer.controlStyle = MPMovieControlStyleDefault;
movieplayer.view.frame = CGRectMake(0,0,300,400);
[self.view addSubview:movieplayer.view];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:movieplayer];
//---play movie---
[movieplayer play];
}
-(void)movieFinishedCallback:(NSNotification*) aNotification
{
MPMoviePlayerController *player = [aNotification object];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[player stop];
// self.view removeFromSuperView;
[self.view removeFromSuperview];
//call the play button again
// pls tell me what to write here to call play function
}
You need to restructure your code.
The code you posted builds a pathname from your array of video pathnames, and then uses a fixed filename of #"filename". That's not right.
You should write a method "playFileAtIndex" that finds a filename at a specific index and plays that file. I would suggest adding a BOOL parameter playMultipleVideos to the method. If the flag is true, the method would set up a movieFinishedCallback to increment the index and start the next movie playing.
Then make your button IBAction method set an index iVar to the selected row and invoke the playFileAtIndex method.

iPhone: Play videos automatically in a sequence, one after another

i built a very basic video player app in Xcode 4.3.2
i have 3 small videos and on my main menu i have 3 buttons. One button for each video
my code looks like this.....
- (IBAction)playMoviePressed1:(id)sender
{
NSString *path = [[NSBundle mainBundle]
pathForResource:#"HomeVideoOne" ofType:#"m4v"];
player = [[MPMoviePlayerViewController alloc]
initWithContentURL:[NSURL fileURLWithPath:path]];
[self presentMoviePlayerViewControllerAnimated:player];
}
And it repeats for videos 2 and 3. I would like to have a 4th button that played all 3 videos in order without stopping and having to select the next one. It's almost like having to play chapters in a movie one at a time.
Here's the kicker, I don't want to make any extra video files to add to the project size. So in other words the only way i am able to accomplish my goal so far is to edit all 3 videos into one .m4v file and import that to the project. But that is no good because it doubles my project size. I'd like to call on the existing files to play in one right after another with no break. I hope I didn't sound to repetitious.
Thank You
-ANthony
In this case you will need to use some more advanced API like AVQueuePlayer instead of a basic MPMoviePlayerController
Try look through the document here first http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback.html
You can always start another video whenever a video is finished playing. One way is to set your custom methods to be called to control the behavior when you create youMoviePlayerController:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(aMoviePlaybackComplete:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:youMoviePlayerController];
and then:
- (void)aMoviePlaybackComplete:(NSNotification*)notification
{
MPMoviePlayerController *moviePlayerController = [notification object];
if(urlIndex < yourUrlArray.count){
NSUrl* myUrl = [yourUrlArray objectAtIndex:urlIndex];
[moviePlayerController setContentURL:myUrl];
[moviePlayerController play];
urlIndex++;
}
else{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayerController];
[moviePlayerController.view removeFromSuperview];
[moviePlayerController release];
}
}
I'm assuming yourUrlArray is a pre-defined array of the urls of the movies you want to play and urlIndex is keeping count of the current movie being played. Of course, you'll have to tune this to your needs.
EDIT- For local files, you can form the NSUrl using bundle:
NSString *moviePath = [[NSBundle mainBundle] pathForResource:#"Movie" ofType:#"m4v"];
NSUrl* url = [NSURL fileURLWithPath:moviePath];
[yourUrlArray addObject:url];
and initialize the url array(yourUrlArray) and then continue as posted before.

Possible Thread issues when looping MPMoviePlayerController video

I am trying to play a short 6 second video in my view using MPMoviePlayerController and would like it to loop indefinitely. I used the following code to achieve this:
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"MyVideo" ofType:#"m4v"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
moviePlayerController.view.frame = CGRectMake(10, 240, 300, 163);
moviePlayerController.controlStyle = MPMovieControlStyleNone;
moviePlayerController.repeatMode = MPMovieRepeatModeOne;
[self.view addSubview:moviePlayerController.view];
[moviePlayerController play];
The problem is that the video starts playing in a loop as desired, but then eventually stops after a random number of iterations. Note that the file size of the video is very small (less than 500 KB).
After some thought, I speculated that the behavior may be attributed to the fact that I am running the above code inside the main thread. In an effort to run the above code in its own thread, I tried the following:
- (void)viewDidLoad
{
[super viewDidLoad];
[NSThread detachNewThreadSelector:#selector(playVideo) toTarget:self withObject:nil];
}
-(void) playVideo
{
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"MyVideo" ofType:#"m4v"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
moviePlayerController.view.frame = CGRectMake(10, 240, 300, 163);
moviePlayerController.controlStyle = MPMovieControlStyleNone;
moviePlayerController.repeatMode = MPMovieRepeatModeOne;
[self.view addSubview:moviePlayerController.view];
[moviePlayerController play];
}
Now, the problem is that the MPMoviePlayerController's view's frame just appears as a black rectangle where the video should be but no video plays.
I would really appreciate any help into how to get this to work as desired (I don't care if its with or without additional threads). All I need is to have a video play and loop continuously.
Thanks in advance!
I have the same issue. But using the separate thread for this is not a good solution.
1. Working with UIKit (addSubview method) in not main thread could give you unexpected behavior.
2. It looks like that MPMoviePlayerController has its own background thread. So all this stuff working in other thread already.
Probable solution could be in using MPMoviePlayerPlaybackDidFinishNotification and MPMoviePlayerPlaybackStateDidChangeNotification notifications and manual restoring playback.

Is this the right way to use AVAudioPlayer, does my code look right?

Considering the code:
soundFilePath = [[NSBundle mainBundle] pathForResource: #"Sound" ofType: #"wav"];
fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
avPlayerNextLevel = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: nil];
avPlayerNextLevel1.volume = volume ;
[soundFilePath release];
[fileURL release];
To play the sound I then do
if([avPlayerNextLevel prepareToPlay]){
[avPlayerNextLevel play];
}
I do this many times within my game. Sometimes on the simulator , the sound stops playing. And when sometimes I detect memory leaks with AvAudioPlayer.
Does everything look alright with my code ?
You'll need to release the instance of AVAudioPlayer that you created. Since the above code sets the delegate to self, just implement the following method and release there:
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
NSLog(#"Audio finished playing.");
[player release];
}
Why are you releaseing a non-owning reference (soundFilePath)?
You don't need to manually prepareToPlay if you're going to invoke play right after.
Quoting the documentation for play:
Discussion
Calling this method implicitly calls the prepareToPlay method if the audio player is not already prepared to play.
Personally, I do this:
NSURL *soundUrl = [NSURL fileURLWithPath:
[[NSBundle mainBundle] pathForResource:track
ofType:nil]];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl
error:nil];
[audioPlayer setDelegate:self];
[audioPlayer play];
Where audioPlayer is an ivar and track is an lvar of type NSString* which I obtained earlier from wherever I configure the next song to play.
I've been working on something similar but I was using a slightly different piece of code. Unfortunately, I got memory leaks, therefore I decided to give a try to the code you posted. Same result: memory leaks again when I invoke [audioPlayer play];
I can't really figure out what's going on. Are you guys aware of any memory leaks when AVAudioPlayer is involved?