Pre-buffering for AVQueuePlayer
Found a work around!!! After many hours of searching, and failed tests, I found a solution that works on iOS 5 and above.
This will play files without any delay in between. Not as convenient if you want to switch between files, but will certainly put everything together for you. It's still possible to keep track of where each file starts, when adding AVURLAsset, keep the CMTime variable, something like:
NSValue *toJumpTo = [NSValue valueWithCMTime:composition.duration];
[array addObject:toJumpTo];
and then just go through the array, checking the current time value and comparing it using CMTimeCompare.
Edit: Was found on this page visible from the web archive (the link currently points to spam).
Ok, I've looked over this problem again and written some code to check out AVQueuePlayer
.
jollyCocoa's answer pointed me in the right direction by suggesting to observe the status property on AVPlayerItem
. However the documentation doesn't seem to point out that this property (and it's AVPlayerItemStatusReadyToPlay
value in particular) might be related to buffering.
However the AVPlayerItem's
loadedTimeRanges
property seems more related to buffering.
Doing KVO on that array was a bit trickier - the array object itself doesn't change, only it's items do - so I resorted to printing out it's content every second.
What I found out is that a few seconds in the queue's first item, the loadedTimeRanges
for the second item shows up a new CMTimeRange
with start time 0 and some small duration. The duration can increase up to 60 or so seconds while the previous item keeps playing.
Short answer: AVQueuePlayer
will buffer the next AVPlayerItem
while playing the current one.
I've been experimenting with the AVQueuePlayer using movies provided by a server. In this particular test I set up a queuePlayer with AVPlayerItems initialized with URL's to two different video assets of different types. One is an .mp4-file (progressive download), the other one an .m3u8 http-streaming file. It does act a bit funky, I must say.
Depending on the order in which I queue the files I get quite different behavior. If I start with the .mp4-file, the AVPlayerLayer goes blank and silent when the nextItem starts player (the .m3u8-file). If I change the order and start with the m3u8-file, the AVPlayerLayer goes blank but the audio from the second file plays fine.
My impression, from what I've seen so far, is that the AVQueuePlayer does NOT start downloading the next AVPlayerItem before the current AVPlayerItem has finished playing. But I might be wrong.
To be continued I guess...
Edit: Ok, so I've done some more testing and it seems the next items starts downloading before the last item finishes playing. See post below. Stroke the "NOT"...
Edit2: Adding my explanation here instead, since the comment left me with no formatting options. (Best practice for this is welcome, if this is a bad way to handle answer updates)
Anyhow, I iterated through my itemsArray adding observation of the status property using KVO...
[playerItem addObserver: self forKeyPath:@"status" options: 0 context: NULL];
I also set my controller as the observer of the AVPlayerItem Notification AVPlayerItemDidPlayToEndTimeNotification:
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(playerItemDidReachEnd:)
name: AVPlayerItemDidPlayToEndTimeNotification
object: nil];
Now I could log the status change of the AVPlayerItem, and it turns out the next AVPlayerItem in the queue is logged with a status change AVPlayerItemStatusReadyToPlay before the current item ends playing back.
My conclusion is therefor that the next item in line starts downloading prior to the current item ends.
However! I create an array with AVPlayerItems which I use to create my player. Reading the AVFoundation docs on AVAssets, I get the impression that these download their assets asynchronously, but I'm still uncertain when these downloads are being initiated by the IAPlayerItem. I still have some funky behavior when I add the .m3u8-file to the queue, which makes me wonder if these assets begin downloading at the time of creation (seems a bit strange to me though).
As of iOS 5, it appears that AVQueuePlayer no longer pre-buffers. It did pre-buffer the next track in iOS 4.
I'm not sure why there's been a change or if it's even deliberate on Apple's part or simply a bug. In any case, it's a pain and I'll be submitting a bug to them about it.