AVCaptureSession如何使用多个输出?

23

我目前正在开发一个iOS应用程序,它将CoreImage应用于相机视频流以拍摄照片和视频,但遇到了一些问题。

到目前为止,我一直在使用AVCaptureVideoDataOutput获取样本缓冲区并使用CoreImage来操作它们,然后显示简单的预览,并使用它来拍摄照片并保存它们。

当我尝试实现视频录制(通过将样本缓冲区从AVCaptureVideoDataOutput写入视频),帧率非常慢(可能是因为正在进行其他图像相关处理)。

所以我想知道,是否可以同时使用AVCaptureVideoDataOutput和AVCaptureMoveFileOutput在同一个AVCaptureSession中工作?

我尝试了一下,发现当我添加了额外的输出时,我的AVCaptureVideoDataOutput停止接收信息。

如果我能让它正常工作,我希望这意味着我可以简单地使用第二个输出以高帧速率记录视频,并在用户停止录制后对视频进行后处理。

任何帮助将不胜感激。


你是在使用AVAssetWriter将图像写入MOV/MP4吗?我使用自定义的OpenGL图像处理引擎,仍然可以以30fps录制。我认为CoreImage应该是OpenGL支持的,以提高效率。我怀疑阻碍你的是图像的显示。你是使用OpenGL来渲染图像,还是使用其他API(可能是基于CPU的)? - Steve McFarlin
你找到可行的解决方案了吗? - user454083
@SteveMcFarlin 他说他正在使用AVCaptureMoveFileOutput;这与AVAssetWriter不同。 - James Bush
1个回答

4

这比你想象的要简单。

看看: AVCamDemo

  1. Capture data using AVCaptureVideoDataOutput.
  2. Create a new dispatch queue before recording, eg. recordingQueue: recordingQueue = dispatch_queue_create("Movie Recording Queue", DISPATCH_QUEUE_SERIAL);
  3. In the captureOutput:didOutputSampleBuffer:fromConnection: delegate method, capture the samplebuffer, retain it, and in the recording queue, write it to the file:

    -(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");
                        }
                    }
                }
            }
        }
    

2
please, convert to Swift 4 - user924
你为什么使用AVAssetWriter?这个问题没有提到过,而你的回答也没有解释你在哪里定义了assetWriter。 - willbattel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接