1

I have a UIImage array with a lot of UIImage objects,and use the methods mentioned by the link to export the image array to a video. Everything works, but the performance of converting UIImage array to CVPixelBuffer is very terrible:

    private func newPixelBufferFrom(cgImage:CGImage) -> CVPixelBuffer?{
    let options:[String: Any] = [kCVPixelBufferCGImageCompatibilityKey as String: true, kCVPixelBufferCGBitmapContextCompatibilityKey as String: true]
    var pxbuffer:CVPixelBuffer?
    let frameWidth = self.videoSettings[AVVideoWidthKey] as! Int
    let frameHeight = self.videoSettings[AVVideoHeightKey] as! Int

    let status = CVPixelBufferCreate(kCFAllocatorDefault, frameWidth, frameHeight, kCVPixelFormatType_32ARGB, options as CFDictionary?, &pxbuffer)
    assert(status == kCVReturnSuccess && pxbuffer != nil, "newPixelBuffer failed")


    CVPixelBufferLockBaseAddress(pxbuffer!, CVPixelBufferLockFlags(rawValue: 0))
    let pxdata = CVPixelBufferGetBaseAddress(pxbuffer!)
    let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
    let context = CGContext(data: pxdata, width: frameWidth, height: frameHeight, bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pxbuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)
    assert(context != nil, "context is nil")

    context!.concatenate(CGAffineTransform.identity)
    context!.draw(cgImage, in: CGRect(x: 0, y: 0, width: frameWidth, height: frameHeight))
    CVPixelBufferUnlockBaseAddress(pxbuffer!, CVPixelBufferLockFlags(rawValue: 0))
    return pxbuffer
}

enter image description here Could you give me some ideas?
Thanks!

Community
  • 1
  • 1
leon wu
  • 315
  • 3
  • 10

1 Answers1

1

I solved my problem.
In my video editing application like iMovie, I need to convert one image to a video and make the image(now it's a video) is movable.
A UIImage array is from a UIImage in essence. Therefore, I avoid call newPixelBufferFrom repeatedly but only once. the following codes will be faster:

    var sampleBuffer:CVPixelBuffer?
    var pxDataBuffer:CVPixelBuffer?

    let options:[String: Any] = [kCVPixelBufferCGImageCompatibilityKey as String: true, kCVPixelBufferCGBitmapContextCompatibilityKey as String: true]
    let frameHeight = self.videoSettings[AVVideoHeightKey] as! Int
    let frameWidth = self.videoSettings[AVVideoWidthKey] as! Int
    let originHeight = frameWidth * img!.cgImage!.height / img!.cgImage!.width
    let heightDifference = originHeight - frameHeight

    let frameCounts = self.duration * Int(self.frameTime.timescale)
    let spacingOfHeight = heightDifference / frameCounts

    sampleBuffer = self.newPixelBufferFrom(cgImage: img!.cgImage!)
    assert(sampleBuffer != nil)

    var presentTime = CMTimeMake(1, self.frameTime.timescale)
    var stepRows = 0

    for i in 0..<frameCounts {
        CVPixelBufferLockBaseAddress(sampleBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        let pointer = CVPixelBufferGetBaseAddress(sampleBuffer!)
        var pxData = pointer?.assumingMemoryBound(to: UInt8.self)
        let bytes = CVPixelBufferGetBytesPerRow(sampleBuffer!) * stepRows
        pxData = pxData?.advanced(by: bytes)

        let status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, frameWidth, frameHeight, kCVPixelFormatType_32ARGB, pxData!, CVPixelBufferGetBytesPerRow(sampleBuffer!), nil, nil, options as CFDictionary?, &pxDataBuffer)
        assert(status == kCVReturnSuccess && pxDataBuffer != nil, "newPixelBuffer failed")
        CVPixelBufferUnlockBaseAddress(sampleBuffer!, CVPixelBufferLockFlags(rawValue: 0))

        while !self.writeInput.isReadyForMoreMediaData {
            usleep(100)
        }
        if (self.writeInput.isReadyForMoreMediaData){
            if i == 0{
                self.bufferAdapter.append(pxDataBuffer!, withPresentationTime: zeroTime)
            }else{
                self.bufferAdapter.append(pxDataBuffer!, withPresentationTime: presentTime)
            }
            presentTime = CMTimeAdd(presentTime, self.frameTime)
        }

        stepRows += spacingOfHeight
    }
leon wu
  • 315
  • 3
  • 10
  • For that there exists [CVPixelBufferPool](https://developer.apple.com/documentation/corevideo/cvpixelbufferpool-77o) – a utility object for managing a recyclable set of pixel buffer objects. – Ian Bytchek May 07 '19 at 03:30