Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/96.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在iOS中使用AVFoundation切换摄像头后,视频录制不起作用_Ios_Avfoundation_Avcapturesession_Video Recording - Fatal编程技术网

在iOS中使用AVFoundation切换摄像头后,视频录制不起作用

在iOS中使用AVFoundation切换摄像头后,视频录制不起作用,ios,avfoundation,avcapturesession,video-recording,Ios,Avfoundation,Avcapturesession,Video Recording,我正在使用AVFoundation在我的应用程序中录制视频。如果我不切换摄像机,录音工作正常。我一切换摄像机,录音就停止了。调试后,我发现在缓冲区委托方法中,我没有得到videoConnection对象。所以我的委托方法不会被调用,因为条件不满足 不知何故,我无法找到代码中的错误。这是我的密码 非常感谢您的任何帮助。谢谢 // I am calling this method to setup the session from viewDidLoad - (BOOL) setupSes

我正在使用AVFoundation在我的应用程序中录制视频。如果我不切换摄像机,录音工作正常。我一切换摄像机,录音就停止了。调试后,我发现在缓冲区委托方法中,我没有得到videoConnection对象。所以我的委托方法不会被调用,因为条件不满足

不知何故,我无法找到代码中的错误。这是我的密码

非常感谢您的任何帮助。谢谢

    // I am calling this method to setup the session from viewDidLoad 
- (BOOL) setupSessionWithPreview:(UIView *)preview usingFrontCamera:(BOOL)frontCamera
{
    AVCaptureDevice *videoDevice = nil;
    if (frontCamera) {
        videoDevice = [self getFrontCamera];
        self.videoDeviceType = VideoDeviceTypeFrontCamera;
    }
    else {
        videoDevice = [self getRearCamera];
        self.videoDeviceType = VideoDeviceTypeRearCamera;
    }
    AVCaptureDevice *audioDevice = [self getAudioDevice];

    self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:videoDevice error:nil];
    AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:audioDevice error:nil];

    self.session = [[AVCaptureSession alloc] init];
    if([self.session canAddInput:self.videoInput])
        [self.session addInput:self.videoInput];

    if([self.session canAddInput:audioInput])
        [self.session addInput:audioInput];

    self.audioOutput = [[AVCaptureAudioDataOutput alloc] init];
    dispatch_queue_t audioCaptureQ = dispatch_queue_create("Audio Capture Q", DISPATCH_QUEUE_SERIAL);
    [self.audioOutput setSampleBufferDelegate:self queue:audioCaptureQ];

    if([self.session canAddOutput:self.audioOutput])
        [self.session addOutput:self.audioOutput];
    self.audioConnection = [self.audioOutput connectionWithMediaType:AVMediaTypeAudio];

    self.videoOutput = [[AVCaptureVideoDataOutput alloc] init];
    [self.videoOutput setAlwaysDiscardsLateVideoFrames:YES];

    dispatch_queue_t videoCaptureQ = dispatch_queue_create("Video Capture Q", DISPATCH_QUEUE_SERIAL);
    [self.videoOutput setSampleBufferDelegate:self queue:videoCaptureQ];

    if([self.session canAddOutput:self.videoOutput])
        [self.session addOutput:self.videoOutput];

    self.videoConnection = [self.videoOutput connectionWithMediaType:AVMediaTypeVideo];

    self.videoConnection.videoOrientation = AVCaptureVideoOrientationPortrait;
    self.videoOrientation = [self.videoConnection videoOrientation];

    movieWriterQ = dispatch_queue_create("Movie Writer Q", DISPATCH_QUEUE_SERIAL);

    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
    self.viewLayer = [preview layer];
    [self.viewLayer setMasksToBounds:YES];

    CGRect bounds = [preview bounds];
    [self.previewLayer setFrame:bounds];

    [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    [self.viewLayer insertSublayer:self.previewLayer below:[[self.viewLayer sublayers] objectAtIndex:0]];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self.session startRunning];
    });

    return YES;
}

