Skip to content

Commit 9bc3de2

Browse files
committed
Merge pull request BradLarson#1550 from erysaj/fix-memory-access
fix memory access issues when working with CVPixelBuffer-backed framebuffer
2 parents e8aa04e + 7d66360 commit 9bc3de2

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

framework/Source/GPUImageFramebuffer.h

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ typedef struct GPUTextureOptions {
5050
- (void)restoreRenderTarget;
5151

5252
// Raw data bytes
53+
- (void)lockForReading;
54+
- (void)unlockAfterReading;
5355
- (NSUInteger)bytesPerRow;
5456
- (GLubyte *)byteBuffer;
5557

framework/Source/GPUImageFramebuffer.m

+34-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ @interface GPUImageFramebuffer()
77
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
88
CVPixelBufferRef renderTarget;
99
CVOpenGLESTextureRef renderTexture;
10+
NSUInteger readLockCount;
1011
#else
1112
#endif
1213
NSUInteger framebufferReferenceCount;
@@ -330,7 +331,7 @@ - (CGImageRef)newCGImageFromFramebufferContents;
330331

331332
glFinish();
332333
CFRetain(renderTarget); // I need to retain the pixel buffer here and release in the data source callback to prevent its bytes from being prematurely deallocated during a photo write operation
333-
CVPixelBufferLockBaseAddress(renderTarget, 0);
334+
[self lockForReading];
334335
rawImagePixels = (GLubyte *)CVPixelBufferGetBaseAddress(renderTarget);
335336
dataProvider = CGDataProviderCreateWithData((__bridge_retained void*)self, rawImagePixels, paddedBytesForImage, dataProviderUnlockCallback);
336337
[[GPUImageContext sharedFramebufferCache] addFramebufferToActiveImageCaptureList:self]; // In case the framebuffer is swapped out on the filter, need to have a strong reference to it somewhere for it to hang on while the image is in existence
@@ -372,7 +373,7 @@ - (CGImageRef)newCGImageFromFramebufferContents;
372373
- (void)restoreRenderTarget;
373374
{
374375
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
375-
CVPixelBufferUnlockBaseAddress(renderTarget, 0);
376+
[self unlockAfterReading];
376377
CFRelease(renderTarget);
377378
#else
378379
#endif
@@ -381,6 +382,35 @@ - (void)restoreRenderTarget;
381382
#pragma mark -
382383
#pragma mark Raw data bytes
383384

385+
- (void)lockForReading
386+
{
387+
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
388+
if ([GPUImageContext supportsFastTextureUpload])
389+
{
390+
if (readLockCount == 0)
391+
{
392+
CVPixelBufferLockBaseAddress(renderTarget, 0);
393+
}
394+
readLockCount++;
395+
}
396+
#endif
397+
}
398+
399+
- (void)unlockAfterReading
400+
{
401+
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
402+
if ([GPUImageContext supportsFastTextureUpload])
403+
{
404+
NSAssert(readLockCount > 0, @"Unbalanced call to -[GPUImageFramebuffer unlockAfterReading]");
405+
readLockCount--;
406+
if (readLockCount == 0)
407+
{
408+
CVPixelBufferUnlockBaseAddress(renderTarget, 0);
409+
}
410+
}
411+
#endif
412+
}
413+
384414
- (NSUInteger)bytesPerRow;
385415
{
386416
if ([GPUImageContext supportsFastTextureUpload])
@@ -400,9 +430,9 @@ - (NSUInteger)bytesPerRow;
400430
- (GLubyte *)byteBuffer;
401431
{
402432
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
403-
CVPixelBufferLockBaseAddress(renderTarget, 0);
433+
[self lockForReading];
404434
GLubyte * bufferBytes = CVPixelBufferGetBaseAddress(renderTarget);
405-
CVPixelBufferUnlockBaseAddress(renderTarget, 0);
435+
[self unlockAfterReading];
406436
return bufferBytes;
407437
#else
408438
return NULL; // TODO: do more with this on the non-texture-cache side

framework/Source/GPUImageRawDataOutput.m

+3
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ - (void)renderAtInternalSize;
106106
if(lockNextFramebuffer)
107107
{
108108
retainedFramebuffer = outputFramebuffer;
109+
[retainedFramebuffer lock];
110+
[retainedFramebuffer lockForReading];
109111
lockNextFramebuffer = NO;
110112
}
111113

@@ -297,6 +299,7 @@ - (void)lockFramebufferForReading;
297299

298300
- (void)unlockFramebufferAfterReading;
299301
{
302+
[retainedFramebuffer unlockAfterReading];
300303
[retainedFramebuffer unlock];
301304
retainedFramebuffer = nil;
302305
}

0 commit comments

Comments
 (0)