Hi, I'm running into issue in iOS 16 I keep getting EXC_BAD_ACCESS crash in creating CVPixelBuffer or CMVideoFormatDescription. It works perfectly on iOS 15 without any issue. The weirder thing is that the crash no longer happen when I enabled Zombie Object. I couldn't tell what's the issue, the code is pretty standard, please help, thanks.
Here's the code sample:
- (CVPixelBufferPoolRef)createPixelBufferPoolWithFormat:(OSType)format
width:(int)width
height:(int)height
{
CVPixelBufferPoolRef bufferPool;
NSDictionary *poolOpts = @{(id)kCVPixelBufferPoolMinimumBufferCountKey: @4};
NSDictionary *opts = @{(id)kCVPixelBufferWidthKey: @(width),
(id)kCVPixelBufferHeightKey: @(height),
(id)kCVPixelBufferIOSurfacePropertiesKey: @{},
(id)kCVPixelBufferPixelFormatTypeKey: @(format)};
CVReturn ret = CVPixelBufferPoolCreate(NULL,
(__bridge CFDictionaryRef _Nullable)(poolOpts),
(__bridge CFDictionaryRef _Nullable)(opts),
&bufferPool);
return bufferPool;
}
- (CVPixelBufferRef)createPixelBufferWithPool:(CVPixelBufferPoolRef)bufferPool
width:(int)width
height:(int)height
{
CVImageBufferRef imageBuffer;
CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(NULL, bufferPool, &imageBuffer); //=>> Crash here
CVPixelBufferPoolFlush(bufferPool, 0);
// Clean aperture setting doesn't get handled by buffer pool?
// Set it on each buffer as we get it.
NSDictionary *aperture = @{
(id)kCVImageBufferCleanApertureWidthKey: @(width), // pictureWidth * width / frameWidth
(id)kCVImageBufferCleanApertureHeightKey: @(height), // pictureHeight * height / frameHeight
(id)kCVImageBufferCleanApertureHorizontalOffsetKey: @(0), // ((frameWidth - pictureWidth) / 2 - pictureOffsetX) * width / frameWidth
(id)kCVImageBufferCleanApertureVerticalOffsetKey: @(0) // ((frameHeight - pictureHeight) / 2 - pictureOffsetY) * height / frameHeight
};
CVBufferSetAttachment(imageBuffer,
kCVImageBufferCleanApertureKey,
(__bridge CFDictionaryRef)aperture,
kCVAttachmentMode_ShouldPropagate);
return imageBuffer;
}
- (CMSampleBufferRef)makeSampleBufferFromTexturesWithY:(void *)yPtr U:(void *)uPtr V:(void *)vPtr yStride:(int)yStride uStride:(int)uStride vStride:(int)vStride width:(int)width height:(int)height doMirror:(BOOL)doMirror doMirrorVertical:(BOOL)doMirrorVertical
{
CVReturn result;
CVPixelBufferPoolRef bufferPool = [self createPixelBufferPoolWithFormat:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange width:width height:height];
CVPixelBufferRef pixelBuffer = [self createPixelBufferWithPool:bufferPool width:width height:height];
CVPixelBufferPoolRelease(bufferPool);
[self updatePixelBuffer420:pixelBuffer withY:yPtr U:uPtr V:vPtr yStride:yStride uStride:uStride vStride:vStride width:width height:height doMirror:doMirror doMirrorVertical:doMirrorVertical];
if (doMirrorVertical || doMirror) {
pixelBuffer = [self mirroredPixelBufferFromPixelBuffer:pixelBuffer width:width height:height doMirror:doMirror doMirrorVertical:doMirrorVertical];
}
CMFormatDescriptionRef formatDesc;
result = CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, &formatDesc); //=>> Crash here
if (result != kCVReturnSuccess) {
NSAssert(NO, @"PIP: Failed to create CMFormatDescription: %d", result);
CVPixelBufferRelease(pixelBuffer);
CFRelease(formatDesc);
return nil;
}
CMTime now = CMTimeMakeWithSeconds(CACurrentMediaTime(), 1000);
CMSampleTimingInfo timingInfo;
timingInfo.duration = CMTimeMakeWithSeconds(1, 1000);
timingInfo.presentationTimeStamp = now;
timingInfo.decodeTimeStamp = now;
CMSampleBufferRef sampleBuffer;
OSStatus ret = CMSampleBufferCreateForImageBuffer(NULL, pixelBuffer, YES, NULL, NULL, formatDesc, &timingInfo, &sampleBuffer);
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
// OSStatus ret = CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault, pixelBuffer, formatDesc, &timingInfo, &sampleBuffer);
if (ret != 0) {
NSAssert(NO, @"PIP: Failed to create CMSampleBufferRef %d", (int)ret);
CVPixelBufferRelease(pixelBuffer);
CFRelease(formatDesc);
return nil;
}
CVPixelBufferRelease(pixelBuffer);
CFRelease(formatDesc);
return sampleBuffer;
}