2017-02-23 115 views
0

我有一个UIImage阵列与很多UIImage对象,并使用link提到的方法将图像数组导出到视频。一切正常,但UIImage数组转换为CVPixelBuffer的性能是非常可怕的:如何提高将UIImage转换为CVPixelBuffer的性能?

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 你能不能给我一些想法?
谢谢!

回答

0

我解决了我的问题。
在我的视频编辑应用程序,如iMovie,我需要将一个图像转换为视频,并使图像(现在它是一个视频)是可移动的。
A UIImage数组本质上来自UIImage。因此,我避免重复拨打newPixelBufferFrom,但只能拨打一次。以下代码将更快:

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 
    }