如何将CGImage转换为OTVideoFrame

时间:2015-10-08 22:03:56

标签: ios opentok

将CGImage转换为OTVideoFrame的最佳方法是什么?

我试图获取底层CGImage像素缓冲区并将其输入OTVideoBuffer,但图像失真。

这就是我所做的:

  1. 使用ARGB像素格式
  2. 创建了一个新的OTVideoFormat对象
  3. 将OTVideoFormat的bytesPerRow设置为height * width * 4。取CGImageGetBytesPerRow(...)的值不起作用,没有错误消息,但在行的另一端也没有帧。
  4. 复制截断它们的行,以便从CGImageGetBytesPerRow(...)转换为高度*宽度*每行4个字节。
  5. 图像变形,行略微移位
  6. 以下是代码:

    func toOTVideoFrame() throws -> OTVideoFrame {
        let width : UInt32 = UInt32(CGImageGetWidth(self)) // self is a CGImage
        let height : UInt32 = UInt32(CGImageGetHeight(self))
        assert(CGImageGetBitsPerPixel(self) == 32)
        assert(CGImageGetBitsPerComponent(self) == 8)
        let bitmapInfo = CGImageGetBitmapInfo(self)
        assert(bitmapInfo.contains(CGBitmapInfo.FloatComponents) == false)
        assert(bitmapInfo.contains(CGBitmapInfo.ByteOrderDefault))
        assert(CGImageGetAlphaInfo(self) == .NoneSkipFirst) 
    
        let bytesPerPixel : UInt32 = 4
        let cgImageBytesPerRow : UInt32 = UInt32(CGImageGetBytesPerRow(self))
        let otFrameBytesPerRow : UInt32 = bytesPerPixel * width
    
        let videoFormat = OTVideoFormat()
        videoFormat.pixelFormat = .ARGB
        videoFormat.bytesPerRow.addObject(NSNumber(unsignedInt: otFrameBytesPerRow))
        videoFormat.imageWidth = width
        videoFormat.imageHeight = height
        videoFormat.estimatedFramesPerSecond = 15
        videoFormat.estimatedCaptureDelay = 100
    
        let videoFrame = OTVideoFrame(format: videoFormat)
        videoFrame.timestamp = CMTimeMake(0, 1) // This is temporary
        videoFrame.orientation = OTVideoOrientation.Up // This is temporary
    
        let dataProvider = CGImageGetDataProvider(self)
        let imageData  : NSData = CGDataProviderCopyData(dataProvider)!
    
        let buffer = UnsafeMutablePointer<UInt8>.alloc(Int(otFrameBytesPerRow * height)) 
    
        for currentRow in 0..<height {
            let currentRowStartOffsetCGImage = currentRow * cgImageBytesPerRow
            let currentRowStartOffsetOTVideoFrame = currentRow * otFrameBytesPerRow
            let cgImageRange = NSRange(location: Int(currentRowStartOffsetCGImage), length: Int(otFrameBytesPerRow))
            imageData.getBytes(buffer.advancedBy(Int(currentRowStartOffsetOTVideoFrame)),
                range: cgImageRange)
        }
    
        do {
            let planes = UnsafeMutablePointer<UnsafeMutablePointer<UInt8>>.alloc(1)
            planes.initialize(buffer)
            videoFrame.setPlanesWithPointers(planes, numPlanes: 1)
            planes.dealloc(1)
        }
    
        return videoFrame
    }
    

    结果图片:

    The distorted resulting image

1 个答案:

答案 0 :(得分:2)

我自己解决了这个问题。

这似乎是OpenTok SDK中的一个错误。 SDK似乎无法处理大小不是16的倍数的图像。当我将所有图像大小更改为16的倍数时,一切都开始正常工作。

TokBox没有在API文档中说明这个限制,也没有在输入图像大小不是16的倍数时抛出异常。

这是我在OpenTok SDK中发现的第二个关键错误。我强烈建议你不要使用这个产品。它的质量很差。