AVCaptureSession с несколькими выходами? - PullRequest
21 голосов
/ 09 ноября 2011

В настоящее время я разрабатываю приложение для iOS, которое применяет CoreImage к каналу камеры, чтобы делать фотографии и видео, и я столкнулся с небольшим затруднением.

До сих пор я использовал AVCaptureVideoDataOutput , чтобы получить образцы буферов и манипулировать ими с помощью CoreImage, а затем отображать простой предварительный просмотр, а также использовать его для захвата фотографий и их сохранения.

Когда я пытался реализовать запись видео, записывая SampleBuffers в видео, когда я получал их от AVCaptureVideoDataOutput , у него была очень низкая частота кадров (возможно, из-за обработки другого изображения, которая продолжается).

Итак, мне было интересно, возможно ли иметь AVCaptureVideoDataOutput и AVCaptureMoveFileOutput, работающие одновременно на одном AVCaptureSession?

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

Если я смогу заставить его работать, я надеюсь, что это означает, что я могу просто использовать 2-й выход для записи видео с высокой частотой кадров и выполнять постобработку видео после того, как пользователь прекратил запись.

Любая помощь будет принята с благодарностью.

1 Ответ

4 голосов
/ 26 февраля 2014

Это проще, чем вы думаете.

См .: AVCamDemo

  1. Захват данных с использованием AVCaptureVideoDataOutput.
  2. Создание новой отправкиочередь перед записью, например.recordingQueue: recordingQueue = dispatch_queue_create("Movie Recording Queue", DISPATCH_QUEUE_SERIAL);
  3. В методе captureOutput: didOutputSampleBuffer: fromConnection: делегировать метод, захватить выборочный буфер, сохранить его, а в очереди записи записать его в файл:

    -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {    
    
        CFRetain(sampleBuffer);
    
        dispatch_async(recordingQueue, ^{
    
            if (assetWriter) {
    
                if (connection == videoConnection) {
                    [self writeSampleBuffer:sampleBuffer ofType:AVMediaTypeVideo];
                } else if (connection == audioConnection) {
                    [self writeSampleBuffer:sampleBuffer ofType:AVMediaTypeAudio];
                }
    
            }
    
            CFRelease(sampleBuffer);        
        });
    }
    
        - (void) writeSampleBuffer:(CMSampleBufferRef)sampleBuffer ofType:(NSString *)mediaType
        {
            CMTime presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    
            if ( assetWriter.status == AVAssetWriterStatusUnknown ) {
    
                if ([assetWriter startWriting]) {
                    [assetWriter startSessionAtSourceTime:presentationTime];
                } else {
                    NSLog(@"Error writing initial buffer");
                }
            }
    
            if ( assetWriter.status == AVAssetWriterStatusWriting ) {
    
                if (mediaType == AVMediaTypeVideo) {
                    if (assetWriterVideoIn.readyForMoreMediaData) {
    
                        if (![assetWriterVideoIn appendSampleBuffer:sampleBuffer]) {
                            NSLog(@"Error writing video buffer");
                        }
                    }
                }
                else if (mediaType == AVMediaTypeAudio) {
                    if (assetWriterAudioIn.readyForMoreMediaData) {
    
                        if (![assetWriterAudioIn appendSampleBuffer:sampleBuffer]) {
                            NSLog(@"Error writing audio buffer");
                        }
                    }
                }
            }
        }
    
...