像素缓冲区不会附加到设备上的AVAssetWriterInput

时间:2015-02-01 09:17:49

标签: ios swift avfoundation

我试图拍摄一张图片并将其转换为Swift中的视频文件。我能够让代码在iOS模拟器中工作,但它不能在实际设备上工作。当我尝试将像素缓冲区附加到AVAssetWriterInput时,它会出错。我想知道这里是否有人遇到过同样的问题。这是代码:

func createVideoFromImage(img: CGImageRef) -> Void {

    var error: NSError?
    let frameSize = CGSizeMake(CGFloat(CGImageGetWidth(img)), CGFloat(CGImageGetHeight(img)))

    let fileName = "\(uniqueString()).m4v"
    let assetWriter = AVAssetWriter(URL: fileUrl(fileName), fileType: AVFileTypeAppleM4V, error: &error)

    let outputSettings = [
        AVVideoCodecKey: AVVideoCodecH264,
        AVVideoWidthKey: frameSize.width,
        AVVideoHeightKey: frameSize.height
    ]

    let assetWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: outputSettings)

    let pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: assetWriterInput, sourcePixelBufferAttributes: nil)

    if assetWriter.canAddInput(assetWriterInput) {
        assetWriter.addInput(assetWriterInput)
    }

    assetWriter.startWriting()
    assetWriter.startSessionAtSourceTime(kCMTimeZero)

    let buffer:CVPixelBufferRef = pixelBufferFromCGImage(img, frameSize: frameSize)

    if pixelBufferAdaptor.assetWriterInput.readyForMoreMediaData {
        let frameTime = CMTimeMakeWithSeconds(0, 30)
        let pixelBufferAppend = pixelBufferAdaptor.appendPixelBuffer(buffer, withPresentationTime: frameTime)

        if pixelBufferAppend {
            assetWriterInput.markAsFinished()

            assetWriter.finishWritingWithCompletionHandler { () -> Void in
                switch assetWriter.status {
                case AVAssetWriterStatus.Failed:
                    println("Error: \(assetWriter.error)")
                default:
                    let path = self.fileUrl(fileName).path!
                    let content = NSFileManager.defaultManager().contentsAtPath(path)
                    println("Video: \(path) \(content?.length)")
                }
            }
        } else {
            println("failed to append pixel buffer")
        }
    }


}

func pixelBufferFromCGImage (img: CGImageRef, frameSize: CGSize) -> CVPixelBufferRef {

    let options = [
        "kCVPixelBufferCGImageCompatibilityKey": true,
        "kCVPixelBufferCGBitmapContextCompatibilityKey": true
    ]

    var pixelBufferPointer = UnsafeMutablePointer<Unmanaged<CVPixelBuffer>?>.alloc(1)

    let buffered:CVReturn = CVPixelBufferCreate(kCFAllocatorDefault, UInt(frameSize.width), UInt(frameSize.height), OSType(kCVPixelFormatType_32ARGB), options, pixelBufferPointer)

    let lockBaseAddress = CVPixelBufferLockBaseAddress(pixelBufferPointer.memory?.takeUnretainedValue(), 0)
    var pixelData:UnsafeMutablePointer<(Void)> = CVPixelBufferGetBaseAddress(pixelBufferPointer.memory?.takeUnretainedValue())

    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipFirst.rawValue)
    let space:CGColorSpace = CGColorSpaceCreateDeviceRGB()

    var context:CGContextRef = CGBitmapContextCreate(pixelData, UInt(frameSize.width), UInt(frameSize.height), 8, CVPixelBufferGetBytesPerRow(pixelBufferPointer.memory?.takeUnretainedValue()), space, bitmapInfo)

    CGContextDrawImage(context, CGRectMake(0, 0, frameSize.width, frameSize.height), img)

    CVPixelBufferUnlockBaseAddress(pixelBufferPointer.memory?.takeUnretainedValue(), 0)

    return pixelBufferPointer.memory!.takeUnretainedValue()
}

pixelBufferAppend返回false!任何帮助将不胜感激。我整夜都在摸不着头脑!

1 个答案:

答案 0 :(得分:0)

我终于能够知道发生了什么。该设备只能支持高达1920x1080px的编码帧 - 缩小图像大小并且工作正常。将frameSize更改为变量并使用以下代码:

if frameSize.width > maxImageSize.width || frameSize.height > maxImageSize.height {
    let scale = min((maxImageSize.width/frameSize.width), (maxImageSize.height/frameSize.height))
    frameSize = CGSizeMake((scale * frameSize.width), (scale * frameSize.height))
}