AVQueuePlayer playing items simultaneously rather than in sequence - objective-c

I am trying to put together a simple app to play a pre-roll video followed by some content video.
Currently, I'm trying to use the AVQueuePlayer class to get this done. Unfortunately, it seems to want to play the videos properly in sequence.
For example, the pre-roll plays by itself for a few seconds, then (prior to the pre-roll being complete) it starts to try and play the content video. For a few seconds, the player seems to be at war with itself and switches back and forth between the two videos (neither playing very well at all). Finally, when the pre-roll is finished, the content video then plays the rest of the way normally.
I've looked through the documentation for the AVQueuePlayer and I don't see anything obvious that I'm missing.
My code is pretty basic:
AVPlayerItem *preRollItem = [AVPlayerItem playerItemWithURL: preRollUrl];
AVPlayerItem *contentItem = [AVPlayerItem playerItemWithURL: contentUrl];
self.player = [AVQueuePlayer queuePlayerWithItems:[NSArray arrayWithObjects:preRollItem, contentItem, nil]];
[self.player play];
What is the trick to getting the videos to play in sequence.

Make sure you are actually testing on the device. From my experience the iOS5 simulator has big problems with AVQueuePlayer and does bizarre things.
I found the iOS4.3 simulator is doing a much better job when it comes to testing AVFoundation.

Related

playing a youtube movie from url in objective C

I have a tableview which contains youtube urls.
http://www.youtube.com/v/M67PNWvKdg0&autoplay=1
I am trying to play the video file with the following piece of code. I also imported the media framework.
Video *video = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSURL *urlString=[NSURL URLWithString:video.url];
//NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
//pathForResource:#"Video1" ofType:#"mp4"]];
MPMoviePlayerViewController *playercontroller = [[MPMoviePlayerViewController alloc]
initWithContentURL:urlString];
[self presentMoviePlayerViewControllerAnimated:playercontroller];
playercontroller.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[playercontroller.moviePlayer play];
playercontroller = nil;
What it does for now is it pops up a movie player but then immediately goes back to my tableview. Does anybody knows what the problem is?
Thanks in advance
Are you working on iOS 6? I found difficulty in playing Youtube videos through MPMoviePlayerController, so I found out this to be very useful.
This has MPMoviePlayerController only...
And this would work well for Versions < iOS 6 too.
You can't play youtube videos via Media Player. You have only two solutions: open the link via external app (just open it and iOS will run Safari or YouTube.app if installed) or you can implement your own view with UIWebView and open the link inside WebView.
May be this link would help you, and one more thing is the video plays only on device cant test on a simulator.
There's another way but you have to be a little adventurous.
You can use a third party rtsp framework of which there are a few.
Then you need to link to the m.youtube.com, this is the rtsp version of youtube that Android and other phones will get you to.
If you try to open this link in safari on the iphone the page redirects to the h264 links.
You can open the url in an uitableview and change the user-agent tag. Or simply copy the links you want into a table.
Are all youtube videos automatically converted to h264 now, at one time I remember they were a subset of the rtsp pages.
If you have an Android device you can access this page in a webview quite easily.
here check this link out.
http://streammore-tv.tumblr.com/post/34794206547/welcome

Initiate Download while iOS Device is Locked or App is in Background

I'm playing music using an instance of AVAudioPlayer. Once one song finishes, the next song in the "playlist" is downloaded using NSURLConnection.
Where I'm stuck: I want to be able to download the next audio file in the playlist AND begin playback in the background while the phone is locked, or while the user is using another app. How do I do this?
I have stumbled across this post: Play music in the background using AVAudioplayer which suggests using [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];, but this only seems to allow audio to play in the background, not initiate a download.
Surely this is possible, as Pandora, Spotify, and others can do it...help!
You should request the system to let you run in the background while you are downloading the audiofile. You can do so by using UIApplication's beginBackgroundTaskWithExpirationHandler: method. Once you download the file, you can get the AVAudioPlayer to play your file.
You should have a read of the Apple documentation for multitasking.
http://developer.apple.com/library/ios/#DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW3
You need to add a UIBackgroundModes key to your info.plist for audio. This stops your app from being suspended and then all the normal callbacks will still run.

Sound does only work on Device but not in Simulator

