fixed ios camera timing (patch by Eduard Feicho)
authorVadim Pisarevsky <vadim.pisarevsky@itseez.com>
Wed, 22 Aug 2012 09:33:13 +0000 (13:33 +0400)
committerVadim Pisarevsky <vadim.pisarevsky@itseez.com>
Wed, 22 Aug 2012 09:33:13 +0000 (13:33 +0400)
modules/highgui/include/opencv2/highgui/cap_ios.h
modules/highgui/src/cap_ios_video_camera.mm

index cc6668a..26a28c0 100644 (file)
@@ -80,7 +80,6 @@
 
 @property (nonatomic, retain) UIView* parentView;
 
-- (void)pause;
 - (void)start;
 - (void)stop;
 - (void)switchCameras;
     AVAssetWriterInput* recordAssetWriterInput;
     AVAssetWriterInputPixelBufferAdaptor* recordPixelBufferAdaptor;
     AVAssetWriter* recordAssetWriter;
+
+       CMTime lastSampleTime;
     
 }
 
 - (void)adjustLayoutToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
 - (void)layoutPreviewLayer;
 - (void)saveVideo;
+- (NSURL *)videoFileURL;
+
 
 @end
 
index 6f7bfa2..0a162eb 100644 (file)
@@ -98,90 +98,29 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
 {
     [super start];
     
-       if (self.recordVideo == YES) {
-//             [self.videoFileOutput startRecordingToOutputFileURL:[self tempFileURL] recordingDelegate:self];
-               
+       if (self.recordVideo == YES) {          
         NSError* error;
-        if ([[NSFileManager defaultManager] fileExistsAtPath:[self tempFileString]]) [[NSFileManager defaultManager] removeItemAtPath:[self tempFileString] error:&error];
+        if ([[NSFileManager defaultManager] fileExistsAtPath:[self videoFileString]]) {
+                       [[NSFileManager defaultManager] removeItemAtPath:[self videoFileString] error:&error];
+               }
         if (error == nil) {
-            NSLog(@"[Camera] Delete file %@", [self tempFileString]);
-        }
-
-        
-               BOOL started = [self.recordAssetWriter startWriting];
-               [self.recordAssetWriter startSessionAtSourceTime:kCMTimeZero];
-        
-        NSLog(@"[Camera] Session started? %d", started);
-        
-        if (self.recordAssetWriter.status == AVAssetWriterStatusUnknown) {
-            NSLog(@"AVAssetWriter status: unknown");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusWriting) {
-            NSLog(@"AVAssetWriter status: writing");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusCompleted) {
-            NSLog(@"AVAssetWriter status: completed");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusFailed) {
-            NSLog(@"AVAssetWriter status: failed");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusCancelled) {
-            NSLog(@"AVAssetWriter status: cancelled");
-        }
-        
-        if (self.recordAssetWriter.status != AVAssetWriterStatusWriting) {
-            NSLog(@"[Camera] Recording Error: asset writer status is not writing: %@", self.recordAssetWriter.error);
-        } else {
-            NSLog(@"[Camera] Recording started");
+            NSLog(@"[Camera] Delete file %@", [self videoFileString]);
         }
        }
 }
 
 
 
-- (void)pause;
-{
-       [super pause];
-       if (self.recordVideo == YES) {
-//             [self.videoFileOutput stopRecording];
-               
-
-        if (self.recordAssetWriter.status == AVAssetWriterStatusUnknown) {
-            NSLog(@"AVAssetWriter status: unknown");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusWriting) {
-            NSLog(@"AVAssetWriter status: writing");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusCompleted) {
-            NSLog(@"AVAssetWriter status: completed");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusFailed) {
-            NSLog(@"AVAssetWriter status: failed");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusCancelled) {
-            NSLog(@"AVAssetWriter status: cancelled");
-        }
-        
-        if (self.recordAssetWriter.status == AVAssetWriterStatusWriting) {
-            [self.recordAssetWriter finishWriting];
-            NSLog(@"[Camera] recording stopped");
-        } else {
-            NSLog(@"[Camera] Recording Error: asset writer status is not writing");
-        }
-       }
-}
-
-
 - (void)stop;
 {
        [super stop];
     
-    if (self.recordVideo == YES) {
-        NSLog(@"recording stop");
-        if (self.recordAssetWriter.status == AVAssetWriterStatusUnknown) {
-            NSLog(@"AVAssetWriter status: unknown");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusWriting) {
-            NSLog(@"AVAssetWriter status: writing");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusCompleted) {
-            NSLog(@"AVAssetWriter status: completed");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusFailed) {
-            NSLog(@"AVAssetWriter status: failed");
-        } else if (self.recordAssetWriter.status == AVAssetWriterStatusCancelled) {
-            NSLog(@"AVAssetWriter status: cancelled");
-        }
-               
+       self.videoDataOutput = nil;
+       if (videoDataOutputQueue) {
+               dispatch_release(videoDataOutputQueue);
+       }
+       
+       if (self.recordVideo == YES) {
         
         if (self.recordAssetWriter.status == AVAssetWriterStatusWriting) {
             [self.recordAssetWriter finishWriting];
@@ -194,11 +133,6 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
         self.recordAssetWriterInput = nil;
         self.recordPixelBufferAdaptor = nil;
        }
-    
-       self.videoDataOutput = nil;
-       if (videoDataOutputQueue) {
-               dispatch_release(videoDataOutputQueue);
-       }
        
        [self.customPreviewLayer removeFromSuperlayer];
        self.customPreviewLayer = nil;
@@ -405,15 +339,6 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
 
 - (void)createVideoFileOutput;
 {
-       /*
-       if (self.recordVideo == YES) {
-               self.videoFileOutput = [[AVCaptureMovieFileOutput alloc] init];
-               if ( [self.captureSession canAddOutput:self.videoFileOutput] ) {
-                       [self.captureSession addOutput:self.videoFileOutput];
-               }
-       }
-       */
-       
        /* Video File Output in H.264, via AVAsserWriter */
     NSLog(@"Create Video with dimensions %dx%d", self.imageWidth, self.imageHeight);
     
@@ -426,21 +351,18 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
     
        
        self.recordAssetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:outputSettings];
-    
        
-       /* I'm going to push pixel buffers to it, so will need a 
-          AVAssetWriterPixelBufferAdaptor, to expect the same 32BGRA input as I've
-          asked the AVCaptureVideDataOutput to supply */
+       
        int pixelBufferFormat = (self.grayscaleMode == YES) ? kCVPixelFormatType_420YpCbCr8BiPlanarFullRange : kCVPixelFormatType_32BGRA;
        
        self.recordPixelBufferAdaptor =
                   [[AVAssetWriterInputPixelBufferAdaptor alloc] 
                        initWithAssetWriterInput:self.recordAssetWriterInput 
-                       sourcePixelBufferAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:pixelBufferFormat], kCVPixelBufferPixelFormatTypeKey,nil]];
+                       sourcePixelBufferAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:pixelBufferFormat], kCVPixelBufferPixelFormatTypeKey, nil]];
        
        NSError* error = nil;
