2014-03-26 54 views
3

我正在使用AVFoundation在我的應用中錄製視頻。如果我不切換相機,錄製就能正常工作。只要我切換相機,錄製停止工作。調試後我發現在緩衝區委託方法中,我沒有獲得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; 
     } 
    } 
} 
相關問題