[vlc-commits] videotoolbox: fix thread-safety
Thomas Guillem
git at videolan.org
Wed Jan 18 15:19:03 CET 2017
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Mon Jan 9 14:29:10 2017 +0100| [3477576bc8842302dff5931c8961b6d54fef09c5] | committer: Thomas Guillem
videotoolbox: fix thread-safety
outputTimeStamps and outputFrames need to be locked together.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3477576bc8842302dff5931c8961b6d54fef09c5
---
modules/codec/videotoolbox.m | 87 +++++++++++++++++++++++---------------------
1 file changed, 45 insertions(+), 42 deletions(-)
diff --git a/modules/codec/videotoolbox.m b/modules/codec/videotoolbox.m
index 9f1008c..e4626fb 100644
--- a/modules/codec/videotoolbox.m
+++ b/modules/codec/videotoolbox.m
@@ -119,6 +119,7 @@ struct decoder_sys_t
CFMutableDictionaryRef decoderConfiguration;
CFMutableDictionaryRef destinationPixelBufferAttributes;
+ vlc_mutex_t outLock;
NSMutableArray *outputTimeStamps;
NSMutableDictionary *outputFrames;
bool b_zero_copy;
@@ -740,6 +741,7 @@ static int OpenDecoder(vlc_object_t *p_this)
p_sys->videoFormatDescription = nil;
p_sys->decoderConfiguration = nil;
p_sys->destinationPixelBufferAttributes = nil;
+ vlc_mutex_init(&p_sys->outLock);
int i_ret = StartVideoToolbox(p_dec, NULL);
if (i_ret != VLC_SUCCESS) {
@@ -777,6 +779,7 @@ static void CloseDecoder(vlc_object_t *p_this)
}
StopVideoToolbox(p_dec);
+ vlc_mutex_destroy(&p_sys->outLock);
free(p_sys);
}
@@ -982,12 +985,10 @@ static void Flush(decoder_t *p_dec)
decoder_sys_t *p_sys = p_dec->p_sys;
if (likely(p_sys->b_started)) {
- @synchronized(p_sys->outputTimeStamps) {
- [p_sys->outputTimeStamps removeAllObjects];
- }
- @synchronized(p_sys->outputFrames) {
- [p_sys->outputFrames removeAllObjects];
- }
+ vlc_mutex_lock(&p_sys->outLock);
+ [p_sys->outputTimeStamps removeAllObjects];
+ [p_sys->outputFrames removeAllObjects];
+ vlc_mutex_unlock(&p_sys->outLock);
}
}
@@ -1090,42 +1091,49 @@ skip:
if (unlikely(!p_sys->b_started))
return NULL;
+ vlc_mutex_lock(&p_sys->outLock);
NSUInteger outputFramesCount = [p_sys->outputFrames count];
if (outputFramesCount > 5) {
- CVPixelBufferRef imageBuffer = NULL;
- id imageBufferObject = nil;
- picture_t *p_pic = NULL;
+ CVPixelBufferRef imageBuffer;
+ id imageBufferObject;
+ picture_t *p_pic;
NSString *timeStamp;
- @synchronized(p_sys->outputTimeStamps) {
- [p_sys->outputTimeStamps sortUsingComparator:^(id obj1, id obj2) {
- if ([obj1 longLongValue] > [obj2 longLongValue]) {
- return (NSComparisonResult)NSOrderedDescending;
- }
- if ([obj1 longLongValue] < [obj2 longLongValue]) {
- return (NSComparisonResult)NSOrderedAscending;
- }
- return (NSComparisonResult)NSOrderedSame;
- }];
- NSMutableArray *timeStamps = p_sys->outputTimeStamps;
- timeStamp = [timeStamps firstObject];
- if (timeStamps.count > 0) {
- [timeStamps removeObjectAtIndex:0];
+ [p_sys->outputTimeStamps sortUsingComparator:^(id obj1, id obj2) {
+ if ([obj1 longLongValue] > [obj2 longLongValue]) {
+ return (NSComparisonResult)NSOrderedDescending;
+ }
+ if ([obj1 longLongValue] < [obj2 longLongValue]) {
+ return (NSComparisonResult)NSOrderedAscending;
}
+ return (NSComparisonResult)NSOrderedSame;
+ }];
+ NSMutableArray *timeStamps = p_sys->outputTimeStamps;
+ timeStamp = [timeStamps firstObject];
+ if (timeStamps.count > 0) {
+ [timeStamps removeObjectAtIndex:0];
}
- @synchronized(p_sys->outputFrames) {
- imageBufferObject = [p_sys->outputFrames objectForKey:timeStamp];
+ imageBufferObject = [p_sys->outputFrames objectForKey:timeStamp];
+ if (imageBufferObject == NULL)
+ {
+ vlc_mutex_unlock(&p_sys->outLock);
+ return NULL;
}
- imageBuffer = (__bridge CVPixelBufferRef)imageBufferObject;
- if (imageBuffer == NULL || CVPixelBufferGetDataSize(imageBuffer) == 0)
+ imageBuffer = (CVPixelBufferRef) CFBridgingRetain(imageBufferObject);
+ [p_sys->outputFrames removeObjectForKey:timeStamp];
+ vlc_mutex_unlock(&p_sys->outLock);
+
+ if (CVPixelBufferGetDataSize(imageBuffer) == 0)
+ {
+ CFRelease(imageBuffer);
return NULL;
+ }
if (decoder_UpdateVideoFormat(p_dec))
return NULL;
p_pic = decoder_NewPicture(p_dec);
-
if (!p_pic)
return NULL;
@@ -1135,6 +1143,7 @@ skip:
imageBuffer,
CVPixelBufferGetWidthOfPlane(imageBuffer, 0),
CVPixelBufferGetHeightOfPlane(imageBuffer, 0));
+ CFRelease(imageBuffer);
} else {
/* the structure is allocated by the vout's pool */
if (p_pic->p_sys) {
@@ -1146,20 +1155,15 @@ skip:
p_pic->p_sys->pixelBuffer = nil;
}
- p_pic->p_sys->pixelBuffer = CFBridgingRetain(imageBufferObject);
+ p_pic->p_sys->pixelBuffer = imageBuffer;
}
/* will be freed by the vout */
}
-
p_pic->date = timeStamp.longLongValue;
-
- if (imageBufferObject) {
- @synchronized(p_sys->outputFrames) {
- [p_sys->outputFrames removeObjectForKey:timeStamp];
- }
- }
return p_pic;
}
+ else
+ vlc_mutex_unlock(&p_sys->outLock);
return NULL;
}
@@ -1270,10 +1274,9 @@ static void DecoderCallback(void *decompressionOutputRefCon,
NSNumber *timeStamp = [NSNumber numberWithLongLong:pts.value];
id imageBufferObject = (__bridge id)imageBuffer;
- @synchronized(p_sys->outputTimeStamps) {
- [p_sys->outputTimeStamps addObject:timeStamp];
- }
- @synchronized(p_sys->outputFrames) {
- [p_sys->outputFrames setObject:imageBufferObject forKey:timeStamp];
- }
+
+ vlc_mutex_lock(&p_sys->outLock);
+ [p_sys->outputTimeStamps addObject:timeStamp];
+ [p_sys->outputFrames setObject:imageBufferObject forKey:timeStamp];
+ vlc_mutex_unlock(&p_sys->outLock);
}
More information about the vlc-commits
mailing list