如何在AvaCptressession中为视频的每个帧应用过滤器



我正在编写一个应用程序,该应用需要将过滤器应用于使用Avcapturesession捕获的视频。过滤后的输出写入输出文件。当前,我是使用Cifilter和CIIMAGE来过滤每个视频框架的当前。这是代码:

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
    ...
    let pixelBuffer = CMSampleBufferGetImageBuffer(samples)!
    let options = [kCVPixelBufferPixelFormatTypeKey as String : kCVPixelFormatType_420YpCbCr8BiPlanarFullRange]
    let cameraImage = CIImage(cvImageBuffer: pixelBuffer, options: options)
    let filter = CIFilter(name: "CIGaussianBlur")!
    filter.setValue((70.0), forKey: kCIInputRadiusKey)
    filter.setValue(cameraImage, forKey: kCIInputImageKey)
    let result = filter.outputImage!
    var pixBuffer:CVPixelBuffer? = nil;
    let fmt = CVPixelBufferGetPixelFormatType(pixelBuffer)
    CVPixelBufferCreate(kCFAllocatorSystemDefault,
                        CVPixelBufferGetWidth(pixelBuffer),
                        CVPixelBufferGetHeight(pixelBuffer),
                        fmt,
                        CVBufferGetAttachments(pixelBuffer, .shouldPropagate),
                        &pixBuffer);
    CVBufferPropagateAttachments(pixelBuffer, pixBuffer!)
    let eaglContext = EAGLContext(api: EAGLRenderingAPI.openGLES3)!
    eaglContext.isMultiThreaded = true
    let contextOptions = [kCIContextWorkingColorSpace : NSNull(), kCIContextOutputColorSpace: NSNull()]
    let context = CIContext(eaglContext: eaglContext, options: contextOptions)
    CVPixelBufferLockBaseAddress( pixBuffer!, CVPixelBufferLockFlags(rawValue: 0))
    context.render(result, to: pixBuffer!)
    CVPixelBufferUnlockBaseAddress( pixBuffer!, CVPixelBufferLockFlags(rawValue: 0))
    var timeInfo = CMSampleTimingInfo(duration: sampleBuffer.duration,
                                      presentationTimeStamp: sampleBuffer.presentationTimeStamp,
                                      decodeTimeStamp: sampleBuffer.decodeTimeStamp)
    var sampleBuf:CMSampleBuffer? = nil;
    CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault,
                                             pixBuffer!,
                                             samples.formatDescription!,
                                             &timeInfo,
                                             &sampleBuf)
    // write to video file
    let ret = assetWriterInput.append(sampleBuf!)
    ...
}

avassetWriterInput的ret始终是错误的。我在这里做错了什么?另外,我使用的方法非常低效。一路上创建了一些临时副本。是否可以在原地?

我使用了与同一问题的几乎相同的代码。当我发现为渲染创建的像素缓冲区有问题。append(sampleBuffer:)总是返回false,assetWriter.error

错误域= avFoundationRordomain code = -11800"操作可以 未完成" userInfo = {nsunderlyingerror = 0x17024ba30 {错误 domain = nsosstatusorrordomain code = -12780"(null)"}, nslocalizedfailurereason =发生未知错误(-12780), nslocalizedDescription =无法完成操作}

他们说这是一个错误(如下所述),已经发布:https://bugreport.apple.com/web/?problemid=34574848。

但出乎意料的是,我发现当使用原始像素缓冲区进行渲染时,问题消失了。请参阅下面的代码:

let sourcePixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
let sourceImage = CIImage(cvImageBuffer: sourcePixelBuffer)
let filter = CIFilter(name: "CIGaussianBlur", withInputParameters: [kCIInputImageKey: sourceImage])!
let filteredImage = filter.outputImage!
var pixelBuffer: CVPixelBuffer? = nil
let width = CVPixelBufferGetWidth(sourcePixelBuffer)
let height = CVPixelBufferGetHeight(sourcePixelBuffer)
let pixelFormat = CVPixelBufferGetPixelFormatType(sourcePixelBuffer)
let attributes = CVBufferGetAttachments(sourcePixelBuffer, .shouldPropagate)!
CVPixelBufferCreate(nil, width, height, pixelFormat, attributes, &pixelBuffer)
CVBufferPropagateAttachments(sourcePixelBuffer, pixelBuffer!)
var filteredPixelBuffer = pixelBuffer!      // this never works
filteredPixelBuffer = sourcePixelBuffer     // 0_0
let context = CIContext(options: [kCIContextOutputColorSpace: CGColorSpace(name: CGColorSpace.sRGB)!])
context.render(filteredImage, to: filteredPixelBuffer)  // modifying original image buffer here!
let presentationTimestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
var timing = CMSampleTimingInfo(duration: kCMTimeInvalid, presentationTimeStamp: presentationTimestamp, decodeTimeStamp: kCMTimeInvalid)
var processedSampleBuffer: CMSampleBuffer? = nil
var formatDescription: CMFormatDescription? = nil
CMVideoFormatDescriptionCreateForImageBuffer(nil, filteredPixelBuffer, &formatDescription)
CMSampleBufferCreateReadyWithImageBuffer(nil, filteredPixelBuffer, formatDescription!, &timing, &processedSampleBuffer)
print(assetInput!.append(processedSampleBuffer!))

当然,我们都知道您不允许您修改样品缓冲区,但是这种方法可以提供正常的处理视频。技巧很脏,我不能说在您有预览层或同时处理程序的情况下是否可以。

相关内容

  • 没有找到相关文章

最新更新