2011-03-22 104 views
8

我使用標準AVFoundation類捕獲視頻,並顯示預覽(http://developer.apple.com/library/ios/#qa/qa1702/_index.html對焦(自動對焦)相機無法正常工作(AVFoundation AVCaptureSession)

這裏是我的代碼:

- (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); 
} 

一切工作正常但有時它有一些問題:

  • 相機焦點不工作 - 它的隨機,有時工作,有時不工作。我嘗試了iPhone 4和3GS的不同設備。我試圖谷歌它,但沒有結果。人們只提到有關破碎的設備,但我檢查了3個iPhone 4和一個iPhone 3GS。問題無處不在。
  • 相機加載時間很長。我正在使用ScannerKit API,它也使用相機出於同樣的原因,它的加載速度比我的實現快兩倍。

任何想法可能是一個問題?第一個問題顯然更重要。

+0

嘗試在創建視頻輸入後設置焦點模式。這是你的代碼和我的唯一區別。您可能還想檢查它是否在您稍後的代碼中設置的模式下。 – 2011-03-22 17:55:05

+0

還是一樣,有沒有其他想法? – woojtekr 2011-03-29 12:06:32

+0

我玩過我的應用程序,我轉載了你的問題。我沒有機會調試這個問題。我首先嚐試從WWDC 2010的AVCamDemo中重現它。 – 2011-03-31 21:54:21

回答

1

幾點,我已經注意到,視頻預置時間超過預設照片初始化。

您正在錄製視頻或拍照嗎?

我注意到你有一箇中等質量設置但32BGRA,它可以制定出更好的設置拍攝模式,照片和拍攝後下採樣圖像。同時設置AVVideoCodecJPEG而不是32BGRA。

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

相反的:

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

您可能還需要註冊通知到 subjectAreaChangeMonitoring並強制進行重新聚焦,如果你在任何時候改變對焦模式AVCaptureFocusModeAutoFocus。

你也許還需要添加代碼來手動設置自動對焦和有時這需要將其重置爲自動。

我已經修改了代碼來設置的興趣焦點和日誌攝像機配置錯誤輸出到委託方法。

- (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

老問題,但無論如何可以節省一些小時的挫折。在致電setFocusMode之前設置興趣點很重要,否則您的相機將把焦點設置到前一個焦點。將setFocusMode想象爲COMMIT。同樣適用於setExposureMode。蘋果

AVCam樣品是完全錯誤和破碎。

+1

您只需要爲我節省很多時間 – devfreak 2015-03-07 20:36:52

+1

非常真實有用:-) – 2015-06-10 13:44:41