78 if (
self = [super init])
80 _queue = dispatch_queue_create(
"org.vuo.VuoWindowRecorder", NULL);
83 _priorFrameTime = CMTimeMake(-1,
TIMEBASE);
85 NSView *v = window.contentView;
87 NSRect frameInPoints = v.frame;
88 NSRect frameInPixels = [window convertRectToBacking:frameInPoints];
89 _originalWidth = _priorWidth = frameInPixels.size.width;
90 _originalHeight = _priorHeight = frameInPixels.size.height;
98 self.assetWriter = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeQuickTimeMovie error:&e];
101 NSDictionary *videoSettings = @{
102#pragma clang diagnostic push
103#pragma clang diagnostic ignored "-Wdeprecated-declarations"
105 AVVideoCodecKey: AVVideoCodecH264,
106#pragma clang diagnostic pop
107 AVVideoWidthKey: [NSNumber numberWithInt:_originalWidth],
108 AVVideoHeightKey: [NSNumber numberWithInt:_originalHeight]
112 self.assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
113 _assetWriterInput.expectsMediaDataInRealTime = YES;
117 NSDictionary *pa = @{
118 (NSString *)kCVPixelBufferPixelFormatTypeKey: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA],
119 (NSString *)kCVPixelBufferWidthKey: [NSNumber numberWithInt:_originalWidth],
120 (NSString *)kCVPixelBufferHeightKey: [NSNumber numberWithInt:_originalHeight],
123 self.assetWriterInputPixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor
124 assetWriterInputPixelBufferAdaptorWithAssetWriterInput:_assetWriterInput
125 sourcePixelBufferAttributes:pa];
127 if (![_assetWriter canAddInput:_assetWriterInput])
129 VUserLog(
"Error adding AVAssetWriterInput: %s", [[_assetWriter.error description] UTF8String]);
132 [_assetWriter addInput:_assetWriterInput];
134 if (![_assetWriter startWriting])
136 VUserLog(
"Error starting writing: %s", [[_assetWriter.error description] UTF8String]);
139 [_assetWriter startSessionAtSourceTime:CMTimeMake(0, TIMEBASE)];
177 CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(NULL, [_assetWriterInputPixelBufferAdaptor pixelBufferPool], &pb);
228static void VuoWindowRecorder_doNothingCallback(
VuoImage imageToFree)
241 VUserLog(
"Error: NULL IOSurface. Skipping frame.");
248 if (width == 0 || height == 0)
250 VUserLog(
"Error: Invalid viewport size %dx%d. Skipping frame.", width, height);
256 dispatch_sync(_queue, ^{
262 if (width == _originalWidth && height == _originalHeight)
273 if (width != _originalWidth || height != _originalHeight)
278 VUserLog(
"Error: Failed to resize image.");
285 image = resizedImage;
290 dispatch_async(_queue, ^{
295 [
self appendBuffer:sourceBytes width:_originalWidth height:_originalHeight];
298 _totalAsyncTime += t1 - t0;
302 VUserLog(
"Error: Couldn't download image.");
306 _priorHeight = height;
309 _totalSyncTime += t1 - t0;
323 dispatch_sync(_queue, ^{
324 dispatch_semaphore_t finishedWriting = dispatch_semaphore_create(0);
325 [_assetWriter finishWritingWithCompletionHandler:^{
326 dispatch_semaphore_signal(finishedWriting);
328 dispatch_semaphore_wait(finishedWriting, DISPATCH_TIME_FOREVER);
329 dispatch_release(finishedWriting);
331 if (_assetWriter.status != AVAssetWriterStatusCompleted)
332 VUserLog(
"Error: %s", [[_assetWriter.error localizedDescription] UTF8String]);
334 dispatch_release(_queue);
338 VUserLog(
"Average render-blocking record time per frame: %g", _totalSyncTime / _frameCount);
339 VUserLog(
"Average background record time per frame: %g", _totalAsyncTime / _frameCount);