首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS加速:将luma和chroma缓冲区放在一个CVPixelBuffer中

iOS加速:将luma和chroma缓冲区放在一个CVPixelBuffer中
EN

Stack Overflow用户
提问于 2022-09-27 06:27:02
回答 2查看 51关注 0票数 0

我正在转换相机输出420YpCbCr8BiPlanarFullRangeARGB8888以便执行一些图像处理。我需要将结果转换回420YpCbCr8BiPlanarFullRange,以将其与webRTC进行流:

代码语言:javascript
复制
func convertTo420Yp8(source: inout vImage_Buffer) -> CVPixelBuffer? {
    let lumaWidth = source.width
    let lumaHeight = source.height
    
    let chromaWidth = source.width
    let chromaHeight = source.height / 2
    
    guard var lumaDestination = try? vImage_Buffer(
        width: Int(lumaWidth),
        height: Int(lumaHeight),
        bitsPerPixel: 8
    ) else {
        return nil
    }
    
    guard var chromaDestination = try? vImage_Buffer(
        width: Int(chromaWidth),
        height: Int(chromaHeight),
        bitsPerPixel: 8
    ) else {
        return nil
    }
    
    defer {
        lumaDestination.free()
        chromaDestination.free()
    }
    
    var error = kvImageNoError
    
    error = vImageConvert_ARGB8888To420Yp8_CbCr8(
        &source,
        &lumaDestination,
        &chromaDestination,
        &infoARGBtoYpCbCr,
        nil,
        vImage_Flags(kvImagePrintDiagnosticsToConsole)
    )
    
    guard error == kvImageNoError else {
        return nil
    }
    
    var pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
    var planeWidths = [Int(lumaWidth), Int(chromaWidth)]
    var planeHeights = [Int(chromaHeight), Int(chromaHeight)]
    var bytesPerRows = [Int(1 * lumaWidth), Int(2 * chromaWidth)]
    var baseAddresses: [UnsafeMutableRawPointer?] = [lumaDestination.data, chromaDestination.data]
    var outputPixelBuffer: CVPixelBuffer?
    
    let status = CVPixelBufferCreateWithPlanarBytes(
        kCFAllocatorDefault,
        Int(lumaWidth),
        Int(lumaHeight),
        pixelFormat,
        nil,
        0,
        2,
        &baseAddresses,
        &planeWidths,
        &planeHeights,
        &bytesPerRows,
        nil,
        nil,
        nil,
        &outputPixelBuffer
    )
    
    if status == noErr {
        print("converted to CVPixelBuffer")
    }
    return outputPixelBuffer
}

vImageConvert_ARGB8888To420Yp8_CbCr8生产两个缓冲器: Chroma和Luma。CVPixelBufferCreateWithPlanarBytes返回noErr状态,但是当查询时,Chroma和Luma数据不在缓冲区-平面地址是nil。知道我做错了什么吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-27 11:50:14

您需要锁定CVPixelBuffer以访问基址。因此,这是可行的:

代码语言:javascript
复制
    let cvPixelBuffer = convertTo420Yp8(source: vImageBuffer)!
    
    CVPixelBufferLockBaseAddress(cvPixelBuffer,
                                 CVPixelBufferLockFlags.readOnly)
    
    print(CVPixelBufferGetBaseAddressOfPlane(cvPixelBuffer, 0))
    print(CVPixelBufferGetBaseAddressOfPlane(cvPixelBuffer, 1))
    
    CVPixelBufferUnlockBaseAddress(cvPixelBuffer,
                                   CVPixelBufferLockFlags.readOnly)

我还建议您将您的bytesPerRow更改为:

代码语言:javascript
复制
var bytesPerRows = [lumaDestination.rowBytes, chromaDestination.rowBytes]

有时,vImage会在缓冲区中添加额外的填充以提高性能。

票数 0
EN

Stack Overflow用户

发布于 2022-09-27 18:28:41

对,CVPixelBuffer需要上锁。在我的代码中还有其他一些问题:

没有设置correctly

  • vImage_Buffer内存的
  • 平面的宽度和高度需要适当释放

本人现将工作守则张贴于此,以供参考:

代码语言:javascript
复制
func convertTo420Yp8(source: inout vImage_Buffer) -> CVPixelBuffer? {
    let lumaWidth = source.width
    let lumaHeight = source.height
    
    let chromaWidth = source.width
    let chromaHeight = source.height / 2
    
    guard var lumaDestination = try? vImage_Buffer(
        width: Int(lumaWidth),
        height: Int(lumaHeight),
        bitsPerPixel: 8
    ) else {
        return nil
    }
    
    guard var chromaDestination = try? vImage_Buffer(
        width: Int(chromaWidth),
        height: Int(chromaHeight),
        bitsPerPixel: 8
    ) else {
        return nil
    }
    
    var error = kvImageNoError
    
    error = vImageConvert_ARGB8888To420Yp8_CbCr8(
        &source,
        &lumaDestination,
        &chromaDestination,
        &infoARGBtoYpCbCr,
        nil,
        vImage_Flags(kvImagePrintDiagnosticsToConsole)
    )
    
    guard error == kvImageNoError else {
        return nil
    }
    
    var pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
    var planeWidths = [Int(lumaWidth), Int(chromaWidth)]
    var planeHeights = [Int(lumaHeight), Int(chromaHeight)]
    var bytesPerRows = [lumaDestination.rowBytes, chromaDestination.rowBytes]
    var baseAddresses: [UnsafeMutableRawPointer?] = [lumaDestination.data, chromaDestination.data]
    var outputPixelBuffer: CVPixelBuffer?
    
    let status = CVPixelBufferCreateWithPlanarBytes(
        kCFAllocatorDefault,
        Int(lumaWidth),
        Int(lumaHeight),
        pixelFormat,
        nil,
        0,
        2,
        &baseAddresses,
        &planeWidths,
        &planeHeights,
        &bytesPerRows,
        { releaseRefCon, dataPtr, dataSize, numberOfPlanes, planeAddresses  in
            planeAddresses?[0]?.deallocate()
            planeAddresses?[1]?.deallocate()
        },
        nil,
        nil,
        &outputPixelBuffer
    )
    if status == noErr {
        print("converted to CVPixelBuffer")
    }
    return outputPixelBuffer
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73863195

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档