使用AV Foundation有效使用Core Image

时间:2014-04-06 23:12:48

标签: ios video opengl-es video-processing core-image

我正在编写一个iOS应用程序,将过滤器应用于现有视频文件,并将结果输出到新视频文件。最初,我尝试使用Brad Larson的漂亮框架GPUImage。虽然我能够毫不费力地输出过滤后的视频文件,但输出并不完美:视频长度适当,但有些帧丢失,其他帧重复(有关详细信息,请参阅Issue 1501) 。我计划了解有关OpenGL ES的更多信息,以便我可以更好地调查丢弃/跳过的帧问题。但是,与此同时,我正在探索渲染视频文件的其他选项。

我已经熟悉Core Image,所以我决定在另一种视频过滤解决方案中利用它。在传递给AVAssetWriterInput requestMediaDataWhenReadyOnQueue:usingBlock:的块中,我过滤并输出输入视频文件的每一帧,如下所示:

CMSampleBufferRef sampleBuffer = [self.assetReaderVideoOutput copyNextSampleBuffer];
if (sampleBuffer != NULL)
{
    CMTime presentationTimeStamp = CMSampleBufferGetOutputPresentationTimeStamp(sampleBuffer);

    CVPixelBufferRef inputPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CIImage* frame = [CIImage imageWithCVPixelBuffer:inputPixelBuffer];
    // a CIFilter created outside the "isReadyForMoreMediaData" loop
    [screenBlend setValue:frame forKey:kCIInputImageKey];

    CVPixelBufferRef outputPixelBuffer;
    CVReturn result = CVPixelBufferPoolCreatePixelBuffer(NULL, assetWriterInputPixelBufferAdaptor.pixelBufferPool, &outputPixelBuffer);

    // verify that everything's gonna be ok
    NSAssert(result == kCVReturnSuccess, @"CVPixelBufferPoolCreatePixelBuffer failed with error code");
    NSAssert(CVPixelBufferGetPixelFormatType(outputPixelBuffer) == kCVPixelFormatType_32BGRA, @"Wrong pixel format");

    [self.coreImageContext render:screenBlend.outputImage toCVPixelBuffer:outputPixelBuffer];
    BOOL success = [assetWriterInputPixelBufferAdaptor appendPixelBuffer:outputPixelBuffer withPresentationTime:presentationTimeStamp];
    CVPixelBufferRelease(outputPixelBuffer);
    CFRelease(sampleBuffer);
    sampleBuffer = NULL;
    completedOrFailed = !success;
}

这很有效:渲染看起来相当快,并且生成的视频文件没有任何丢失或重复的帧。但是,我并不确信我的代码是否尽可能高效。具体来说,我的问题是

  1. 此方法是否允许设备将所有帧数据保留在GPU上,或者是否存在过早将像素复制到CPU的任何方法(例如imageWithCVPixelBuffer:render:toCVPixelBuffer:)?
  2. 使用CIContext drawImage:inRect:fromRect:绘制到OpenGLES上下文会更有效吗?
  3. 如果对#2的回答是肯定的,那么将drawImage:inRect:fromRect:的结果导入CVPixelBufferRef的正确方法是什么,以便将其附加到输出视频文件?< / LI>

    我已经搜索过如何使用CIContext drawImage:inRect:fromRect:呈现已过滤的视频帧的示例,但尚未找到任何内容。值得注意的是,GPUImageMovieWriter的来源做了类似的事情,但是因为a)我还没有真正理解它,并且b)它对这个用例不太正常,我&#39;警惕复制其解决方案。

0 个答案:

没有答案