【问题标题】:AVCaptureSession with multiple Outputs?具有多个输出的 AVCaptureSession?
【发布时间】:2011-11-09 00:17:53
【问题描述】:

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

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

当我尝试实现视频录制时,通过将 SampleBuffers 写入视频,因为我从 AVCaptureVideoDataOutput 收到它们,它的帧速率非常慢(可能是因为其他与图像相关的处理正在进行中)。

所以我想知道,是否有可能让 AVCaptureVideoDataOutput 和 AVCaptureMoveFileOutput 同时在同一个 AVCaptureSession 上进行?

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

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

任何帮助将不胜感激。

【问题讨论】:

  • 您是否使用 AVAssetWriter 将图像写入 MOV/MP4?我确实使用了自定义的 OpenGL 图像处理引擎,并且仍然可以以 30fps 的速度录制。我假设 CoreImage 将支持 OpenGL 以提高效率。我确实怀疑阻碍你的是图像的显示。您是使用 OpenGL 来渲染图像,还是使用其他 API(可能基于 CPU)?
  • 您找到可行的解决方案了吗?
  • @SteveMcFarlin 他说他正在使用 AVCaptureMoveFileOutput;这与 AVAssetWriter 不同。

标签: ios avfoundation avcapturesession


【解决方案1】:

这比你想象的要容易。

见:AVCamDemo

  1. 使用 AVCaptureVideoDataOutput 捕获数据。
  2. 在录制之前创建一个新的调度队列,例如。录音队列:recordingQueue = dispatch_queue_create("Movie Recording Queue", DISPATCH_QUEUE_SERIAL);
  3. 在 captureOutput:didOutputSampleBuffer:fromConnection:delegate 方法,捕获样本缓冲区,保留它,并在记录中 队列,将其写入文件:

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

【讨论】:

  • 请转换为 Swift 4
  • 你为什么使用 AVAssetWriter?这个问题没有提到这一点,你的回答也没有解释你在哪里定义了assetWriter。
猜你喜欢
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
相关资源
最近更新 更多