CMSampleBuffer在Swift 3中从纵向旋转到横向

时间:2017-09-23 13:39:32

标签: ios cgaffinetransform cifilter ciimage cmsamplebuffer

我在iOS中处理ReplayKit2,由于某些原因我需要将CMSampleBuffer从纵向旋转到横向,我发现结果不正确。

我想念的是什么?

这是原始样本缓冲区enter image description here

这是实际输出缓冲区enter image description here

  

宽度& height是sampleBuffer的维度

func rotation(sampleBuffer: CMSampleBuffer, width: Int, height: Int) -> CMSampleBuffer {

        //create pixelbuffer from the delegate method samplebuffer
        let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!

        CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))

        //create CI image from the buffer
        let image = CIImage(cvImageBuffer: pixelBuffer)

        let extent = CGRect(x: 0, y: 0, width: width, height: height)

        var tx = CGAffineTransform(translationX: extent.midX, y: extent.midY)

        tx = tx.rotated(by: CGFloat(Double.pi / 2))

        tx = tx.translatedBy(x: -extent.midX, y: -extent.midY)

        var transformImage = CIFilter(
            name: "CIAffineTransform",
            withInputParameters: [
                kCIInputImageKey: image,
                kCIInputTransformKey: NSValue.init(cgAffineTransform: tx)])!.outputImage!

        //create empty pixelbuffer
        var newPixelBuffer : CVPixelBuffer? = nil

        CVPixelBufferCreate(kCFAllocatorDefault,
                            width,
                            height,
                            kCVPixelFormatType_32BGRA,
                            nil,
                            &newPixelBuffer)
        //render the context to the new pixelbuffer, context is a global
        //CIContext variable. creating a new one each frame is too CPU intensive
        self.ciContext.render(transformImage, to: newPixelBuffer!)

        //finally, write this to the pixelbufferadaptor

        CVPixelBufferUnlockBaseAddress(pixelBuffer,CVPixelBufferLockFlags(rawValue: 0))

        var videoInfo: CMVideoFormatDescription?

        CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, newPixelBuffer!, &videoInfo)

        var sampleTimingInfo = CMSampleTimingInfo(duration: CMSampleBufferGetDuration(sampleBuffer), presentationTimeStamp: CMSampleBufferGetPresentationTimeStamp(sampleBuffer), decodeTimeStamp: CMSampleBufferGetDecodeTimeStamp(sampleBuffer))

        var newSampleBuffer: CMSampleBuffer?

        CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, newPixelBuffer!, true, nil, nil, videoInfo!, &sampleTimingInfo, &newSampleBuffer)

        return newSampleBuffer!

    }

2 个答案:

答案 0 :(得分:2)

刚刚在iOS 11中找到了一个非常甜蜜的方法!

/* Returns a new image representing the original image transformeded for the given CGImagePropertyOrientation */
    @available(iOS 11.0, *)
    open func oriented(_ orientation: CGImagePropertyOrientation) -> CIImage

答案 1 :(得分:0)

也许会有用

func rotate(_ sampleBuffer: CMSampleBuffer) -> CVPixelBuffer? {
        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return nil
        }
        var newPixelBuffer: CVPixelBuffer?
        let error = CVPixelBufferCreate(kCFAllocatorDefault,
                                        CVPixelBufferGetHeight(pixelBuffer),
                                        CVPixelBufferGetWidth(pixelBuffer),
                                        kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
                                        nil,
                                        &newPixelBuffer)
        guard error == kCVReturnSuccess else {
            return nil
        }
        let ciImage = CIImage(cvPixelBuffer: pixelBuffer).oriented(.right)
        let context = CIContext(options: nil)
        context.render(ciImage, to: newPixelBuffer!)
        return newPixelBuffer
    }