Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVPlayerItemStatusFailed error when too many AVPlayer instances created

I'm working on an iOS app which creates a feed of all the videos submitted by the pool of users, enabling users to browse and view the videos that others have created. As you can imagine, I need to be able to support an arbitrary number of videos in the feed.

Currently, I am creating and retaining an AVPlayer instance for each video like so:

//inside the init method of a UIView

//create the AVPlayer and store it in a strong property
NSString * urlString = @"aRemoteURL.mov";
NSURL * movURL = [NSURL URLWithString:urlString];
_videoPlayer = [[AVPlayer alloc]initWithURL:movURL];

//register callbacks for handling buffering
[_videoPlayer.currentItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[_videoPlayer.currentItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];

//add the AVPlayerLayer to the view so you can see the video
AVPlayerLayer * playerLayer = [AVPlayerLayer playerLayerWithPlayer:_videoPlayer];
playerLayer.frame = self.frame;
[self.layer addSublayer:playerLayer];

I call play on _videoPlayer when the user taps on the UIView, and everything works perfectly. That is, until enough videos are submitted to the feed...

Once more than 18 videos exist in the feed, the new instances of AVPlayer will not play, and _videoPlayer.currentItem.status will be AVPlayerItemStatusFailed with an ambiguous error Code=-11800 "The operation could not be completed". Interestingly, it is always the 19th video which is the first to break, regardless of the length and quality of the first 18 videos.

I take it I'm not supposed to be creating all these AVPlayer instances. I tried using an AVPlayer singleton wrapper, where I handed a shared AVPlayer instance around to the relevant UIView when a user wanted to play a video. This eliminated the AVPlayerItemStatusFailed error, but made playback unusably laggy.

I haven't been able to find any other accounts of this problem. If anyone can offer some insight into a better approach to this situation, or even so much as point me in the direction of a good AVPlayer tutorial, I will be very grateful. Thanks!

like image 684
bfich Avatar asked Nov 30 '15 23:11

bfich


1 Answers

If anyone comes across this same problem, I ended up creating a work around. Turns out that the number of AVPlayer instances is limited by iPhone hardware, I wish Apple made this more clear. This question touches on that.

In order to get around this limitation, I create and retain an AVURLAsset as well as an AVPlayerItem for each video I wish to play. When it's time to play the video, I create an AVPlayer instance on the fly (not a shared instance), add the AVPlayerItem to it, and play the video. After the video is done playing, I destroy the AVPlayer instance to free up the hardware. This is working well for me and my specialized situation, but some variation of this should help you too if you're experiencing the problem outlined above.

small rant:

I have been working fairly extensively with AVFoundation over the last couple of months, manipulating different types of media in lots of different ways. I frequently find myself cursing Apple's skeletal documentation and examples related to the AVFoundation framework. I wish they would bolster their docs for this as a lot of the framework is convoluted and unintuitive. This tiny rant in a dusty corner of the internet won't change anything but I guess I'm just venting.

end rant

like image 94
bfich Avatar answered Sep 19 '22 21:09

bfich