如何从Swift中的UnsafeMutablePointer <UInt8>获取CVPixelBuffer句柄?

时间:2019-08-12 15:30:19

标签: swift ffmpeg video-toolbox

我得到了解码的 AVFrame ,其格式显示为160 / Videotoolbox_vld。在Google搜索了一些文章(here)并查看了 FFmpeg 源代码(herehere)之后,CVBuffer句柄应位于{ {1}}。但是我得到的AVFrame.data[3]似乎无效,任何CVBuffer函数都返回0或nil。

如果像ffmpeg的example/hw_decode.c一样使用CVPixelBufferGetXXX(),则可以将样本从硬件下载到软件缓冲区。其av_hwframe_transfer_data()将是AVFrame.format。通过nv12转换为sws_scale后,该示例可以正确的内容显示在视图上。

我认为VideoToolbox解码的帧还可以。我将bgra转换为AVFrame.data[3]的方式可能是错误的。刚刚学会了快速访问c指针,但是我不确定如何正确读取指针中的资源句柄(CVBuffer)。

以下是我尝试从AVFrame提取CVBuffer

CVBuffer

4 个答案:

答案 0 :(得分:0)

似乎我错误地将void*强制转换为CVPixelBuffer*,而不是直接将void*强制强制转换为CVPixelBuffer。我找不到从指针到数值的快速C样式转换方法。 (使用as! CVPixelBuffer会导致崩溃)。

因此,我使用C代码为void*CVPixelBufferRef创建了一个函数来完成这种转换工作。

// util.h
#include <CoreVideo/CVPixelBuffer.h>
CVPixelBufferRef CastToCVPixelBuffer(void* p);
// util.c
CVPixelBufferRef CastToCVPixelBuffer(void* p)
{
    return (CVPixelBufferRef)p;
}
// BridgeHeader.h
#include "util.h"

然后传入UnsafeMutablePointer<UInt8>,获取 CVPixelBuffer 句柄。

let pFrameOpt: UnsafeMutablePointer<AVFrame>? = ...
let data3: UnsafeMutablePointer<UInt8>? = pFrameOpt?.pointee.data.3

let cvBuf: CVBuffer = CastToCVPixelBuffer(data3).takeUnretainedValue()

let width = CVPixelBufferGetWidth(cvBuf)   // print 3840
let height = CVPixelBufferGetHeight(cvBuf) // print 2160

答案 1 :(得分:0)

尝试一下

let cvBuf: CVBuffer = Array(UnsafeMutableBufferPointer(start: data3, count: 3))
.withUnsafeBufferPointer {
   $0.baseAddress!.withMemoryRebound(to: CVBuffer.self, capacity: 1) { $0 }
}.pointee

甚至是

let cvBuf: CVBuffer = unsafeBitcast(UnsafeMutableBufferPointer(start: data3, count: 3), to: CVBuffer.self)

答案 2 :(得分:0)

CVBuffer的大小不是固定的,因此无法重新绑定内存。我相信Unmanaged<CVBuffer>.fromOpaque(data!).takeRetainedValue()是这种情况下的解决方法。

底线是FFmpeg的VideoToolbox后端未创建CVPixelBuffer设置为kCVPixelBufferMetalCompatibilityKey的{​​{1}}。在任何情况下,您都无法成功致电true

答案 3 :(得分:0)

/**
    @function   CVPixelBufferGetBaseAddressOfPlane
    @abstract   Returns the base address of the plane at planeIndex in the PixelBuffer.
    @discussion Retrieving the base address for a PixelBuffer requires that the buffer base address be locked
                via a successful call to CVPixelBufferLockBaseAddress. On OSX 10.10 and earlier, or iOS 8 and
                earlier, calling this function with a non-planar buffer will have undefined behavior.
    @param      pixelBuffer Target PixelBuffer.
    @param      planeIndex  Identifying the plane.
    @result     Base address of the plane, or NULL for non-planar CVPixelBufferRefs.
*/
@available(iOS 4.0, *)
public func CVPixelBufferGetBaseAddressOfPlane(_ pixelBuffer: CVPixelBuffer, _ planeIndex: Int) -> UnsafeMutableRawPointer?

也许你可以在使用 CVPixelBufferGetBaseAddressOfPlane 之前尝试使用 CVPixelBufferLockBaseAddress