如何使用 AVFoundation 从视频流中获取原始格式的图像缓冲区?

Posted

技术标签:

【中文标题】如何使用 AVFoundation 从视频流中获取原始格式的图像缓冲区?【英文标题】:How does one obtain image buffers in their original format from a video stream using AVFoundation? 【发布时间】:2018-05-05 08:07:35 【问题描述】:

在Apple的AVAssetReaderTrackOutput的文档中,它指出了使用+[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:outputSettings:]实例化实例时outputSettings的参数如下

nil 值将输出配置为以指定轨道存储的原始格式提供样本。

当使用它时,例如一个 MP4 视频资产,它似乎会按解码顺序逐步遍历帧(即显示无序),但是使用 CMSampleBufferGetImageBuffer 传递的 CMSampleBufferRef 对象的所有查询都会产生 NULL CVImageBufferRef 对象。

我可以确保传递图像缓冲区对象的唯一方法是向outputSettings: 提供像素缓冲区格式,例如kCVPixelFormatType_32ARGB 用于kCVPixelBufferPixelFormatTypeKey 字典条目。

这样做的另一个有趣的副作用是,帧随后按显示顺序传递,而帧的底层解码顺序被抽象/隐藏了。

任何想法为什么会这样?

【问题讨论】:

你怎么知道框架有问题?从演示时间戳?你确定它们是框架? p.s. “原始格式”是什么意思? 由于显示时间戳,帧似乎是无序的,是的。我不确定它们是否包含帧,但它们会跟踪帧的解码顺序,否则,通过例如其他 API,例如 QuickTime。通过原始格式,我引用了 Apple 的文档所表明的内容——其想法是避免在编码流自然传输的内容和我最终得到的内容之间进行任何不必要的像素格式转换。 也许 GOP B 帧可以解释乱序时间戳?我们说话有多乱? en.wikipedia.org/wiki/Video_compression_picture_types 【参考方案1】:

和你一样,我预计将 outputSettings 设置为 nil 会导致输出原生格式视频帧,但事实并非如此,您必须指定一些内容才能获得有效的 CVSampleBufferRef

一切都不会丢失,使用“几乎没有”的字典似乎会以其本机格式输出帧,

AVAsset asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
AVAssetTrack *videoTrack = [[asset tracksWithMediaCharacteristic:AVMediaCharacteristicVisual] objectAtIndex:0];

NSDictionary *decompressionSettings =
     @ (id)kCVPixelBufferiosurfacePropertiesKey : [NSDictionary dictionary] ;
AVAssetReaderTrackOutput trackOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:videoTrack outputSettings:decompressionSettings];
...

IOSurfaceOptions 只是默认设置 - 进一步阅读以供参考:https://developer.apple.com/documentation/corevideo/kcvpixelbufferiosurfacepropertieskey?language=objc

【讨论】:

以上是关于如何使用 AVFoundation 从视频流中获取原始格式的图像缓冲区?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AVFoundation 修剪视频

使用 AVFoundation / QTKit 一次录制多个视频

使用AVFoundation 自定义相机和录制视频

Swift IOS 使用 AVFoundation 录制视频和音频

AVFoundation 初解

如何使用 AVFoundation 为您的视频添加不同图像和不同 CMTimes 的水印