ios - 同一个 AVCaptureSession 中的多个 AVCaptureVideoDataOutput

标签 ios iphone ios-camera

我想知道是否可以通过单个相机设备输入将多个 AVCaptureVideoDataOutput 添加到 AVCaptureSession

我的实验表明,添加第二个 VideoDataOutput 将导致 canAddOutput 返回 NO。但是我在 Apple 的文档中找不到任何地方说不允许多数据输出。

最佳答案

我们不能对多个 AVCaptureVideoDataOutput 对象使用单个 AVCaptureSession

您可以做的是使用多个 AVCaptureSession 对象制作多个 AVCaptureVideoDataOutput

您可以创建两个不同的 AVCaptureVideoDataOutputAVCaptureSession 设置,然后您可以在应用程序中一个接一个地使用它们,您将能够实现目标。

在我的例子中,我必须同时使用相机拍摄正面和背面图像。

我确实为 AVCaptureVideoDataOutputAVCaptureSession 创建了两个不同的对象,如下所示。

/* Front camera settings */
@property bool isFrontRecording;
@property (strong, nonatomic) AVCaptureDeviceInput *videoInputBack;
@property (strong, nonatomic) AVCaptureStillImageOutput *imageOutputBack;
@property (strong, nonatomic) AVCaptureSession *sessionBack;

/* Back camera settings */
@property bool isBackRecording;
@property (strong, nonatomic) AVCaptureDeviceInput *videoInputFront;
@property (strong, nonatomic) AVCaptureStillImageOutput *imageOutputFront;
@property (strong, nonatomic) AVCaptureSession *sessionFront;

现在在 View 中最初加载我设置了后置摄像头并设置了 session 开始记录或不开始记录的标志,如下所示。

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setupBackAVCapture];

    self.isFrontRecording = NO;
    self.isBackRecording = NO;
}

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

    self.sessionBack = [[AVCaptureSession alloc] init];
    self.sessionBack.sessionPreset = AVCaptureSessionPresetPhoto;

    AVCaptureDevice *camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    self.videoInputBack = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&error];
    [self.sessionBack addInput:self.videoInputBack];

    self.imageOutputBack = [[AVCaptureStillImageOutput alloc] init];
    [self.sessionBack addOutput:self.imageOutputBack];

}

现在,每当用户开始拍摄照片时,我们都会使用以下代码拍摄正面照片。

- (IBAction)buttonCapture:(id)sender {
    [self takeBackPhoto];
}

- (void)takeBackPhoto
{
    [self.sessionBack startRunning];
    if (!self.isFrontRecording) {

        self.isFrontRecording = YES;

        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
        AVCaptureConnection *videoConnection = [self.imageOutputBack connectionWithMediaType:AVMediaTypeVideo];

        if (videoConnection == nil) {
            return;
        }


        [self.imageOutputBack
         captureStillImageAsynchronouslyFromConnection:videoConnection
         completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {

             if (imageDataSampleBuffer == NULL) {
                 return;
             }

             NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];

             UIImage *image = [[UIImage alloc] initWithData:imageData];

             UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);

             [self.imageView setImage:image];

             [self.sessionBack stopRunning];

             // Set up front camera setting and capture photo.
             [self setupFrontAVCapture];
             [self takeFrontPhoto];

         }];

        self.isFrontRecording = NO;

    }

}

一旦捕获到背面图像,我们将设置 session 以使用 setupFrontAVCapture 方法捕获正面图像,然后我们将使用 takeFrontPhoto 方法捕获正面图像,如下所示.

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

    self.sessionFront = [[AVCaptureSession alloc] init];
    self.sessionFront.sessionPreset = AVCaptureSessionPresetPhoto;

    AVCaptureDevice *camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    camera = [self cameraWithPosition:AVCaptureDevicePositionFront];

    self.videoInputFront = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&error];
    [self.sessionFront addInput:self.videoInputFront];

    self.imageOutputFront = [[AVCaptureStillImageOutput alloc] init];
    [self.sessionFront addOutput:self.imageOutputFront];
}

- (void)takeFrontPhoto
{
    [self.sessionFront startRunning];
    if (!self.isBackRecording) {

        self.isBackRecording = YES;

        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
        AVCaptureConnection *videoConnection = [self.imageOutputFront connectionWithMediaType:AVMediaTypeVideo];

        if (videoConnection == nil) {
            return;
        }


        [self.imageOutputFront
         captureStillImageAsynchronouslyFromConnection:videoConnection
         completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {

             if (imageDataSampleBuffer == NULL) {
                 return;
             }

             NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];

             UIImage *image = [[UIImage alloc] initWithData:imageData];

             UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
             [self.imageViewBack setImage:image];

             [self.sessionFront stopRunning];


         }];

        self.isBackRecording = NO;

    }

}

这样你就可以使用两组不同的 AVCaptureSessionAVCaptureStillImageOutput 对象,你可以实现你的目标。

如果您有任何困惑,请告诉我。

关于ios - 同一个 AVCaptureSession 中的多个 AVCaptureVideoDataOutput,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44577331/

相关文章:

ios - 必须调用父类(super class) 'UITableViewHeaderFooterView' 的指定初始化程序

iPhone UITextField inputView 错误 : Assignement to readonly property

ios - 如何打开/关闭 iPhone 相机闪光灯?

ios - 使用 self.property 释放属性 - 分析器中的错误

ios - 媒体查询像素比率不起作用

ios - 如何检查某个对象是否存在于 NSMutableArray 的某个索引处?

iphone - 如何处理多个 View

iphone - 检查网站上的文件是否存在

ios - 了解AVCapture设备exposureDuration、exposureTargetOffset、exposureTargetBias

ios 9 AVCaptureDevice 设置焦点