import AVFoundation import MetalKit final class SampleConverter { private var textureCache: CVMetalTextureCache? private let pixelFormat: MTLPixelFormat init?(device: MTLDevice, pixelFormat: MTLPixelFormat) { guard CVMetalTextureCacheCreate(nil, nil, device, nil, &textureCache) == kCVReturnSuccess, textureCache != nil else { return nil } self.pixelFormat = pixelFormat } func convert(sample: CMSampleBuffer) -> MTLTexture? { guard let cvImageBuffer = CMSampleBufferGetImageBuffer(sample), let textureCache = textureCache else { return nil } let width = CVPixelBufferGetWidth(cvImageBuffer) let height = CVPixelBufferGetHeight(cvImageBuffer) var textureOptional: CVMetalTexture? let createResult = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache, cvImageBuffer, nil, pixelFormat, width, height, 0, &textureOptional) guard createResult == kCVReturnSuccess, let texture = textureOptional, let resultTexture = CVMetalTextureGetTexture(texture) else { return nil } return resultTexture } }