我已经用
Swift(
How to use CVPixelBufferPool in conjunction with AVAssetWriterInputPixelBufferAdaptor in iPhone?)实现了以前的建议,
但在使用CVPixelBufferPoolCreatePixelBuffer作为指导时,却遇到了“kCVReturnInvalidArgument”(错误值:-6661).
但在使用CVPixelBufferPoolCreatePixelBuffer作为指导时,却遇到了“kCVReturnInvalidArgument”(错误值:-6661).
我基本上试图从图像创建一个电影,但由于缓冲池未成功创建,我无法附加像素缓冲区 – 这是我执行此操作的代码.
任何建议都非常感谢!
- import Foundation
- import Photos
- import OpenGLES
- import AVFoundation
- import CoreMedia
- class MovieGenerator {
- var _videoWriter:AVAssetWriter
- var _videoWriterInput: AVAssetWriterInput
- var _adapter: AVAssetWriterInputPixelBufferAdaptor
- var _buffer = UnsafeMutablePointer<Unmanaged<CVPixelBuffer>?>.alloc(1)
- init(frameSize size: CGSize,outputURL url: NSURL) {
- // delete file if exists
- let sharedManager = NSFileManager.defaultManager() as NSFileManager
- if(sharedManager.fileExistsAtPath(url.path!)) {
- sharedManager.removeItemAtPath(url.path,error: nil)
- }
- // video writer
- _videoWriter = AVAssetWriter(URL: url,fileType: AVFileTypeQuickTimeMovie,error: nil)
- // writer input
- var videoSettings = [AVVideoCodecKey:AVVideoCodecH264,AVVideoWidthKey:size.width,AVVideoHeightKey:size.height]
- _videoWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo,outputSettings: videoSettings)
- _videoWriterInput.expectsMediaDataInRealTime = true
- _videoWriter.addInput(_videoWriterInput)
- // pixel buffer adapter
- var adapterAttributes = [kCVPixelBufferPixelFormatTypeKey:kCVPixelFormatType_32BGRA,kCVPixelBufferWidthKey: size.width,kCVPixelBufferHeightKey: size.height,kCVPixelFormatOpenGLESCompatibility: kcfBooleanTrue]
- _adapter = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: _videoWriterInput,sourcePixelBufferAttributes: adapterAttributes)
- var poolCreateResult:CVReturn = CVPixelBufferPoolCreatePixelBuffer(nil,_adapter.pixelBufferPool,_buffer)
- println("pool creation:\(poolCreateResult)")
- _videoWriter.startWriting()
- _videoWriter.startSessionAtSourceTime(kCMTimeZero)
- }
- func addImage(image:UIImage,frameNum:Int,fps:Int)->Bool {
- self.createPixelBufferFromCGImage(image.CGImage,pixelBufferPtr: _buffer)
- var presentTime:CMTime = CMTimeMake(Int64(frameNum),Int32(fps))
- var result:Bool = _adapter.appendPixelBuffer(_buffer.memory?.takeUnretainedValue(),withPresentationTime: presentTime)
- return result
- }
- func finalizeMovie(timeStamp: CMTime) {
- _videoWriterInput.markAsFinished()
- _videoWriter.endSessionAtSourceTime(timeStamp)
- _videoWriter.finishWritingWithCompletionHandler({println("video writer finished with status: \(self._videoWriter.status)")})
- }
- func createPixelBufferFromCGImage(image: CGImage,pixelBufferPtr: UnsafeMutablePointer<Unmanaged<CVPixelBuffer>?>) {
- let width:UInt = CGImageGetWidth(image)
- let height:UInt = CGImageGetHeight(image)
- let imageData:CFData = CGDataProviderCopyData(CGImageGetDataProvider(image))
- let options:CFDictionary = [kCVPixelBufferCGImageCompatibilityKey:NSNumber.numberWithBool(true),kCVPixelBufferCGBitmapContextCompatibilityKey:NSNumber.numberWithBool(true)]
- var status:CVReturn = CVPixelBufferCreate(kcfAllocatorDefault,width,height,OSType(kCVPixelFormatType_32BGRA),options,pixelBufferPtr)
- assert(status != 0,"CVPixelBufferCreate: \(status)")
- var lockStatus:CVReturn = CVPixelBufferLockBaseAddress(pixelBufferPtr.memory?.takeUnretainedValue(),0)
- println("CVPixelBufferLockBaseAddress: \(lockStatus)")
- var pxData:UnsafeMutablePointer<(Void)> = CVPixelBufferGetBaseAddress(pixelBufferPtr.memory?.takeUnretainedValue())
- let bitmapinfo = CGBitmapInfo.fromRaw(CGImageAlphaInfo.NoneSkipFirst.toRaw())
- let rgbColorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB()
- var context:CGContextRef = CGBitmapContextCreate(pxData,8,4*CGImageGetWidth(image),rgbColorSpace,bitmapinfo!)
- CGContextDrawImage(context,CGRectMake(0,CGFloat(width),CGFloat(height)),image)
- CVPixelBufferUnlockBaseAddress(pixelBufferPtr.memory?.takeUnretainedValue(),0)
- }
- }
令人沮丧的是,我无法准确回答你的问题,但我正在研究基本相同的代码.并且,我的情况恰好比你得到的错误更进一步;它一直到试图将图像添加到电影中然后因为从未从appendPixelBuffer()获得成功结果而失败 – 我不知道如何找出原因.我发布这篇文章是为了帮助你进一步发展.
(我的代码改编自AVFoundation + AssetWriter: Generate Movie With Images and Audio,我用你的帖子来帮助浏览指针互操作的somanigans …)
- func writeAnimationToMovie(path: String,size: CGSize,animation: Animation) -> Bool {
- var error: NSError?
- let writer = AVAssetWriter(URL: NSURL(fileURLWithPath: path),error: &error)
- let videoSettings = [AVVideoCodecKey: AVVideoCodecH264,AVVideoWidthKey: size.width,AVVideoHeightKey: size.height]
- let input = AVAssetWriterInput(mediaType: AVMediaTypeVideo,outputSettings: videoSettings)
- let pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: input,sourcePixelBufferAttributes: nil)
- input.expectsMediaDataInRealTime = true
- writer.addInput(input)
- writer.startWriting()
- writer.startSessionAtSourceTime(kCMTimeZero)
- var buffer: CVPixelBufferRef
- var frameCount = 0
- for frame in animation.frames {
- let rect = CGRectMake(0,size.width,size.height)
- let rectPtr = UnsafeMutablePointer<CGRect>.alloc(1)
- rectPtr.memory = rect
- buffer = pixelBufferFromCGImage(frame.image.CGImageForProposedRect(rectPtr,context: nil,hints: nil).takeUnretainedValue(),size)
- var appendOk = false
- var j = 0
- while (!appendOk && j < 30) {
- if pixelBufferAdaptor.assetWriterInput.readyForMoreMediaData {
- let frameTime = CMTimeMake(Int64(frameCount),10)
- appendOk = pixelBufferAdaptor.appendPixelBuffer(buffer,withPresentationTime: frameTime)
- // appendOk will always be false
- NSThread.sleepForTimeInterval(0.05)
- } else {
- NSThread.sleepForTimeInterval(0.1)
- }
- j++
- }
- if (!appendOk) {
- println("Doh,frame \(frame) at offset \(frameCount) Failed to append")
- }
- }
- input.markAsFinished()
- writer.finishWritingWithCompletionHandler({
- if writer.status == AVAssetWriterStatus.Failed {
- println("oh noes,an error: \(writer.error.description)")
- } else {
- println("hrmmm,there should be a movie?")
- }
- })
- return true;
- }
其中pixelBufferFromCGImage的定义如下:
- func pixelBufferFromCGImage(image: CGImageRef,size: CGSize) -> CVPixelBufferRef {
- let options = [
- kCVPixelBufferCGImageCompatibilityKey: true,kCVPixelBufferCGBitmapContextCompatibilityKey: true]
- var pixBufferPointer = UnsafeMutablePointer<Unmanaged<CVPixelBuffer>?>.alloc(1)
- let status = CVPixelBufferCreate(
- nil,UInt(size.width),UInt(size.height),OSType(kCVPixelFormatType_32ARGB),pixBufferPointer)
- CVPixelBufferLockBaseAddress(pixBufferPointer.memory?.takeUnretainedValue(),0)
- let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
- let bitmapinfo = CGBitmapInfo.fromRaw(CGImageAlphaInfo.NoneSkipFirst.toRaw())
- var pixBufferData:UnsafeMutablePointer<(Void)> = CVPixelBufferGetBaseAddress(pixBufferPointer.memory?.takeUnretainedValue())
- let context = CGBitmapContextCreate(
- pixBufferData,UInt(4 * size.width),bitmapinfo!)
- CGContextConcatCTM(context,CGAffineTransformMakeRotation(0))
- CGContextDrawImage(
- context,CGFloat(CGImageGetWidth(image)),CGFloat(CGImageGetHeight(image))),image)
- CVPixelBufferUnlockBaseAddress(pixBufferPointer.memory?.takeUnretainedValue(),0)
- return pixBufferPointer.memory!.takeUnretainedValue()
- }