From bd0f551759f63921e1e3926475a2e369846ef1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Caetano?= Date: Tue, 25 Nov 2014 15:39:34 -0200 Subject: [PATCH 1/3] Setting maximum input framerate fix #83 --- Examples/Sources/SCRecorderViewController.m | 2 ++ Library/Sources/SCRecordSession.m | 27 +++++++++++++++++++-- Library/Sources/SCRecordSession_Internal.h | 2 ++ Library/Sources/SCVideoConfiguration.h | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Examples/Sources/SCRecorderViewController.m b/Examples/Sources/SCRecorderViewController.m index fd936523..613716b7 100644 --- a/Examples/Sources/SCRecorderViewController.m +++ b/Examples/Sources/SCRecorderViewController.m @@ -69,6 +69,8 @@ - (void)viewDidLoad { _recorder = [SCRecorder recorder]; _recorder.sessionPreset = AVCaptureSessionPreset1280x720; _recorder.maxRecordDuration = CMTimeMake(5, 1); + _recorder.videoConfiguration.maxFrameRate = 10; + _recorder.videoConfiguration.timeScale = 0.333; _recorder.delegate = self; _recorder.autoSetVideoOrientation = YES; diff --git a/Library/Sources/SCRecordSession.m b/Library/Sources/SCRecordSession.m index 2ae6c1af..b7cfede4 100644 --- a/Library/Sources/SCRecordSession.m +++ b/Library/Sources/SCRecordSession.m @@ -93,8 +93,10 @@ - (id)init { _timeOffset = kCMTimeZero; _lastTimeVideo = kCMTimeZero; _lastTimeAudio = kCMTimeZero; + _lastAppendedVideo = kCMTimeZero; _currentSegmentDuration = kCMTimeZero; _segmentsDuration = kCMTimeZero; + _sessionBegan = kCMTimeZero; _date = [NSDate date]; _recordSegmentsDirectory = SCRecordSessionTemporaryDirectory; _identifier = [NSString stringWithFormat:@"%ld", (long)[_date timeIntervalSince1970]]; @@ -612,6 +614,10 @@ - (BOOL)appendAudioSampleBuffer:(CMSampleBufferRef)audioSampleBuffer { if ([_audioInput isReadyForMoreMediaData]) { CMTime actualBufferTime = CMSampleBufferGetPresentationTimeStamp(audioSampleBuffer); + if (CMTIME_IS_INVALID(_sessionBegan)) { + _sessionBegan = actualBufferTime; + } + if (CMTIME_IS_INVALID(_timeOffset)) { _timeOffset = CMTimeSubtract(actualBufferTime, _currentSegmentDuration); } @@ -644,6 +650,23 @@ - (BOOL)appendVideoSampleBuffer:(CMSampleBufferRef)videoSampleBuffer { if ([_videoInput isReadyForMoreMediaData]) { CMTime actualBufferTime = CMSampleBufferGetPresentationTimeStamp(videoSampleBuffer); + if (CMTIME_IS_INVALID(_sessionBegan)) { + _sessionBegan = actualBufferTime; + } + + if (_videoConfiguration.maxFrameRate > 0) { + CMTime interval = CMTimeMake(1, _videoConfiguration.maxFrameRate); + + CMTime offset = CMTimeSubtract(actualBufferTime, _lastAppendedVideo); + if (CMTIME_COMPARE_INLINE(_lastAppendedVideo, ==, kCMTimeZero)) { + offset = CMTimeSubtract(actualBufferTime, _sessionBegan); + } + + if (CMTIME_COMPARE_INLINE(offset, <, interval)) { + return NO; + } + } + if (CMTIME_IS_INVALID(_timeOffset)) { _timeOffset = CMTimeSubtract(actualBufferTime, _currentSegmentDuration); // NSLog(@"Recomputed time offset to: %fs", CMTimeGetSeconds(_timeOffset)); @@ -662,8 +685,7 @@ - (BOOL)appendVideoSampleBuffer:(CMSampleBufferRef)videoSampleBuffer { } } - CMTime bufferTimestamp = CMTimeSubtract(CMSampleBufferGetPresentationTimeStamp(videoSampleBuffer), _timeOffset); - + CMTime bufferTimestamp = CMTimeSubtract(actualBufferTime, _timeOffset); if (_videoPixelBufferAdaptor != nil) { CIImage *image = [CIImage imageWithCVPixelBuffer:CMSampleBufferGetImageBuffer(videoSampleBuffer)]; @@ -693,6 +715,7 @@ - (BOOL)appendVideoSampleBuffer:(CMSampleBufferRef)videoSampleBuffer { CFRelease(adjustedBuffer); } + _lastAppendedVideo = actualBufferTime; _lastTimeVideo = actualBufferTime; _currentSegmentDuration = bufferTimestamp; diff --git a/Library/Sources/SCRecordSession_Internal.h b/Library/Sources/SCRecordSession_Internal.h index d999185a..6025e443 100644 --- a/Library/Sources/SCRecordSession_Internal.h +++ b/Library/Sources/SCRecordSession_Internal.h @@ -23,6 +23,8 @@ CMTime _timeOffset; CMTime _lastTimeVideo; CMTime _lastTimeAudio; + CMTime _lastAppendedVideo; + CMTime _sessionBegan; SCVideoConfiguration *_videoConfiguration; SCAudioConfiguration *_audioConfiguration; diff --git a/Library/Sources/SCVideoConfiguration.h b/Library/Sources/SCVideoConfiguration.h index d05232c8..018b93d3 100644 --- a/Library/Sources/SCVideoConfiguration.h +++ b/Library/Sources/SCVideoConfiguration.h @@ -43,7 +43,7 @@ @property (copy, nonatomic) NSString *scalingMode; /** - The maximum framerate that this SCRecordSession should handle + The maximum input framerate that this SCRecordSession should handle If the camera appends too much frames, they will be dropped. If this property's value is 0, it will use the current video framerate from the camera. From 6707d19000ac1477d479cf9676fcaa58deb97c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Caetano?= Date: Tue, 25 Nov 2014 20:04:26 -0200 Subject: [PATCH 2/3] Improving AVCaptureSession's commitConfiguration time while switching cameras --- Library/Sources/SCRecorder.m | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Library/Sources/SCRecorder.m b/Library/Sources/SCRecorder.m index 3cb10043..9a3e20d7 100644 --- a/Library/Sources/SCRecorder.m +++ b/Library/Sources/SCRecorder.m @@ -155,7 +155,7 @@ - (void)commitSessionConfiguration { if (_captureSession != nil) { _beginSessionConfigurationCount--; if (_beginSessionConfigurationCount == 0) { - [_captureSession commitConfiguration]; + [self.captureSession commitConfiguration]; } } } @@ -683,11 +683,14 @@ - (void)reconfigureVideoInput:(BOOL)shouldConfigureVideo audioInput:(BOOL)should } - (void)switchCaptureDevices { + CFTimeInterval startTime = CACurrentMediaTime(); if (self.device == AVCaptureDevicePositionBack) { self.device = AVCaptureDevicePositionFront; } else { self.device = AVCaptureDevicePositionBack; } + CFTimeInterval elapsedTime = CACurrentMediaTime() - startTime; + NSLog(@"commit time: %fs\tthread: %@", elapsedTime, [NSThread currentThread]); } - (void)previewViewFrameChanged { @@ -955,7 +958,31 @@ - (void)setPhotoOutputSettings:(NSDictionary *)photoOutputSettings { - (void)setDevice:(AVCaptureDevicePosition)device { _device = device; if (_captureSession != nil) { - [self reconfigureVideoInput:self.videoConfiguration.enabled audioInput:NO]; + + [self beginSessionConfiguration]; + NSError *error = nil; + AVCaptureDeviceInput *currentInput = [self currentDeviceInputForMediaType:AVMediaTypeVideo]; + AVCaptureDeviceInput *newInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self videoDevice] error:&error]; + + if (error == nil) { + [_captureSession removeInput:currentInput]; + if ([_captureSession canAddInput:newInput]) { + [_captureSession addInput:newInput]; + } else { + [_captureSession addInput:currentInput]; + error = [SCRecorder createError:@"Failed to add input to capture session"]; + } + } + + dispatch_sync(_recordSessionQueue, ^{ + [self updateVideoOrientation]; + }); + [self commitSessionConfiguration]; + + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(recorder:didReconfigureVideoInput:)]) { + [delegate recorder:self didReconfigureVideoInput:error]; + } } } From 73e96ab8aa5bc63c999942c0354ab19a546d5fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Caetano?= Date: Tue, 25 Nov 2014 20:09:28 -0200 Subject: [PATCH 3/3] Removing timelogging --- Library/Sources/SCRecorder.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/Library/Sources/SCRecorder.m b/Library/Sources/SCRecorder.m index 9a3e20d7..78e474a3 100644 --- a/Library/Sources/SCRecorder.m +++ b/Library/Sources/SCRecorder.m @@ -683,14 +683,11 @@ - (void)reconfigureVideoInput:(BOOL)shouldConfigureVideo audioInput:(BOOL)should } - (void)switchCaptureDevices { - CFTimeInterval startTime = CACurrentMediaTime(); if (self.device == AVCaptureDevicePositionBack) { self.device = AVCaptureDevicePositionFront; } else { self.device = AVCaptureDevicePositionBack; } - CFTimeInterval elapsedTime = CACurrentMediaTime() - startTime; - NSLog(@"commit time: %fs\tthread: %@", elapsedTime, [NSThread currentThread]); } - (void)previewViewFrameChanged {