Last active
November 7, 2023 15:29
-
-
Save T1T4N/0ae90716b0c5d1bea39efe94512e1b72 to your computer and use it in GitHub Desktop.
A format-agnostic way of converting CVPixelBuffer to Data and back
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension CVPixelBuffer { | |
public static func from(_ data: Data, width: Int, height: Int, pixelFormat: OSType) -> CVPixelBuffer { | |
data.withUnsafeBytes { buffer in | |
var pixelBuffer: CVPixelBuffer! | |
let result = CVPixelBufferCreate(kCFAllocatorDefault, width, height, pixelFormat, nil, &pixelBuffer) | |
guard result == kCVReturnSuccess else { fatalError() } | |
CVPixelBufferLockBaseAddress(pixelBuffer, []) | |
defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, []) } | |
var source = buffer.baseAddress! | |
for plane in 0 ..< CVPixelBufferGetPlaneCount(pixelBuffer) { | |
let dest = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, plane) | |
let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, plane) | |
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, plane) | |
let planeSize = height * bytesPerRow | |
memcpy(dest, source, planeSize) | |
source += planeSize | |
} | |
return pixelBuffer | |
} | |
} | |
} | |
extension Data { | |
public static func from(pixelBuffer: CVPixelBuffer) -> Self { | |
CVPixelBufferLockBaseAddress(pixelBuffer, [.readOnly]) | |
defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, [.readOnly]) } | |
// Calculate sum of planes' size | |
var totalSize = 0 | |
for plane in 0 ..< CVPixelBufferGetPlaneCount(pixelBuffer) { | |
let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, plane) | |
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, plane) | |
let planeSize = height * bytesPerRow | |
totalSize += planeSize | |
} | |
guard let rawFrame = malloc(totalSize) else { fatalError() } | |
var dest = rawFrame | |
for plane in 0 ..< CVPixelBufferGetPlaneCount(pixelBuffer) { | |
let source = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, plane) | |
let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, plane) | |
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, plane) | |
let planeSize = height * bytesPerRow | |
memcpy(dest, source, planeSize) | |
dest += planeSize | |
} | |
return Data(bytesNoCopy: rawFrame, count: totalSize, deallocator: .free) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
great but at #14
seems won't enter