I am playing some short sounds on my iPad like so: Play a short sound in iOS
I am using a caf file which I can successfully play from the Finder. Now I went through quite a bit of a hassle trying to achieve the playback of the sound and I am curious what might be the problems which I don't seem to understand:
Option 1: When I create the SystemSoundID and then play it right away I don't hear anything on the device and the simulator.
Option 2: When I create an instance variable for the SystemSoundID and initialize it in viewDidLoad I manage to play sound but only on the iPad, not the Simulator.
Option 3: Instead of using SystemSoundID I can also use AVAudioPlayer to playback a .wav file which then works on both the iPad and the Simulator but here I need to create the AVAudioPlayer in viewDidLoad otherwise I won't get any sound if I do everything in one go.
The best option currently seems to be Option 3 because it works on both the Simulator and the iPad, but because I need to pre-initialize the Player I would need an AVAudioPlayer instance for every different sound that I want to play, which does not seem to be very memory-wise...
Is there something that I am missing and is it possible to play sounds on both platforms using the AudioToolbox framework (Option 1 & Option 2)
I wrote a library to simplify all this. It wraps AVAudioPlayer, and works fine on both the device and simulator.
https://github.com/nicklockwood/SoundManager
The code is fairly straightforward, although I do some semi-clever stuff to initialise the audio player. If you don't want to use the library you can just copy the code.
A word of warning though - the simulator throws some odd exceptions internally whenever you use AVAudioPlayer. They don't affect the app at all, but if you have enabled break-on-exceptions in Xcode then the app will drop into the debugger a few times during startup and you'll have to manually resume, which may freak you out if you're not expecting it.

How do you know when a user chooses to play a video through AirPlay?

I have a custom video player set up with custom controls, and I utilize MPVolumeView to provide an airplay button. When a user chooses to use AirPlay, they interact with that Apple UI and there is no event (that I can find) that says "hey, the video is now playing over AirPlay".
The problem is that, if I close the player and reopen it, it loads the movie (load state changes to MPMovieLoadStatePlayable), I play it, and I immediately get a playback did finish notification with reason being MPMovieFinishReasonPlaybackEnded, and the video continues to try to play through AirPlay. I'm certain the movie stops and is deallocated whenever I close the player.
If anyone has any advice on how to handle this, knows some events to listen for, or has any ideas about this whatsoever, please let me know. Thanks!
The answer here turns out to be that, at least up to 4.3, there is no way to get an answer to this through code.
The problem in this case is how you dispose of the MPMoviePlayerController when you're finished with it. Even if the video plays through, before you finally release it, you have to call pause and then stop. Like this:
MPMoviePlayerController *mp = [[MPMoviePlayerController alloc] init];
// use the player. then when done with it:
[mp pause];
[mp stop];
[mp release];
If you don't do this then the next time you create a MPMoviePlayerController, certain properties are somehow ghosted in the framework. Playing a video progressively caused audio from the previous mp to play while the new mp did its initial buffering. Also, if the previous video was playing over airplay, the next video would get a notification that the video finished right after it starts and some other weirdness.
Long story short, dispose of your video players with the above sequence to avoid issues with later movie players.

Is it possible to play multiple video files simultaneously on an iPad in either HTML5 or Native App?

In either HTML5 or written natively in Objective-c, I need to generate a grid of video thumbnails that are automatically playing when the page or view loads on an iPad. I have been reading on multiple forums and StackOverflow. Some people indicate this is possible with AVController. Others including Apple state,
"Note: Although you can create multiple MPMoviePlayerController objects and present their views in your interface, only one movie player at a time can play its movie."
Reference: MPMoviePlayerController
In HTML5, it works on a Macbook where all 9 videos are playing:
<video class="movie" src="videos/aerials.m4v" autoplay controls width="200" height="110"></video>
Paste this 9x with the proper links and a nice grid of videos starts playing no problem. On the iPad however, the HTML5 loaded into a webview yields the same 9 grid but with no videos playing immediately. Only 1 video is playable at a time.
Now I took the objective-c path and tried it with a different approach to test out Apple's statement referenced earlier:
moviePlayer1 = [[MPMoviePlayerController alloc]
initWithContentURL:videoURL];
moviePlayer1.view.frame = CGRectMake(0, 0, 200, 110);
[self.view addSubview:moviePlayer1.view];
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer1];
[moviePlayer1 play];
moviePlayer2 = [[MPMoviePlayerController alloc]
initWithContentURL:videoURL];
moviePlayer2.view.frame = CGRectMake(0, 300, 200, 110);
[self.view addSubview:moviePlayer2.view];
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer2];
[moviePlayer2 play];
This indeed does show both video files on a view but again the same issue as with HTML5 and only 1 video playable at a time.
I believe this is because of a hardware limitation with decoding potentially that Apple is enforcing on the iPad to prevent CPU usage from sky rocketing and maintaining yet another strict level of control over the media portion in the framework. Am I right or wrong? If wrong, please help provide the code segment that will enable my task. Thanks!
You actually answered your own question already by the given quote. But just to make it clear to everyone, once again from my answer to a very similar question.
That is not possible. Only one movie/stream can be played at a time when using MPMoviePlayerController / MPMoviePlayerViewController.
From MPMoviePlayerController Class Reference
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.