Skip to content

Instantly share code, notes, and snippets.

@standinga
Created December 31, 2019 04:38
Show Gist options
  • Save standinga/2a7d0998c99131b6ca30cdd9adf35b76 to your computer and use it in GitHub Desktop.
Save standinga/2a7d0998c99131b6ca30cdd9adf35b76 to your computer and use it in GitHub Desktop.
Deep Copying of CMSampleBuffer and CVPixelBuffer
//
// CVPixelBuffer+CMSampleBuffer+Copy.swift
// VideoDelaySwift
//
// Created by michal on 16/07/2019.
// Copyright © 2019 michal. All rights reserved.
//
import AVFoundation
extension CMSampleBuffer {
var deepCopy: CMSampleBuffer {
#if targetEnvironment(simulator)
return self
#else
guard let pixelBuffer = CMSampleBufferGetImageBuffer(self) else {
fatalError("can't get pixelBuffer \(#line)")
}
guard let formatDescription = CMSampleBufferGetFormatDescription(self) else {
fatalError("can't get formatDescription \(#line)")
}
let copiedBuffer = pixelBuffer.deepCopy
var sampleTiming = CMSampleTimingInfo(duration: .invalid, presentationTimeStamp: .invalid, decodeTimeStamp: .invalid)
var sampleBufferCopy: CMSampleBuffer?
let match = CMVideoFormatDescriptionMatchesImageBuffer(formatDescription, imageBuffer: copiedBuffer)
let _ = CMVideoFormatDescriptionGetExtensionKeysCommonWithImageBuffers()
precondition(match, "doesn't match \(formatDescription)")
CMSampleBufferGetSampleTimingInfo(self, at: 0, timingInfoOut: &sampleTiming)
let status = CMSampleBufferCreateReadyWithImageBuffer(
allocator: kCFAllocatorDefault,
imageBuffer: copiedBuffer,
formatDescription: formatDescription,
sampleTiming: &sampleTiming,
sampleBufferOut: &sampleBufferCopy)
precondition(status == 0, "CMSampleBufferCreateReadyWithImageBuffer failed \(status) at \(#line)")
guard let buffer = sampleBufferCopy else {
fatalError("could not copy buffer \(#line)")
}
return buffer
#endif
}
}
extension CVPixelBuffer {
var deepCopy: CVPixelBuffer {
CVPixelBufferLockBaseAddress(self, [])
let width = CVPixelBufferGetWidth(self)
let height = CVPixelBufferGetHeight(self)
let baseAddress = CVPixelBufferGetBaseAddressOfPlane(self, 0)
var bufferToCopy: CVPixelBuffer?
let pixelBufferAttributes = [kCVPixelBufferIOSurfacePropertiesKey: [:] as AnyObject]
let status = CVPixelBufferCreate(kCFAllocatorDefault,
width,
height,
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
pixelBufferAttributes as CFDictionary?,
&bufferToCopy)
precondition(status == 0, "failed creating pixelbuffer \(status) at \(#line)")
guard let bufferCopy = bufferToCopy else {
fatalError("bufferCopy nil \(#line)")
}
CVPixelBufferLockBaseAddress(bufferCopy, [])
CVBufferPropagateAttachments(self, bufferCopy)
let copyBaseAddress = CVPixelBufferGetBaseAddressOfPlane(bufferCopy, 0)
let size = CVPixelBufferGetDataSize(bufferCopy)
memcpy(copyBaseAddress, baseAddress, size)
CVPixelBufferUnlockBaseAddress(bufferCopy, [])
CVPixelBufferUnlockBaseAddress(self, [])
return bufferCopy
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment