I am building a AVQeueue Player from a set of encoded videos on an s3 bucket, playing videos in sequence using AVPlayerActionAtItemEndAdvance;
- videos are all encoded the same resolution and codec
- They are all tested good to play
- On some devices this solution below works fine
- The issue below is noticed both on IOS 5.x and 6.x
- Been trying to check all done in the main thread. (most likely the issue)
Issue: on the simulator and on some devices (noticed on 4s and 5) after an x amount of videos (x being unpredictable at times but usually 3, 4) a video plays only with sound and kills the queue and does not throw "playerItemDidReachEnd" notification. App does not crash or freeze. No Errors received from "AVPlayerItemStatusFailed" or "AVPlayerItemStatusUnknown"
If anyone has experience with this problem please share.
Code: -(void)addObservers {
dispatch_async(dispatch_get_main_queue(),
^{
for(int i = 0; i < [self.videodata count]; i++) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[self.videodata objectAtIndex:i]];
[[self.videodata objectAtIndex:i] addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
[[self.videodata objectAtIndex:i] addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[[self.videodata objectAtIndex:i] addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
}
});
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *) change context:(void *)context
{
if ([object isKindOfClass:[AVPlayerItem class]])
{
AVPlayerItem *item = (AVPlayerItem *)object;
if ([keyPath isEqualToString:@"status"])
{ //yes->check it...
switch(item.status)
{
case AVPlayerItemStatusFailed:
{
[TestFlight passCheckpoint:@"AV FAILED"];
NSError *error = [item error];
NSLog(@"playback error is %@", error);
break;
}
case AVPlayerItemStatusReadyToPlay:
NSLog(@"player item status is ready to play");
break;
case AVPlayerItemStatusUnknown:
{
[TestFlight passCheckpoint:@"AV STATUS UNKNOWN"];
break;
}
}
}
else if (item == [self.queuePlayer currentItem] && [keyPath isEqualToString:@"playbackBufferEmpty"])
{
if (item.playbackBufferEmpty)
{
[loadingView show:YES];
}
}
else if(item == [self.queuePlayer currentItem] && [keyPath isEqualToString:@"playbackLikelyToKeepUp"])
{
[self.queuePlayer play];
[loadingView hide:YES];
}
}
}
- (void)playerItemDidReachEnd:(NSNotification *)notification {
NSLog(@"ended video %i " , (int)self.currentItem);
AVPlayerItem *p = [notification object];
[p seekToTime:kCMTimeZero];
}