将相机预览显示在AVCaptureVideoPreviewLayer上

11
我试图让相机输入显示在预览层视图上。 self.cameraPreviewView绑定了IB中的一个UIView。 以下是来自AV Foundation编程指南的当前代码。 但是,预览从未显示。
AVCaptureSession *session = [[AVCaptureSession alloc] init];
    session.sessionPreset = AVCaptureSessionPresetHigh;

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    NSError *error = nil;
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];

    if (!input) {
        NSLog(@"Couldn't create video capture device");
    }
    [session addInput:input];


        // Create video preview layer and add it to the UI
        AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
        UIView *view = self.cameraPreviewView;
        CALayer *viewLayer = [view layer];

        newCaptureVideoPreviewLayer.frame = view.bounds;

        [viewLayer addSublayer:newCaptureVideoPreviewLayer];

        self.cameraPreviewLayer = newCaptureVideoPreviewLayer;



        [session startRunning];

请尝试以下代码: newCaptureVideoPreviewLayer.frame = self.cameraPreviewView.bounds; [self.cameraPreviewView.layer addSublayer:newCaptureVideoPreviewLayer]; [session startRunning]; - BhushanVU
@bhuXan - 刚刚尝试了一下,仍然是黑屏。 - William
2个回答

22

经过一些尝试和查看苹果的AVCam示例代码,我将PreviewLayer代码和session startRunning进行了封装,放入了一个大中央调度块中,这样它就开始工作了。

 dispatch_async(dispatch_get_main_queue(), ^{
    AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    UIView *view = self.cameraPreviewView;
    CALayer *viewLayer = [view layer];

    newCaptureVideoPreviewLayer.frame = view.bounds;

    [viewLayer addSublayer:newCaptureVideoPreviewLayer];

    self.cameraPreviewLayer = newCaptureVideoPreviewLayer;

    [session startRunning];
});

6
这里最棘手的一行是 [session startRunning]; ,不幸的是,大多数教程都没有涉及到它。 - Andrei Konstantinov
对不起,我不太理解 self.cameraPreviewLayer 到底是什么?如果它是一个 UIView 的话,很明显会给我们一个错误。这让我感到困惑。 - Reza.Ab

19

这是我的代码,对我来说完美地工作了,你可以参考它。

- (void)initCapture
{
    AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];
    if (!captureInput) {
        return;
    }
    AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];
    /* captureOutput:didOutputSampleBuffer:fromConnection delegate method !*/
    [captureOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
    NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
    NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
    NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
    [captureOutput setVideoSettings:videoSettings];
    self.captureSession = [[AVCaptureSession alloc] init];
    NSString* preset = 0;
    if (!preset) {
        preset = AVCaptureSessionPresetMedium;
    }
    self.captureSession.sessionPreset = preset;
    if ([self.captureSession canAddInput:captureInput]) {
        [self.captureSession addInput:captureInput];
    }
    if ([self.captureSession canAddOutput:captureOutput]) {
        [self.captureSession addOutput:captureOutput];
    }

    //handle prevLayer
    if (!self.captureVideoPreviewLayer) {
        self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
    }

    //if you want to adjust the previewlayer frame, here!
    self.captureVideoPreviewLayer.frame = self.view.bounds;
    self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.view.layer addSublayer: self.captureVideoPreviewLayer];
    [self.captureSession startRunning];
}

这个会真的记录吗? - user717452
你是怎么想出这段代码的?你是先参考了苹果文档吗?很想知道 :) - hinterbu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接