Skip to content

Instantly share code, notes, and snippets.

@shalyf
Created July 17, 2018 12:44
Show Gist options
  • Save shalyf/a001492d364954aaa3f6dbc3d04b81a5 to your computer and use it in GitHub Desktop.
Save shalyf/a001492d364954aaa3f6dbc3d04b81a5 to your computer and use it in GitHub Desktop.
CVPixelBuffer转Data,以及Data转CVPixelBuffer
func getData(from pixelBuffer: CVPixelBuffer) -> Data {
//TODO:可以通过CVPixelBufferGetPlaneCount判断一下pixelBuffer是否有两个Plane
CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
let pixelFormatType = CVPixelBufferGetPixelFormatType(pixelBuffer)
let width = CVPixelBufferGetWidth(pixelBuffer)
let height = CVPixelBufferGetHeight(pixelBuffer)
var data = Data()
let yBaseAddress = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0)
let yBytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0)
let yLength = yBytesPerRow * height
data.append(Data(bytes: yBaseAddress!, count: yLength))
let cbcrBaseAddress = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1)
let cbcrBytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1)
let cbcrLength = cbcrBytesPerRow * height / 2
data.append(Data(bytes: cbcrBaseAddress!, count: cbcrLength))
CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
return data
}
func configPixelBufferPool() -> Bool {
let attributes: [CFString: Any] = [
kCVPixelBufferPixelFormatTypeKey: pixelFormatType,
kCVPixelBufferWidthKey: width,
kCVPixelBufferHeightKey: height,
kCVPixelBufferBytesPerRowAlignmentKey: yBytesPerRow
]
let status = CVPixelBufferPoolCreate(kCFAllocatorDefault, nil, attributes as CFDictionary, &pixelBufferPool)
return status == kCVReturnSuccess
}
func getPixelBuffer(from data: Data) -> CVPixelBuffer? {
guard data.count == yLength + cbcrLength,
let pixelBufferPool = pixelBufferPool else { return nil }
var _pixelBuffer: CVPixelBuffer?
//用CVPixelBufferPoolCreatePixelBuffer创建CVPixelBuffer会更快一些
let status = CVPixelBufferPoolCreatePixelBuffer(nil, pixelBufferPool, &_pixelBuffer)
guard status == kCVReturnSuccess, let pixelBuffer = _pixelBuffer else {
print("CVPixelBufferPoolCreatePixelBuffer error")
return nil
}
//把data转换为指针,用指针进行memcpy操作,比用subdata快上百倍
let srcPtr = data.withUnsafeBytes({ UnsafeRawPointer($0) })
CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
let yBaseAddress = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0)
memcpy(yBaseAddress, srcPtr, yLength)
let cbcrBaseAddress = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1)
memcpy(cbcrBaseAddress, srcPtr.advanced(by: yLength), cbcrLength)
CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
return pixelBuffer
}
@LucasDang
Copy link

Got it!

@LucasDang
Copy link

将 data 转成 CVPixelBuffer 的时候为什么还需要 CVPixelBuffer 的信息呢?这个 yLength 和 cbcrLength 你是怎么存储的,与CVPixelBuffer生成的Data绑定在一起么?

@shalyf
Copy link
Author

shalyf commented Aug 8, 2020

有这些信息才知道怎么把data还原成CVPixelBuffer,我写了一个struct用来存储length等信息,这些信息可以从getData中获取

@LucasDang
Copy link

LucasDang commented Aug 8, 2020

谢谢回复。
我目前需要将 从Broadcast Upload Extension中获取到的CVPixelBuffer数据通过socket传递给主项目,想问下CVPixelBuffer有什么压缩的好方法么?

@shalyf
Copy link
Author

shalyf commented Aug 8, 2020

Broadcast Upload Extension出的图像好像是yuv420的,再压缩颜色就要失真了,转成data通过socket传给主程序就行了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment