2010-11-20 1 views
1

Я пытаюсь использовать AVCaptureSession для получения изображений с передней камеры для обработки. Пока каждый новый кадр был доступен, я просто назначал его переменной и запускал NSTimer, который проверяет каждую десятую часть секунды, если есть новый фрейм, и если он его обрабатывает.Как вы снимаете только отдельные кадры камеры с помощью AVCaptureSession?

Я хотел бы получить рамку, заморозить камеру и получить следующий кадр, когда захочу. Что-то вроде [captureSession getNextFrame] вы знаете?

Вот часть моего кода, хотя я не уверен, насколько полезным может быть:

- (void)startFeed { 

loopTimerIndex = 0; 

    NSArray *captureDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 

    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput 
              deviceInputWithDevice:[captureDevices objectAtIndex:1] 
              error:nil]; 

    AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init]; 
    captureOutput.minFrameDuration = CMTimeMake(1, 10); 
    captureOutput.alwaysDiscardsLateVideoFrames = true; 

    dispatch_queue_t queue; 
    queue = dispatch_queue_create("cameraQueue", nil); 

    [captureOutput setSampleBufferDelegate:self queue:queue]; 
    dispatch_release(queue); 

    NSString *key = (NSString *)kCVPixelBufferPixelFormatTypeKey; 
    NSNumber *value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA]; 
    NSDictionary *videoSettings = [NSDictionary dictionaryWithObject:value forKey:key]; 
    [captureOutput setVideoSettings:videoSettings]; 

    captureSession = [[AVCaptureSession alloc] init]; 
    captureSession.sessionPreset = AVCaptureSessionPresetLow; 
    [captureSession addInput:captureInput]; 
    [captureSession addOutput:captureOutput]; 

    imageView = [[UIImage alloc] init]; 

    [captureSession startRunning]; 

} 

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection { 

loopTimerIndex++; 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    CGImageRef newImage = CGBitmapContextCreateImage(newContext); 

    CGContextRelease(newContext); 
    CGColorSpaceRelease(colorSpace); 

    imageView = [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationLeftMirrored]; 
    [delegate updatePresentor:imageView]; 
    if(loopTimerIndex == 1) { 
     [delegate feedStarted]; 
    } 

    CGImageRelease(newImage); 
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0); 

    [pool drain]; 

} 

ответ

3

Вы не активно опрашивать камеру, чтобы получить кадры обратно, потому что это не так, как процесс захвата архитектура. Вместо этого, если вы хотите отображать только кадры каждую десятую секунды вместо каждых 1/30 или более, вы должны просто игнорировать рамки между ними.

Например, вы могли бы сохранить временную метку, которую вы бы сравнивали с каждым разом, когда был запущен -captureOutput:didOutputSampleBuffer:fromConnection:. Если метка времени больше или равна 0,1 секундам прямо сейчас, обработайте и покажите рамку камеры и сбросьте метку времени до текущего времени. В противном случае игнорируйте рамку.