【问题标题】:Converting MTLTexture to CVPixelBuffer将 MTLTexture 转换为 CVPixelBuffer
【发布时间】:2017-10-01 15:28:42
【问题描述】:

我目前正在使用 Metal 开发实时过滤器。 定义我的 CIImage 后,我将图像渲染为 MTLTexture。

下面是我的渲染代码。 context 是一个由 Metal 支持的 CIContext; targetTexture 是附加到我的 MTKView 实例的 currentDrawable 属性的纹理的别名:

context?.render(drawImage, to: targetTexture, commandBuffer: commandBuffer, bounds: targetRect, colorSpace: colorSpace)

它可以正确渲染,因为我可以看到金属视图上显示的图像。

问题是在渲染图像(并显示它)之后,我想提取 CVPixelBuffer 并使用 AVAssetWriter 类将其保存到磁盘。

另一种选择是有两个渲染步骤,一个渲染到纹理,另一个渲染到 CVPixelBuffer。 (但不清楚如何创建这样的缓冲区,或者两个渲染步骤对帧率的影响)

任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: ios swift avfoundation core-image metal


    【解决方案1】:

    您可以尝试像这样从 MTLTexture 复制原始数据:

    var outPixelbuffer: CVPixelBuffer?
    if let datas = targetTexture.texture.buffer?.contents() {
        CVPixelBufferCreateWithBytes(kCFAllocatorDefault, targetTexture.width, 
        targetTexture.height, kCVPixelFormatType_64RGBAHalf, datas, 
        targetTexture.texture.bufferBytesPerRow, nil, nil, nil, &outPixelbuffer);
    }
    

    【讨论】:

    • 哦,我刚刚找到了另一种方法,CoreImage可以使用MTLTexture创建CIImage,而不用关心pixelFormat
    • 请注意,如果纹理最初不是从缓冲区创建的,则“缓冲区”将为 NIL。
    • @Ash 知道如果纹理不是从缓冲区创建的,如何创建像素缓冲区?
    • @prabhu 改用CVPixelBufferCreate()。前四个和后两个属性与上面代码中的相同。
    【解决方案2】:
    + (void)getPixelBufferFromBGRAMTLTexture:(id<MTLTexture>)texture result:(void(^)(CVPixelBufferRef pixelBuffer))block
    {
    
    CVPixelBufferRef pxbuffer = NULL;
     NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                              [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                              [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                              nil];
     
    size_t imageByteCount = texture.width * texture.height * 4;
    void *imageBytes = malloc(imageByteCount);
    NSUInteger bytesPerRow = texture.width * 4;
    MTLRegion region = MTLRegionMake2D(0, 0, texture.width, texture.height);
    [texture getBytes:imageBytes bytesPerRow:bytesPerRow fromRegion:region mipmapLevel:0];
    
    CVPixelBufferCreateWithBytes(kCFAllocatorDefault,texture.width,texture.height,kCVPixelFormatType_32BGRA,imageBytes,bytesPerRow,NULL,NULL,(__bridge CFDictionaryRef)options,&pxbuffer);
    
    if (block) {
        block(pxbuffer);
    }
    CVPixelBufferRelease(pxbuffer);
    free(imageBytes);
    }
    

    【讨论】:

    • 您可以使用代码格式化吗(使用``` 表示代码块)?谢谢!
    猜你喜欢
    • 2017-12-04
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    • 1970-01-01
    • 2016-09-23
    • 2017-11-11
    • 2018-04-16
    • 1970-01-01
    相关资源
    最近更新 更多