Converting CMSampleBuffer to Data and Data To UIImage 不起作用,为什么

Converting CMSampleBuffer to Data and Data To UIImage does not work, why

为了测试,我们尝试使用 Swift 4 和以下函数将 CMSampleBuffer 从捕获输出转换为数据。

获取数据后,我们将此帧数据转换为 UIImage 并返回 nil。我们无法获取 UIImage。

我们正在做这个测试,因为我们要将数据发送到其他设备以最终获取图像。

但是我们还无法从数据中获取同一设备上的图像。

我们是不是漏掉了什么。

PS:我们将此测试的 FPS 降低为 1。

func captureOutput(_ output: AVCaptureOutput,
                   didOutput sampleBuffer: CMSampleBuffer,
                   from connection: AVCaptureConnection) {

   func frameData() -> (Data) {

        let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)

        CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))

        let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
        let height = CVPixelBufferGetHeight(imageBuffer!)
        let src_buff = CVPixelBufferGetBaseAddress(imageBuffer!)

        let data = Data(bytes: src_buff!, count: bytesPerRow * height)


        CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))


            return (data)

    }

       DispatchQueue.main.async {
         let data = frameData()
         guard let image = UIImage(data) else {return}
         self.myImageView.image = image
     }



 }    

您应该检查 UIImage 构造函数的文档和数据。我很确定你不能简单地用你正在做的原始像素数据来构造它。此构造函数可能需要 png 或 jpeg 数据。 UIImage 实例上类似 pngData() 方法的反转。要从原始数据构建图像,您可以使用低一点 API。 This 看起来很有希望,但您需要将其从 objective C 移植到 Swift 或找到类似的解决方案。

您会看到在原始数据旁边需要多个参数,例如宽度、高度和像素格式。图像数据并不那么简单。因此,要重建它,您还需要附加此数据。由于您想将其发送到另一台设备,这可能并不容易。

也许一开始最好将其转换为 JSON。只需使用 base 64 编码的字符串来转换 to/from 字符串和数据:

let dataInstance = Data(base64Encoded: stringInstance)
let stringInstance = dataInstance.base64EncodedString()

所以现在你可以像这样构造一个字典:

let imageJSONDescriptor: [String: Any] = [
    "width": imageWidth,
    "height": imageHeight,
    "rawRGBAData": stringInstance
]

然后创建JSON数据

let JSONData = try! JSONSerialization.data(withJSONObject: imageJSONDescriptor, options: .prettyPrinted

另一方面,一旦您收到 JSON 数据,您需要将其转换回字典

imageJSONDescriptor = (try! JSONSerialization.jsonObject(with: JSONData, options: .allowFragments)) as! [String: Any]

并获取值

let imageWidth = imageJSONDescriptor["width"] as! Int
let imageHeight = imageJSONDescriptor["height"] as! Int
stringInstance = imageJSONDescriptor["rawRGBAData"] as! String

我希望这能解决您的问题,但问题是您实际上可能需要的数据不仅仅是宽度和高度。

好吧,我找到了一种方法,虽然有点粗糙。

我用

创建了数据
  let data = testImage.pngData() as Data?

并流式传输此数据并使用

将其转换为 UIImage
  let image = UIImage(data:Data)

但是为了做到这一点,我首先将 CMSampleBuffer 转换为 UIImage。