2013-08-27 3 views
4

Я разрабатываю приложение для iPhone. В этом случае требуется приостановка и возобновление работы камеры. Поэтому я использовал AVFoundation для этого, вместо того, чтобы использовать UIImagePickerController.Измените устройство захвата камеры во время записи видео

Мой код:

- (void) startup :(BOOL)isFrontCamera 
    { 

     if (_session == nil) 
     { 
      NSLog(@"Starting up server"); 

      self.isCapturing = NO; 
      self.isPaused = NO; 
      _currentFile = 0; 
      _discont = NO; 

      // create capture device with video input 
      _session = [[AVCaptureSession alloc] init]; 
      AVCaptureDevice *cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

     if(isFrontCamera) 
     { 
      NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 
      AVCaptureDevice *captureDevice = nil; 
      for (AVCaptureDevice *device in videoDevices) 
      { 
       if (device.position == AVCaptureDevicePositionFront) 
       { 
        captureDevice = device; 
        break; 
       } 
      } 

      cameraDevice = captureDevice; 

     } 


      cameraDevice=[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 
    AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:cameraDevice error:nil]; 

      [_session addInput:input]; 

      // audio input from default mic 
      AVCaptureDevice* mic = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; 
      AVCaptureDeviceInput* micinput = [AVCaptureDeviceInput deviceInputWithDevice:mic error:nil]; 
      [_session addInput:micinput]; 

      // create an output for YUV output with self as delegate 
      _captureQueue = dispatch_queue_create("uk.co.gdcl.cameraengine.capture", DISPATCH_QUEUE_SERIAL); 
      AVCaptureVideoDataOutput* videoout = [[AVCaptureVideoDataOutput alloc] init]; 
      [videoout setSampleBufferDelegate:self queue:_captureQueue]; 
      NSDictionary* setcapSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
              [NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange], kCVPixelBufferPixelFormatTypeKey, 
              nil]; 
      videoout.videoSettings = setcapSettings; 
      [_session addOutput:videoout]; 
      _videoConnection = [videoout connectionWithMediaType:AVMediaTypeVideo]; 

      [_videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait]; 

      NSDictionary* actual = videoout.videoSettings; 
      _cy = [[actual objectForKey:@"Width"] integerValue]; 
      _cx = [[actual objectForKey:@"Height"] integerValue]; 
    AVCaptureAudioDataOutput* audioout = [[AVCaptureAudioDataOutput alloc] init]; 
      [audioout setSampleBufferDelegate:self queue:_captureQueue]; 
      [_session addOutput:audioout]; 
      _audioConnection = [audioout connectionWithMediaType:AVMediaTypeAudio]; 
    [_session startRunning]; 

      _preview = [AVCaptureVideoPreviewLayer layerWithSession:_session]; 
      _preview.videoGravity = AVLayerVideoGravityResizeAspectFill; 
     } 
    } 

Здесь я столкнулся с проблемой, когда я изменить камеру на передний план. когда я вызываю вышеупомянутый метод, меняя камеру на передний план, слой предварительного просмотра застревает, и предварительный просмотр не появляется. Я сомневаюсь: «Можем ли мы изменить захват в середине сеанса захвата?». Сообщите мне, где я ошибаюсь (или) Предложите мне решение о том, как перемещаться между передней и задней камерами во время записи.

Спасибо заранее.

ответ

1

Вы не можете изменить сеанс captureDevice. И вы можете выполнять только один сеанс захвата за раз. Вы можете завершить текущий сеанс и создать новый. Будет небольшое отставание (возможно, второе или два в зависимости от нагрузки вашего процессора).

Желаю, чтобы Apple разрешила несколько сеансов или, по крайней мере, несколько устройств за сеанс ... но они еще не ....

0

Вы считаете, что имеете несколько сеансов, а затем обрабатываете видеофайлы, чтобы объединить их в один?

4

Да, вы можете. Есть всего несколько вещей, которые вам нужно удовлетворить.

  1. Необходимо использовать AVCaptureVideoDataOutput и его делегат для записи.
  2. Перед добавлением нового устройства в устройство убедитесь, что вы удалили предыдущее устройство.
  3. Вы также должны удалить и воссоздать AVCaptureVideoDataOutput.

Я использую эти две функции для него прямо сейчас, и он работает во время сеанса.

- (void)configureVideoWithDevice:(AVCaptureDevice *)camera { 

    [_session beginConfiguration]; 
    [_session removeInput:_videoInputDevice]; 
    _videoInputDevice = nil; 

    _videoInputDevice = [AVCaptureDeviceInput deviceInputWithDevice:camera error:nil]; 
    if ([_session canAddInput:_videoInputDevice]) { 
     [_session addInput:_videoInputDevice]; 
    } 

    [_session removeOutput:_videoDataOutput]; 
    _videoDataOutput = nil; 

    _videoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; 
    [_videoDataOutput setSampleBufferDelegate:self queue:_outputQueueVideo]; 
    NSDictionary* setcapSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange], kCVPixelBufferPixelFormatTypeKey, nil]; 

    _videoDataOutput.videoSettings = setcapSettings; 
    [_session addOutput:_videoDataOutput]; 
    _videoConnection = [_videoDataOutput connectionWithMediaType:AVMediaTypeVideo]; 

    if([_videoConnection isVideoOrientationSupported]) { 
     [_videoConnection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight]; 
    } 

    [_session commitConfiguration]; 
} 

- (void)configureAudioWithDevice:(AVCaptureDevice *)microphone { 
    [_session beginConfiguration]; 
    _audioInputDevice = [AVCaptureDeviceInput deviceInputWithDevice:microphone error:nil]; 
    if ([_session canAddInput:_audioInputDevice]) { 
     [_session addInput:_audioInputDevice]; 
    } 

    [_session removeOutput:_audioDataOutput]; 
    _audioDataOutput = nil; 

    _audioDataOutput = [[AVCaptureAudioDataOutput alloc] init]; 
    [_audioDataOutput setSampleBufferDelegate:self queue:_outputQueueAudio]; 
    [_session addOutput:_audioDataOutput]; 
    _audioConnection = [_audioDataOutput connectionWithMediaType:AVMediaTypeAudio]; 

    [_session commitConfiguration]; 
} 
+0

Этот алгоритм является убийцей, моя единственная проблема заключается в том, что видео и аудио выпадают из синхронизации. Есть ли необходимость в настройке как аудио, так и видео одновременно? – HighFlyingFantasy

+0

@HighFlyingFantasy Существует определенно путь. Это немного сложно. Вам нужно будет вручную манипулировать информацией о времени буфера аудиопоследовательности в соответствии с видео. Поскольку мы воссоздаем audioOutput, его временная информация будет начинаться с нуля каждый раз. Вы должны следить за временем записанного звука и настраивать audioSampleBuffer на это значение, прежде чем записывать его в файл. Geraint Davies внедрил эту технику на примере паузы и возобновления видео. Смесь обоих должна работать на вас. http://www.gdcl.co.uk/2013/02/20/iPhone-Pause.html – hatebyte

Смежные вопросы