#macos #video-processing #apple-m1 #apple-silicon
Вопрос:
У меня есть код, который много лет работал для написания файлов ProRes, и теперь он выходит из строя на новом MacBook M1 Max. В частности, если я создам буферы с типом пикселя « kCVPixelFormatType_64ARGB
«, после нескольких кадров записи операция добавления завершится ошибкой -12905
. Это указывает на то, что система записи не смогла выполнить преобразование для этого типа буфера, что является очень странным и неожиданным поведением. Опять же, этот код отлично работает на процессорах, отличных от Max (изначально Intel и base M1). Вот пример основного, который демонстрирует проблему. Я что-то здесь делаю не так?
//
// 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 fileURLWithPath:@"/Users/diftil/TempData/testfile.mov"];
NSLog(@"Output file = %@", [url absoluteURL]);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
[fileManager removeItemAtURL:url error:amp;error];
// Set up the writer
AVAssetWriter *trackWriter =
[[AVAssetWriter alloc] initWithURL:url
fileType:AVFileTypeQuickTimeMovie
error:amp;error];
// Set up the track
NSDictionary *videoSettings =
@{AVVideoCodecKey: AVVideoCodecTypeAppleProRes4444,
AVVideoWidthKey: @(width),
AVVideoHeightKey: @(height)};
AVAssetWriterInput *track =
[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings];
// Set up the adapter
// This pixel type causes problems on M1 Max
NSDictionary *attributes =
@{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_64ARGB),
(id)kCVPixelBufferWidthKey: @(width),
(id)kCVPixelBufferHeightKey: @(height)};
// This pixel type works on M1 Max
// NSDictionary *attributes =
// @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32ARGB),
// (id)kCVPixelBufferWidthKey: @(width),
// (id)kCVPixelBufferHeightKey: @(height)};
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);
CVPixelBufferRef frameBuffer = NULL;
for (int i = 0; i < 100; i )
{
NSLog(@"Frame %d", i);
CVPixelBufferPoolRef PixelBufferPool = pixelBufferAdaptor.pixelBufferPool;
if (PixelBufferPool == nil)
{
NSLog(@"PixelBufferPool is invalid.");
exit(1);
}
CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(nil, PixelBufferPool,
amp;frameBuffer);
if (ret != kCVReturnSuccess)
{
NSLog(@"Error creating framebuffer from pool");
exit(1);
}
CVPixelBufferLockBaseAddress(frameBuffer, 0);
void *imagebuf = CVPixelBufferGetBaseAddress(frameBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(frameBuffer);
memset(imagebuf, 0x00, bytesPerRow * height);
CVPixelBufferUnlockBaseAddress(frameBuffer, 0);
while(!track.readyForMoreMediaData);
CMTime presentationTime = CMTimeMake(i, timescale);
BOOL result = [pixelBufferAdaptor appendPixelBuffer:frameBuffer
withPresentationTime:presentationTime];
if (result == NO)
{
NSLog(@"Error appending to track.");
NSError *error = trackWriter.error;
if(error!=nil) {
NSLog(@"Unresolved error %@,%@.", error, [error userInfo]);
}
exit(1);
}
CVPixelBufferRelease(frameBuffer);
}
// Close everything
if ( trackWriter.status == AVAssetWriterStatusWriting)
[track markAsFinished];
__block BOOL isOpen = YES;
[trackWriter finishWritingWithCompletionHandler:^{
isOpen = NO;
NSLog(@"Closed.");
}];
while (isOpen);
NSLog(@"Completed.");
}
return 0;
}
Выполнение этого кода приведет к:
2021-11-13 14:11:37.032427-0700 TestProresWriting[56235:2066349] Output file = file:///Users/diftil/TempData/testfile.mov
2021-11-13 14:11:37.054946-0700 TestProresWriting[56235:2066349] Metal API Validation Enabled
2021-11-13 14:11:37.155398-0700 TestProresWriting[56235:2066349] Frame 0
2021-11-13 14:11:37.158434-0700 TestProresWriting[56235:2066349] Frame 1
2021-11-13 14:11:37.158607-0700 TestProresWriting[56235:2066349] Frame 2
2021-11-13 14:11:37.158715-0700 TestProresWriting[56235:2066349] Frame 3
2021-11-13 14:11:37.159803-0700 TestProresWriting[56235:2066349] Frame 4
2021-11-13 14:11:37.172890-0700 TestProresWriting[56235:2066349] Frame 5
2021-11-13 14:11:37.176622-0700 TestProresWriting[56235:2066349] Error appending to track.
2021-11-13 14:11:37.176723-0700 TestProresWriting[56235:2066349] Unresolved error Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12905), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x10602c1e0 {Error Domain=NSOSStatusErrorDomain Code=-12905 "(null)"}},{
NSLocalizedDescription = "The operation could not be completed";
NSLocalizedFailureReason = "An unknown error occurred (-12905)";
NSUnderlyingError = "Error Domain=NSOSStatusErrorDomain Code=-12905 "(null)"";
}.
Program ended with exit code: 1
Если я переключусь kCVPixelFormatType_64ARGB
на kCVPixelFormatType_32ARGB
, он отлично работает на моем MacBook Pro с M1 Max. Опять же, исходный код отлично работает на любом другом компьютере.