2014-03-26 3 views
3

AVFoundation을 사용하여 내 응용 프로그램에 비디오를 녹화하고 있습니다. 카메라를 전환하지 않으면 촬영이 올바르게 작동합니다. 카메라를 전환하자 마자 녹음이 멈 춥니 다. 디버깅 후 나는 buffer delegate 메소드에서 videoConnection 객체를 얻지 못하고 있음을 발견했다. 그래서 조건이 만족되지 않기 때문에 내 대리자 메서드가 호출되지 않습니다.iOS에서 AVFoundation을 사용하여 카메라를 전환 한 후 비디오 녹화가 작동하지 않습니다.

어떻게 든 코드에서 잘못된 것을 찾을 수 없습니다. 여기 내 코드

어떤 종류의 도움을 주시면 감사하겠습니다. 감사.

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

답변

1

아래와 같이 전환 방법을 업데이트 한 후, 비디오 레코딩이

-(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; 
     } 
    } 
} 
올바르게 작동