diff --git a/VoidLink/Stream/VideoDecoderRenderer.h b/VoidLink/Stream/VideoDecoderRenderer.h index afc36a47..3bc61d06 100644 --- a/VoidLink/Stream/VideoDecoderRenderer.h +++ b/VoidLink/Stream/VideoDecoderRenderer.h @@ -43,4 +43,6 @@ frameType:(int)frameType decodeStartTime:(CFTimeInterval)decodeStartTime; +- (void)invalidateDecompressionSession; + @end diff --git a/VoidLink/Stream/VideoDecoderRenderer.m b/VoidLink/Stream/VideoDecoderRenderer.m index cc9e24e0..2a71cae6 100644 --- a/VoidLink/Stream/VideoDecoderRenderer.m +++ b/VoidLink/Stream/VideoDecoderRenderer.m @@ -98,12 +98,14 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size, _formatDescImageBuffer = nil; } - if (_decompressionSession != nil){ - VTDecompressionSessionWaitForAsynchronousFrames(_decompressionSession); + @synchronized(self) { + if (_decompressionSession != nil){ + VTDecompressionSessionWaitForAsynchronousFrames(_decompressionSession); - VTDecompressionSessionInvalidate(_decompressionSession); - CFRelease(_decompressionSession); - _decompressionSession = nil; + VTDecompressionSessionInvalidate(_decompressionSession); + CFRelease(_decompressionSession); + _decompressionSession = nil; + } } } @@ -174,6 +176,7 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size, - (void)setupDecompressionSessionWithAttributes:(NSDictionary *)destinationPixelBufferAttributes { + // This method is called from within synchronized block, so no additional sync needed here if (_decompressionSession != NULL) { VTDecompressionSessionInvalidate(_decompressionSession); CFRelease(_decompressionSession); @@ -367,10 +370,12 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit); [_displayLink invalidate]; } - if (_decompressionSession != NULL) { - VTDecompressionSessionInvalidate(_decompressionSession); - CFRelease(_decompressionSession); - _decompressionSession = nil; + @synchronized(self) { + if (_decompressionSession != NULL) { + VTDecompressionSessionInvalidate(_decompressionSession); + CFRelease(_decompressionSession); + _decompressionSession = nil; + } } } @@ -845,28 +850,30 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit); frameNumber:(int)frameNumber frameType:(int)frameType decodeStartTime:(CFTimeInterval)decodeStartTime { - // Check if we need to create/recreate the decompression session - BOOL needsNewSession = (frameType == FRAME_TYPE_IDR || _decompressionSession == nil); + // Synchronize access to decompression session to prevent race conditions during background/foreground transitions + @synchronized(self) { + // Check if we need to create/recreate the decompression session + BOOL needsNewSession = (frameType == FRAME_TYPE_IDR || _decompressionSession == nil); - // Also check if the session might have been invalidated by iOS during background - if (!needsNewSession && _decompressionSession != nil) { - Boolean isValid = VTDecompressionSessionCanAcceptFormatDescription(_decompressionSession, _formatDesc); - if (!isValid) { - Log(LOG_W, @"Decompression session is invalid, needs recreation"); - needsNewSession = YES; + // Also check if the session might have been invalidated by iOS during background + if (!needsNewSession && _decompressionSession != nil) { + Boolean isValid = VTDecompressionSessionCanAcceptFormatDescription(_decompressionSession, _formatDesc); + if (!isValid) { + Log(LOG_W, @"Decompression session is invalid, needs recreation"); + needsNewSession = YES; + } } - } - if (needsNewSession) { - [self setupDecompressionSession]; - } + if (needsNewSession) { + [self setupDecompressionSession]; + } - if (_decompressionSession == nil) { - Log(LOG_E, @"Failed to create decompression session"); - return kVTInvalidSessionErr; - } + if (_decompressionSession == nil) { + Log(LOG_E, @"Failed to create decompression session"); + return kVTInvalidSessionErr; + } - OSStatus status = VTDecompressionSessionDecodeFrameWithOutputHandler( + OSStatus status = VTDecompressionSessionDecodeFrameWithOutputHandler( _decompressionSession, sampleBuffer, 0, @@ -878,10 +885,12 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit); if (status == kVTInvalidSessionErr) { // The session was invalidated by the OS. Destroy our reference // so it gets recreated on the next IDR frame. - if (self->_decompressionSession) { - VTDecompressionSessionInvalidate(self->_decompressionSession); - CFRelease(self->_decompressionSession); - self->_decompressionSession = nil; + @synchronized(self) { + if (self->_decompressionSession) { + VTDecompressionSessionInvalidate(self->_decompressionSession); + CFRelease(self->_decompressionSession); + self->_decompressionSession = nil; + } } } LiRequestIdrFrame(); // Request an IDR to restart the stream @@ -948,7 +957,8 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit); }); }); - return status; + return status; + } } - (void)setHdrMode:(BOOL)enabled {