2011-03-22 11 views
8

estoy usando clases AVFoundation estándar para capturar vídeo y mostrar vista previa (http://developer.apple.com/library/ios/#qa/qa1702/_index.html)Focus (enfoque automático) que no trabajan en la cámara (AVFoundation AVCaptureSession)

Aquí está mi código:

- (void)setupCaptureSession {  
    NSError *error = nil; 

    [self setCaptureSession: [[AVCaptureSession alloc] init]]; 

    self.captureSession.sessionPreset = AVCaptureSessionPresetMedium; 

    device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

    if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus] && [device lockForConfiguration:&error]) { 
     [device setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; 
     [device unlockForConfiguration]; 
    } 

    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device 
                     error:&error]; 
    if (!input) { 
     // TODO: Obsługa błędu, gdy nie uda się utworzyć wejścia 
    } 
    [[self captureSession] addInput:input]; 

    AVCaptureVideoDataOutput *output = [[[AVCaptureVideoDataOutput alloc] init] autorelease]; 
    [[self captureSession] addOutput:output]; 

    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL); 
    [output setSampleBufferDelegate:self queue:queue]; 
    dispatch_release(queue); 

    output.videoSettings = 
    [NSDictionary dictionaryWithObject: 
    [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] 
           forKey:(id)kCVPixelBufferPixelFormatTypeKey]; 


    output.minFrameDuration = CMTimeMake(1, 15); 

    [[self captureSession] startRunning]; 

    AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession]; 
    captureVideoPreviewLayer.frame = previewLayer.bounds; 
    [previewLayer.layer insertSublayer:captureVideoPreviewLayer atIndex:0]; 
    [previewLayer setHidden:NO]; 

    mutex = YES; 
} 

// Delegate routine that is called when a sample buffer was written 
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection { 
    if (mutex && ![device isAdjustingFocus] && ![device isAdjustingExposure] && ![device isAdjustingWhiteBalance]) { 
     // something 
    } 
} 

// Create a UIImage from sample buffer data 
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer { 
    // Get a CMSampleBuffer's Core Video image buffer for the media data 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    // Lock the base address of the pixel buffer 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    // Get the number of bytes per row for the pixel buffer 
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 

    // Get the number of bytes per row for the pixel buffer 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    // Get the pixel buffer width and height 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Create a device-dependent RGB color space 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    // Create a bitmap graphics context with the sample buffer data 
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, 
               bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    // Create a Quartz image from the pixel data in the bitmap graphics context 
    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 
    // Unlock the pixel buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

    // Free up the context and color space 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 

    // Create an image object from the Quartz image 
    UIImage *image = [UIImage imageWithCGImage:quartzImage]; 

    // Release the Quartz image 
    CGImageRelease(quartzImage); 

    return (image); 
} 

Todo está funcionando bien pero a veces tiene algunos problemas:

  • Camera Focus no funciona - Es aleatorio, a veces funciona, a veces no. Probé en diferentes dispositivos tanto para iPhone 4 como para 3GS. Traté de googlearlo, pero sin resultados. La gente solo menciona sobre dispositivos rotos, pero revisé 3 iPhone 4 y uno iPhone 3GS. El problema está en todas partes.
  • La cámara se está cargando bastante. Estoy usando la API de ScannerKit, que también usa la cámara por las mismas razones y se carga aproximadamente dos veces más rápido que mi implementación.

¿Alguna idea que puede ser un problema? El primer problema es definitivamente más importante.

+0

Intente configurar el modo de enfoque después de haber creado la entrada de video. Esa es la única diferencia entre tu código y el mío. También es posible que desee verificar que esté en el modo que configuró en algún momento posterior de su código. –

+0

sigue siendo el mismo, alguna otra idea? – woojtekr

+0

Jugué con mi aplicación y reproduje su problema. No he tenido la oportunidad de solucionar este problema. Comenzaré tratando de reproducirlo con AVCamDemo desde WWDC 2010. –

Respuesta

1

En algunos puntos, me he dado cuenta de que los ajustes preestablecidos de video tardan más en inicializarse que los ajustes preestablecidos de fotos.

¿Está grabando video o tomando fotos?

Me he dado cuenta de que tiene una configuración de calidad media, pero con 32BGRA, podría ser mejor configurar el modo de captura en Foto y disminuir la resolución de la imagen después de la captura. También configure AVVideoCodecJPEG en lugar de 32BGRA.

[device setOutputSettings:[NSDictionary dictionaryWithObject:AVVideoCodecJPEG forKey:AVVideoCodecKey]]; 

En lugar de:

[device setOutputSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCMPixelFormat_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; 

También puede ser que desee registrar las notificaciones a subjectAreaChangeMonitoring y forzar un nuevo enfoque, si el cambio de modo de enfoque en AVCaptureFocusModeAutoFocus en cualquier punto.

También es posible que desee agregar un código para configurar manualmente el enfoque automático y restablecerlo a automático, como a veces es necesario.

He modificado el código para establecer un foco de interés y registrar el resultado de error de configuración de la cámara en un método delegado.

- (void)setupCaptureSession {  
    NSError *error = nil; 

    [self setCaptureSession: [[AVCaptureSession alloc] init]]; 

    self.captureSession.sessionPreset = AVCaptureSessionPresetMedium; 

    device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

    if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus] && [device lockForConfiguration:&error]){ 
     [device setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; 
     if ([device isFocusPointOfInterestSupported]) 
      [device setFocusPointOfInterest:CGPointMake(0.5f,0.5f)]; 
     [device unlockForConfiguration]; 
    }else { 
     if ([[self delegate] 
       respondsToSelector:@selector(captureManager:didFailWithError:)]) { 
       [[self delegate] captureManager:self didFailWithError:error]; 
     } 
    } 

    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device 
                     error:&error]; 
    if (!input) { 
     // TODO: Obsługa błędu, gdy nie uda się utworzyć wejścia 
    } 
    [[self captureSession] addInput:input]; 

    AVCaptureVideoDataOutput *output = [[[AVCaptureVideoDataOutput alloc] init] autorelease]; 
    [[self captureSession] addOutput:output]; 

    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL); 
    [output setSampleBufferDelegate:self queue:queue]; 
    dispatch_release(queue); 

    output.videoSettings = 
    [NSDictionary dictionaryWithObject: 
    [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] 
           forKey:(id)kCVPixelBufferPixelFormatTypeKey]; 


    output.minFrameDuration = CMTimeMake(1, 15); 

    [[self captureSession] startRunning]; 

    AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession]; 
    captureVideoPreviewLayer.frame = previewLayer.bounds; 
    [previewLayer.layer insertSublayer:captureVideoPreviewLayer atIndex:0]; 
    [previewLayer setHidden:NO]; 

    mutex = YES; 
} 
9

Una pregunta anterior pero de todos modos puede ahorrarle a alguien horas de frustración. Es importante establecer el punto de interés antes de llamar al setFocusMode; de lo contrario, la cámara establecerá el enfoque en el punto de enfoque anterior. Piense en setFocusMode como COMPROMISO. Lo mismo se aplica al setExposureMode.

La muestra AVCam de Apple es totalmente incorrecta y está rota.

+1

Simplemente me ahorras mucho tiempo muchas gracias – devfreak

+1

Muy cierto y útil :-) –

Cuestiones relacionadas