From 432dafb913245e8de6d57206ac96e92606e9ccaf Mon Sep 17 00:00:00 2001 From: Davide Bertola Date: Tue, 17 Oct 2017 07:46:10 +0200 Subject: [PATCH] Reattach videooutput on too many failures I verified that sometimes AVPlayerItemVideoOutput may become stuck due to broken media, strange network behaviours, or when media ends and the user skips back to a valid position. This can result in - no video rendering - crashes (xcode sees the device as disconnected, no stack trace) When this happens the video output needs to be recreated and reattached ref. https://stackoverflow.com/questions/24800742/iosavplayeritemvideooutput-hasnewpixelbufferforitemtime-doesnt-work-correctly --- .../MDVideoDataAdatperAVPlayerImpl.m | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/MDVRLibrary/MDVRLibrary/MDVideoDataAdatperAVPlayerImpl.m b/MDVRLibrary/MDVRLibrary/MDVideoDataAdatperAVPlayerImpl.m index e8e30f9..4f5b79c 100644 --- a/MDVRLibrary/MDVRLibrary/MDVideoDataAdatperAVPlayerImpl.m +++ b/MDVRLibrary/MDVRLibrary/MDVideoDataAdatperAVPlayerImpl.m @@ -11,6 +11,8 @@ @interface MDVideoDataAdatperAVPlayerImpl () @property (nonatomic, strong) AVPlayerItemVideoOutput* output; @property (nonatomic, strong) AVPlayerItem* playerItem; +@property (nonatomic) int failures; +@property (nonatomic) CMTime lastFailure; @end @@ -66,7 +68,7 @@ - (void) setup{ [self.playerItem addOutput:self.output]; } -- (void)teardown{ +- (void)teardown { if (self.playerItem != nil && self.output != nil) { [self.playerItem removeOutput:self.output]; self.output = nil; @@ -74,17 +76,29 @@ - (void)teardown{ } - (CVPixelBufferRef)copyPixelBuffer{ + if (_failures == 10) { + if (self.output != nil) { + [self teardown]; + [self setup]; + _failures = 0; + } + } + if (self.output == nil) { return nil; } CMTime currentTime = [self.playerItem currentTime]; if([self.output hasNewPixelBufferForItemTime:currentTime]){ + _failures = 0; return [self.output copyPixelBufferForItemTime:currentTime itemTimeForDisplay:nil]; } else { + if (_lastFailure.value != currentTime.value) { + _failures += 1; + _lastFailure = currentTime; + } return nil; } - } - (void)dealloc{