I have code that has worked for many years for writing ProRes files, and it is now failing on the new M1 Max MacBook. Specifically, if I construct buffers with the pixel type "kCVPixelFormatType_64ARGB", after a few frames of writing, the pixel buffer pool becomes nil. This code works just fine on non Max processors (Intel and base M1 natively).
Here's a sample main that demonstrates the problem. Am I doing something wrong here?
// main.m // TestProresWriting // #import <Foundation/Foundation.h> #import <AVFoundation/AVFoundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int timescale = 24; int width = 1920; int height = 1080; NSURL *url = [NSURL URLWithString:@"file:///Users/diftil/TempData/testfile.mov"]; NSLog(@"Output file = %@", [url absoluteURL]); NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error = nil; [fileManager removeItemAtURL:url error:&error]; // Set up the writer AVAssetWriter *trackWriter = [[AVAssetWriter alloc] initWithURL:url fileType:AVFileTypeQuickTimeMovie error:&error]; // Set up the track NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecTypeAppleProRes4444, AVVideoCodecKey, [NSNumber numberWithInt:width], AVVideoWidthKey, [NSNumber numberWithInt:height], AVVideoHeightKey, nil]; AVAssetWriterInput *track = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings]; // Set up the adapter NSDictionary *attributes = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_64ARGB], // This pixel type causes problems on M1 Max, but works on everything else [NSNumber numberWithUnsignedInt:width],[NSNumber numberWithUnsignedInt:height], nil] forKeys: [NSArray arrayWithObjects:(NSString *)kCVPixelBufferPixelFormatTypeKey, (NSString*)kCVPixelBufferWidthKey, (NSString*)kCVPixelBufferHeightKey, nil]]; /* NSDictionary *attributes = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB], // This pixel type works on M1 Max [NSNumber numberWithUnsignedInt:width],[NSNumber numberWithUnsignedInt:height], nil] forKeys: [NSArray arrayWithObjects:(NSString *)kCVPixelBufferPixelFormatTypeKey, (NSString*)kCVPixelBufferWidthKey, (NSString*)kCVPixelBufferHeightKey, nil]]; */ AVAssetWriterInputPixelBufferAdaptor *pixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:track sourcePixelBufferAttributes:attributes]; // Add the track and start writing [trackWriter addInput:track]; [trackWriter startWriting]; CMTime startTime = CMTimeMake(0, timescale); [trackWriter startSessionAtSourceTime:startTime]; while(!track.readyForMoreMediaData); int frameTime = 0; CVPixelBufferRef frameBuffer = NULL; for (int i = 0; i < 100; i++) { NSLog(@"Frame %@", [NSString stringWithFormat:@"%d", i]); CVPixelBufferPoolRef PixelBufferPool = pixelBufferAdaptor.pixelBufferPool; if (PixelBufferPool == nil) { NSLog(@"PixelBufferPool is invalid."); exit(1); } CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(nil, PixelBufferPool, &frameBuffer); if (ret != kCVReturnSuccess) { NSLog(@"Error creating framebuffer from pool"); exit(1); } CVPixelBufferLockBaseAddress(frameBuffer, 0); // This is where we would put image data into the buffer. Nothing right now. CVPixelBufferUnlockBaseAddress(frameBuffer, 0); while(!track.readyForMoreMediaData); CMTime presentationTime = CMTimeMake(frameTime+(i*timescale), timescale); BOOL result = [pixelBufferAdaptor appendPixelBuffer:frameBuffer withPresentationTime:presentationTime]; if (result == NO) { NSLog(@"Error appending to track."); exit(1); } CVPixelBufferRelease(frameBuffer); } // Close everything if ( trackWriter.status == AVAssetWriterStatusWriting) [track markAsFinished]; NSLog(@"Completed."); } return 0; }