我得到了解码的 AVFrame ,其格式显示为160 / Videotoolbox_vld
。在Google搜索了一些文章(here)并查看了 FFmpeg 源代码(here和here)之后,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
答案 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