@@ -19,13 +19,6 @@ @interface ImageSnap()
1919@property (nonatomic , strong ) AVCaptureStillImageOutput *captureStillImageOutput;
2020@property (nonatomic , assign ) CVImageBufferRef currentImageBuffer;
2121@property (nonatomic , strong ) AVCaptureConnection *videoConnection;
22- @property (nonatomic , strong ) NSDateFormatter *dateFormatter;
23-
24- #if OS_OBJECT_HAVE_OBJC_SUPPORT == 1
25- @property (nonatomic , strong ) dispatch_queue_t imageQueue;
26- #else
27- @property (nonatomic , assign ) dispatch_queue_t imageQueue;
28- #endif
2922
3023@end
3124
@@ -76,11 +69,30 @@ + (AVCaptureDevice *)deviceNamed:(NSString *)name {
7669 return result;
7770}
7871
72+ + (NSURL *)NSURLfromPath : (NSString *)path andDate : (NSDate *)now {
73+
74+ NSDateFormatter *dateFormatter;
75+ dateFormatter = [NSDateFormatter new ];
76+ dateFormatter.dateFormat = @" yyyy-MM-dd_HH-mm-ss.SSS" ;
77+
78+ NSString *nowstr = [dateFormatter stringFromDate: now];
79+
80+ NSString *pathAndFilename = [NSString stringWithFormat: @" %@%@%@ " , path, nowstr, @" .jpg" ];
81+
82+ return [NSURL fileURLWithPath: pathAndFilename isDirectory: NO ];
83+ }
84+
7985+ (void )saveSingleSnapshotFrom : (AVCaptureDevice *)device
8086 toPath : (NSString *)path
8187 withWarmup : (NSNumber *)warmup
8288 withCallbackBlock : (void (^)(NSURL *imageURL, NSError *error))callbackBlock {
8389
90+ NSOperationQueue *queue = [NSOperationQueue new ];
91+ queue.maxConcurrentOperationCount =1 ;
92+
93+ NSDate *now = [NSDate date ];
94+ NSURL *imageURL = [self NSURLfromPath: path andDate: now];
95+
8496 verbose (" Starting device..." );
8597
8698 NSError *error;
@@ -126,6 +138,30 @@ + (void)saveSingleSnapshotFrom:(AVCaptureDevice *)device
126138
127139 verbose (" Device started.\n " );
128140
141+ void (^stopSession)(void ) = ^void (void ) {
142+ verbose (" Stopping session...\n " );
143+
144+ // Make sure we've stopped
145+ while (captureSession != nil ) {
146+ verbose (" \t CaptureSession != nil\n " );
147+
148+ verbose (" \t Stopping CaptureSession..." );
149+ [captureSession stopRunning ];
150+ verbose (" Done.\n " );
151+
152+ if ([captureSession isRunning ]) {
153+ verbose (" [captureSession isRunning]" );
154+ [[NSRunLoop currentRunLoop ] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1 ]];
155+ } else {
156+ verbose (" \t Shutting down 'stopSession(..)'" );
157+
158+ captureSession = nil ;
159+ captureDeviceInput = nil ;
160+ captureStillImageOutput = nil ;
161+ }
162+ }
163+ };
164+
129165 if (warmup == nil ) {
130166 // Skip warmup
131167 verbose (" Skipping warmup period.\n " );
@@ -136,61 +172,32 @@ + (void)saveSingleSnapshotFrom:(AVCaptureDevice *)device
136172 verbose (" Warmup complete.\n " );
137173 }
138174
139- [captureStillImageOutput captureStillImageAsynchronouslyFromConnection: videoConnection
140- completionHandler:
141- ^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
142-
143- NSDateFormatter *dateFormatter;
144- dateFormatter = [NSDateFormatter new ];
145- dateFormatter.dateFormat = @" yyyy-MM-dd_HH-mm-ss.SSS" ;
146-
147- NSDate *now = [NSDate date ];
148- NSString *nowstr = [dateFormatter stringFromDate: now];
149-
150- NSString *pathAndFilename = [NSString stringWithFormat: @" %@%@%@ " , path, nowstr, @" .jpg" ];
151-
152- NSURL *imageURL = [NSURL fileURLWithPath: pathAndFilename isDirectory: NO ];
153-
154- NSLog (@" Making exif data" );
155- ExifContainer *container = [[ExifContainer alloc ] init ];
156- [container addCreationDate: now];
157- [container addDigitizedDate: now];
158-
159- NSData *rawImageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation: imageDataSampleBuffer];
175+ void (^saveImage)(CMSampleBufferRef imageDataSampleBuffer, NSError *error) = ^void (CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
160176
161- NSData *imageData = [NSImage getAppendedDataForImageData: rawImageData exif: container];
162-
163- dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^(void ) {
164-
165- [imageData writeToURL: imageURL atomically: YES ];
166-
167- verbose (" Stopping session...\n " );
168-
169- // Make sure we've stopped
170- while (captureSession != nil ) {
171- verbose (" \t CaptureSession != nil\n " );
172-
173- verbose (" \t Stopping CaptureSession..." );
174- [captureSession stopRunning ];
175- verbose (" Done.\n " );
177+ // usually happens if you close lid while its grabbing a photos
178+ if (error){
179+ [queue addOperationWithBlock: stopSession];
180+ callbackBlock (NULL , error);
181+ return ;
182+ }
176183
177- if ([captureSession isRunning ]) {
178- verbose (" [captureSession isRunning]" );
179- [[NSRunLoop currentRunLoop ] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1 ]];
180- } else {
181- verbose (" \t Shutting down 'stopSession(..)'" );
184+ verbose (" Making exif data" );
185+ ExifContainer *container = [[ExifContainer alloc ] init ];
186+ [container addCreationDate: now];
187+ [container addDigitizedDate: now];
182188
183- captureSession = nil ;
184- captureDeviceInput = nil ;
185- captureStillImageOutput = nil ;
186- }
187- }
189+ NSData *rawImageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation: imageDataSampleBuffer];
190+ NSData *imageData = [NSImage getAppendedDataForImageData: rawImageData exif: container];
188191
189- });
192+ [queue addOperationWithBlock: ^void (void ) {
193+ [imageData writeToURL: imageURL atomically: YES ];
194+ }];
195+ [queue addOperationWithBlock: stopSession];
196+ callbackBlock (imageURL, error);
197+ };
190198
191- verbose (" Callback...\n " );
192- callbackBlock (imageURL, error);
193- }];
199+ [captureStillImageOutput captureStillImageAsynchronouslyFromConnection: videoConnection
200+ completionHandler: saveImage];
194201}
195202
196203@end
0 commit comments