-    NSLog(@"Create AVAssetWriter with url: %@", [self tempFileURL]);
-       self.recordAssetWriter = [AVAssetWriter assetWriterWithURL:[self tempFileURL]
+    NSLog(@"Create AVAssetWriter with url: %@", [self videoFileURL]);
+       self.recordAssetWriter = [AVAssetWriter assetWriterWithURL:[self videoFileURL]
                                                       fileType:AVFileTypeMPEG4
                                                          error:&error];
        if (error != nil) {
@@ -448,10 +370,9 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
        }
        
        [self.recordAssetWriter addInput:self.recordAssetWriterInput];
-       self.recordAssetWriterInput.expectsMediaDataInRealTime = NO;
+       self.recordAssetWriterInput.expectsMediaDataInRealTime = YES;
     
     NSLog(@"[Camera] created AVAssetWriter");
-
 }
 
 
@@ -580,8 +501,6 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
                }
                
                
-               
-               
                // render buffer
                dispatch_sync(dispatch_get_main_queue(), ^{
                        self.customPreviewLayer.contents = (__bridge id)dstImage;
@@ -589,16 +508,26 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
                
                
                if (self.recordVideo == YES) {
-                       // a very dense way to keep track of the time at which this frame
-                       // occurs relative to the output stream, but it's just an example!
+                       lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
+//                     CMTimeShow(lastSampleTime);
+                       if (self.recordAssetWriter.status != AVAssetWriterStatusWriting) {
+                               [self.recordAssetWriter startWriting];
+                               [self.recordAssetWriter startSessionAtSourceTime:lastSampleTime];
+                               if (self.recordAssetWriter.status != AVAssetWriterStatusWriting) {
+                                       NSLog(@"[Camera] Recording Error: asset writer status is not writing: %@", self.recordAssetWriter.error);
+                                       return;
+                               } else {
+                                       NSLog(@"[Camera] Video recording started");
+                               }
+                       }
                        
-                       // TODO reset frame number
-                       static int64_t frameNumber = 0;
                        if (self.recordAssetWriterInput.readyForMoreMediaData) {
-                               [self.recordPixelBufferAdaptor appendPixelBuffer:imageBuffer
-                                               withPresentationTime:CMTimeMake(frameNumber, self.defaultFPS)];
+                               if (! [self.recordPixelBufferAdaptor appendPixelBuffer:imageBuffer
+                                                                                                 withPresentationTime:lastSampleTime] ) {
+                                       NSLog(@"Video Writing Error");
+                               }
                        }
-                       frameNumber++;
+               
                }
                
                
@@ -627,14 +556,14 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
     }
     
        ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
-    if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:[self tempFileURL]]) {
-        [library writeVideoAtPathToSavedPhotosAlbum:[self tempFileURL]
+    if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:[self videoFileURL]]) {
+        [library writeVideoAtPathToSavedPhotosAlbum:[self videoFileURL]
                                     completionBlock:^(NSURL *assetURL, NSError *error){}];
     }
 }
 
 
-- (NSURL *)tempFileURL;
+- (NSURL *)videoFileURL;
 {
     NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"];
     NSURL *outputURL = [NSURL fileURLWithPath:outputPath];
@@ -647,7 +576,7 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
 
 
 
-- (NSString *)tempFileString;
+- (NSString *)videoFileString;
 {
     NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"];
     return outputPath;