【问题标题】:How to convert CGImage to OTVideoFrame如何将 CGImage 转换为 OTVideoFrame
【发布时间】:2016-01-06 17:16:33
【问题描述】:

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

我尝试获取底层 CGImage 像素缓冲区并将其输入到 OTVideoBuffer,但得到了一个失真的图像。

这是我所做的:

  1. 创建了一个新的 ARGB 像素格式的 OTVideoFormat 对象
  2. 将 OTVideoFormat 的 bytesPerRow 设置为 height*width*4。获取 CGImageGetBytesPerRow(...) 的值不起作用,没有收到错误消息,但行的另一端也没有帧。
  3. 复制行以将它们截断以从 CGImageGetBytesPerRow(...) 转换为 height*width*4 bytes 每行。
  4. 得到一个扭曲的图像,行略有偏移

代码如下:

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
}

结果图片:

【问题讨论】:

    标签: ios opentok


    【解决方案1】:

    我自己解决了这个问题。

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

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

    这是我在 OpenTok SDK 中发现的第二个严重错误。我强烈建议您不要使用该产品。它的质量非常低。

    【讨论】:

      猜你喜欢
      • 2017-10-03
      • 2011-04-14
      • 1970-01-01
      • 1970-01-01
      • 2019-04-11
      • 1970-01-01
      • 2014-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多