Swift - 如何将 CVImageBufferRef 转换为 CVPixelBufferRef

Posted

技术标签:

【中文标题】Swift - 如何将 CVImageBufferRef 转换为 CVPixelBufferRef【英文标题】:Swift - How do you cast a CVImageBufferRef as a CVPixelBufferRef 【发布时间】:2014-06-24 15:08:09 【问题描述】:

在 Objective-c 中,您可以轻松地将 CVImageBufferRef 转换为 CVPixelBufferRef:

CMSampleBufferRef sampleBuffer = some value

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

我怎样才能快速做到这一点?


var pixelBuffer : CVPixelBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)

给出错误:'Unmanaged' 不能转换为 'CVPixelBufferRef'


var pixelBuffer : CVPixelBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer).takeRetainedValue()

给出错误:'CVImageBuffer' 不能转换为 'CVPixelBufferRef'


var pixelBuffer : CVPixelBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer).takeRetainedValue() as CVPixelBufferRef

给出错误:无法将表达式的类型“CVPixelBufferRef”转换为类型“CVPixelBufferRef”

【问题讨论】:

【参考方案1】:

编辑

这个答案是在 Swift beta 测试期间给出的。正如 klinger 所建议的那样,现在的解决方案似乎更简单了

var pixelBuffer : CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)

但是,出于历史原因,我将保留之前的答案 :-)

以前的答案

查看预发布文档:

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-XID_40

特别是这种说法

重新映射的类型

当 Swift 导入 Core Foundation 类型时,编译器会重新映射 这些类型的名称。编译器从每个末尾删除 Ref 类型名称,因为所有 Swift 类都是引用类型,因此 后缀是多余的。

Core Foundation CFTypeRef 类型完全重新映射到 AnyObject 类型。无论你在哪里使用 CFTypeRef,你现在都应该使用 AnyObject 在你的代码中。

您要做的第一件事是从每种类型中删除“ref”。 但是这不是必需的,因为“refs”被类型化为“non-ref”类型。

那么,这个语句应该有效。在我从未使用过CMSampleBufferGetImageBuffer 之前,它可能需要一些调整,因此我不确定第一行(初始化缓冲区)

    var buf : CMSampleBuffer = // initialize the buffer
    var anUnmanaged : Unmanaged<CVImageBuffer> = CMSampleBufferGetImageBuffer(buf)
    var returnValue = anUnmanaged.takeUnretainedValue()

或者,很快

    var buf : CMSampleBuffer = // initialize the buffer
    var anUnmanaged : CVImageBuffer = CMSampleBufferGetImageBuffer(buf).takeRetainedValue()

但是,您要求提供 CVPixelBuffer。 如果这两种类型完全兼容(我不知道底层 API,所以我假设 objc 中的 CVPixelBuffer 和 CVImageBuffer 之间的转换总是安全的),没有“自动化”来做到这一点,你必须通过一个 Unsafe Pointer .

完整的代码是这样的:

    var buf : CMSampleBuffer = // initialize the buffer
    var anUnmanaged : Unmanaged<CVImageBuffer> = CMSampleBufferGetImageBuffer(buf)
    var returnValue = anUnmanaged.takeUnretainedValue()

    var anOpaque = anUnmanaged.toOpaque()
    var pixelBuffer : CVPixelBuffer = Unmanaged<CVPixelBuffer>.fromOpaque(anOpaque).takeUnretainedValue()

我使用了不消耗保留计数的 takeUnretainedValue(),因为 CMSampleBufferGetImageBuffer() 返回一个未保留的对象

【讨论】:

谢谢!在 Objective-c 中,CVImageBufferRef 是 CVPixelBufferRef 的同义词,所以这让我发疯了。 在这种情况下,我建议您提交一个错误功能请求以在未来的版本中进行自动转换:-) 我不排除有一些功能可以在隐藏的两种类型之间架起桥梁在某个地方,但是通过一个不透明的指针是我想到的第一个解决方案:-)【参考方案2】:

在 Xcode 6 beta 6 中,这终于可以工作了:

var pixelBuffer : CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)

【讨论】:

【参考方案3】:

@LombaX 的解决方案在最新版本 Xcode Beta5 中对我不起作用。以下是有效的方法:

let imageBuffer : CVImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
let srcPtr = Unmanaged.passUnretained(imageBuffer).toOpaque()
let pixelBuffer = Unmanaged<CVPixelBuffer>.fromOpaque(srcPtr).takeUnretainedValue()

【讨论】:

以上是关于Swift - 如何将 CVImageBufferRef 转换为 CVPixelBufferRef的主要内容,如果未能解决你的问题,请参考以下文章

300x300像素Png图像到字节数组

如何将 swift 对象传递给 javascript (WKWebView / swift)

swift 如何将Swift 3内置的cocoapod更新为Swift 4

如何将以下代码从 Swift 2 转换为 Swift 5?

Swift:如何将字符串放入 \()? [复制]

Swift:如何将 MapView 放入 UIView(?)