Слить CAShapeLayer с CVPixelBuffer

Я записываю вывод воспроизводимого видео с помощью AVPlayerItemVideoOutput.copyPixelBuffer

Я могу преобразовать буфер пикселей в CIImage, затем снова отобразить его обратно в буфер пикселей, а затем AVAssetWriter успешно записывает поток буфера в новый фрагмент ролика.

Причина, по которой я конвертирую в CIImage, заключается в том, что я хочу поработать над каждым кадром. (Пока я не понимаю, как напрямую управлять пиксельными буферами).

В этом случае я хочу наложить рисунок в стиле каракулей, который пользователь делает пальцем. Во время воспроизведения видео они могут рисовать поверх него. Я успешно записываю этот рисунок в CAShapeLayer.

Приведенный ниже код успешно выводит только наложение CAShapeLayer. Когда я пытаюсь повторно включить исходный кадр, раскомментировав показанные строки, весь процесс резко замедляется и падает с 60 кадров в секунду до нестабильных 10 кадров в секунду или около того на iPhone 12. Я получаю стабильные 60 кадров в секунду во всех случаях, кроме тех случаев, когда я раскомментирую этот код.

Как лучше всего включить слой-фигуру в этот поток буферов пикселей со скоростью 60 кадров в секунду в реальном времени?

Примечание: часть этого кода не доработана - правильная установка границ и т. Д. Однако это не связано с моим вопросом, и я знаю, что это необходимо сделать. Вращение / перемещение используются для ориентации слоя формы - на данный момент все это работает.

func addShapesToBuffer(buffer: CVPixelBuffer, shapeLayer: CAShapeLayer) -> CVPixelBuffer? {
    let coreImage = CoreImage.CIImage.init(cvImageBuffer: buffer)
    let newBuffer = getBuffer(from: coreImage)
    CVPixelBufferLockBaseAddress(newBuffer!, [])

    let rect = CGRect(origin: CGPoint.zero, size: CGSize(width: 800, height: 390))
    
    shapeLayer.shouldRasterize = true
    shapeLayer.rasterizationScale = UIScreen.main.scale
    shapeLayer.backgroundColor = UIColor.clear.cgColor
    
    let renderer = UIGraphicsImageRenderer(size: rect.size)

    let uiImageDrawing = renderer.image {
        context in

//            let videoImage = UIImage(ciImage: coreImage)

//            videoImage.draw(in: rect)

        let cgContext = context.cgContext
        cgContext.rotate(by: deg2rad(-90))
        cgContext.translateBy(x: -390, y: 0)
        return shapeLayer.render(in: cgContext)
    }

    let ciContext = CIContext()
    let newImage = CIImage(cgImage: uiImageDrawing.cgImage!)
    ciContext.render(_: newImage, to: newBuffer!)
    

    CVPixelBufferUnlockBaseAddress(newBuffer!, [])
    
    return newBuffer

}

person Steve Macdonald    schedule 18.05.2021    source источник
comment
Я обнаружил, что UIGraphicsImageRenderer слишком медленный, попробуйте переписать без него. Также может происходить преобразование цветового пространства, экран iPhone имеет глубокие цвета.   -  person paiv    schedule 21.05.2021
comment
Проверьте этот пост - он о медленном UIImage.draw и предлагает вместо этого использовать CGImage. stackoverflow.com/a/7912531/921573   -  person de.    schedule 23.05.2021