iOS(swift):CVPixelBuffer图像格式转换成CMSampleBuffer

本文介绍在Swift环境下,如何利用AVSampleBufferDisplayLayer类将CVPixelBuffer格式的图像转换并显示为CMSampleBuffer格式。文章详细阐述了通过enqueue(_sampleBuffer:CMSampleBuffer)方法实现图像显示的过程,以及在iOS8及以后版本中,如何使用AVSampleBufferDisplayLayer替代传统的显示方式,同时提供了关键代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      手机上可以通过imageView作为图像的载体对一副图像进行显示。另一方面,在iOS端图像处理中,可以通过GPU对图像进行处理和渲染,并且通过metal框架,可以将处理后的图像直接显示在MTKView上。但是如果不做复杂的处理或者更加有利于将处理后的图像与MTKView更好的解耦,如何将图像进行显示了呢?一方面我们可以将CVpixelbuffer的图像数据个是转换成UIImage,另一方面,在iOS8之后,可以通过AVSampleBufferDisplayLayer这个图层进行显示。猛一看这个类,让我想起了AVPlayer()这个最为基础的iOS端的播放神器,它就是通过AVPlayerLayer()图层进行图像的显示。

      通过AVSampleBufferDisplayLayer这个类对图像进行渲染显示,需要改图像的格式为CMSampleBuffer。尽管和视频编解码接触的不多,但是知道CMSampleBuffer的图像格式和编解码联系紧密,因为其内部包含了PTS和DTS等相关信息。当有了CMSampleBuffer图像格式的数据,通过调用AVSampleBufferDisplayLayer的enqueue(_ sampleBuffer: CMSampleBuffer)方法,即可将该帧的图像进行显示。

 var sampleBufferLayer = AVSampleBufferDisplayLayer()

     AVSampleBufferDisplayLayer比较容易理解,直接对该图层包括frame在内的一些属性进行设置后,即可调用方法。

self.sampleBufferLayer.frame = self.view.bounds
self.sampleBufferLayer.videoGravity = AVLayerVideoGravity.resizeAspect
self.sampleBufferLayer.isOpaque = true
self.view.layer.addSublayer(self.sampleBufferLayer)

但是难点在于如何将CVPixeBuffer的图像格式转换成CMSampleBuffer。网络上现在OC版本挺多的,但是swift暂时还很缺少,这里就提供一下:

    func displayPixelBuffer(pixelBuffer : CVPixelBuffer){
        
        var newSampleBuffer: CMSampleBuffer? = nil
        var timimgInfo: CMSampleTimingInfo = CMSampleTimingInfo.invalid
        var videoInfo: CMVideoFormatDescription? = nil

        CMVideoFormatDescriptionCreateForImageBuffer(allocator: nil, imageBuffer: pixelBuffer, formatDescriptionOut: &videoInfo)
        CMSampleBufferCreateForImageBuffer(allocator: kCFAllocatorDefault, imageBuffer: pixelBuffer, dataReady: true, makeDataReadyCallback: nil, refcon: nil, formatDescription: videoInfo!, sampleTiming: &timimgInfo, sampleBufferOut: &newSampleBuffer)

        self.setSampleBufferAttachments(newSampleBuffer!)

        self.sampleBufferLayer.enqueue(newSampleBuffer!)
        
    }

其中的setSampleBufferAttachments函数为设置CMSampleBuffer内部的一些属性。因为这里不涉及到视频的解码信息,所有不必设置解码时间DTS和渲染时间PTS。并且也包含其他的一些属性设置。

    func setSampleBufferAttachments(_ sampleBuffer: CMSampleBuffer) {
        let attachments: CFArray! = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, createIfNecessary: true)
        let dictionary = unsafeBitCast(CFArrayGetValueAtIndex(attachments, 0),
                                       to: CFMutableDictionary.self)
        let key = Unmanaged.passUnretained(kCMSampleAttachmentKey_DisplayImmediately).toOpaque()
        let value = Unmanaged.passUnretained(kCFBooleanTrue).toOpaque()
        CFDictionarySetValue(dictionary, key, value)
    }

到了这里,图像应该能够正常显示。但是bug也不会少了,比如,当进入后台等一些事件导致渲染中断,再次进入该渲染时间后,你会发现图象不见了。网上如何解决这类bug的博客不在少数,这里就不在介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值