我正在转换相机输出420YpCbCr8BiPlanarFullRange到ARGB8888以便执行一些图像处理。我需要将结果转换回420YpCbCr8BiPlanarFullRange,以将其与webRTC进行流:
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。知道我做错了什么吗?
发布于 2022-09-27 11:50:14
您需要锁定CVPixelBuffer以访问基址。因此,这是可行的:
let cvPixelBuffer = convertTo420Yp8(source: vImageBuffer)!
CVPixelBufferLockBaseAddress(cvPixelBuffer,
CVPixelBufferLockFlags.readOnly)
print(CVPixelBufferGetBaseAddressOfPlane(cvPixelBuffer, 0))
print(CVPixelBufferGetBaseAddressOfPlane(cvPixelBuffer, 1))
CVPixelBufferUnlockBaseAddress(cvPixelBuffer,
CVPixelBufferLockFlags.readOnly)我还建议您将您的bytesPerRow更改为:
var bytesPerRows = [lumaDestination.rowBytes, chromaDestination.rowBytes]有时,vImage会在缓冲区中添加额外的填充以提高性能。
发布于 2022-09-27 18:28:41
对,CVPixelBuffer需要上锁。在我的代码中还有其他一些问题:
没有设置correctly
vImage_Buffer内存的本人现将工作守则张贴于此,以供参考:
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
}https://stackoverflow.com/questions/73863195
复制相似问题