// When user tap on switch camera button , I am calling this method
-(void)toggleCameraIsFront:(BOOL)isFront
{
    AVCaptureDevicePosition desiredPosition;
    if (isFront) {
        desiredPosition = AVCaptureDevicePositionFront;
        self.videoDeviceType = VideoDeviceTypeFrontCamera;
    }
    else {
        desiredPosition = AVCaptureDevicePositionBack;
        self.videoDeviceType = VideoDeviceTypeRearCamera;
    }

    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in videoDevices)
    {
        if ([device position] == desiredPosition)
        {
            AVCaptureDeviceInput *videoDeviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:device error:nil];
            [self.session beginConfiguration];
            [self.session removeInput:self.videoInput];
            if ([self.session canAddInput:videoDeviceInput])
            {
                [self.session addInput:videoDeviceInput];
                [self setVideoInput:videoDeviceInput];
            }
            else
            {
                [self.session addInput:self.videoInput];
            }
            [self.session commitConfiguration];
            break;
        }
    }
}

// This is delegate method
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);

    CFRetain(sampleBuffer);
    CFRetain(formatDescription);

    dispatch_async(movieWriterQ, ^{
        NSString *mediaType = nil;
        if(self.assetWriter)
        {
            BOOL wasReadyToRecord = (readyToRecordAudio && readyToRecordVideo);
            if(connection == self.videoConnection)// this condition is not excuting after switch camera
            {
                if(!readyToRecordVideo)
                    readyToRecordVideo = [self setupAssetWriterVideoInput:formatDescription];
                mediaType = AVMediaTypeVideo;
            }
            else if(connection == self.audioConnection)
            {
                if(!readyToRecordAudio)
                    readyToRecordAudio = [self setupAssetWriterAudioInput:formatDescription];
                mediaType = AVMediaTypeAudio;
            }
            BOOL isReadyToRecord = (readyToRecordAudio && readyToRecordVideo);
            if(!wasReadyToRecord && isReadyToRecord)
            {
                LogDebug(LOG_MODULE, @"Send recording did being");
                recordingWillStart = NO;
                recording = YES;

                dispatch_async(dispatch_get_main_queue(), ^{
                    [self.delegate recordingDidBeginToOutputFileURL:self.outputUrl withID:self.recordingID];
                });
            }

            if(mediaType != nil)
            {
                if(readyToRecordVideo && readyToRecordAudio)
                    [self writeSampleBuffer:sampleBuffer ofType:mediaType];
            }
        }
        CFRelease(sampleBuffer);
        CFRelease(formatDescription);
    });
}

按如下所示更新切换方法后,视频录制工作正常

    -(void)toggleCameraIsFront:(BOOL)isFront
{
    AVCaptureDevicePosition desiredPosition;
    if (isFront) {
        desiredPosition = AVCaptureDevicePositionFront;
        self.videoDeviceType = VideoDeviceTypeFrontCamera;
    }
    else {
        desiredPosition = AVCaptureDevicePositionBack;
        self.videoDeviceType = VideoDeviceTypeRearCamera;
    }


    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in videoDevices)
    {
        if ([device position] == desiredPosition)
        {
            AVCaptureDeviceInput *videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
            [self.session beginConfiguration];
            [self.session removeInput:self.videoInput];
            if ([self.session canAddInput:videoDeviceInput])
            {
                [self.session addInput:videoDeviceInput];
                [self setVideoInput:videoDeviceInput];
            }
            else
            {
                [self.session addInput:self.videoInput];
            }

            [self.session removeOutput:self.videoOutput];

            AVCaptureVideoDataOutput *videoDeviceOutput = [[AVCaptureVideoDataOutput alloc] init];
            if ([self.session canAddOutput:videoDeviceOutput])
            {
                [self.session addOutput:videoDeviceOutput];
                [self setVideoOutput:videoDeviceOutput];
                [self.videoOutput setAlwaysDiscardsLateVideoFrames:YES];

                // How to manage previously created videoCaptureQ in setupSessionWithPreview method ???
                // or do we need create instance variable as dispatch_queue_t videoCaptureQ ???
                dispatch_queue_t videoCaptureQ = dispatch_queue_create("Video Capture Q", DISPATCH_QUEUE_SERIAL);
                [self.videoOutput setSampleBufferDelegate:self queue:videoCaptureQ];

                self.videoConnection = [self.videoOutput connectionWithMediaType:AVMediaTypeVideo];

                self.videoConnection.videoOrientation = AVCaptureVideoOrientationPortrait;
                self.videoOrientation = [self.videoConnection videoOrientation];
            }
            else
            {
                [self.session addOutput:self.videoOutput];
            }

            [self.session commitConfiguration];
            break;
        }
    }
}