2

我需要实时处理来自远程视频的视频帧,并将处理后的帧呈现在屏幕上。

我曾尝试使用 AVAssetReader,但由于 AVURLAsset 正在访问远程 URL,调用AVAssetReader:initWithAsset将导致崩溃。

AVCaptureSession 看起来不错,但它适用于相机而不是视频文件(更不用说远程文件)。

因此,我现在正在探索:在 AVPlayerLayer 中显示远程视频,然后使用 GL ES 访问显示的内容。

问题:

  1. 如何将 AVPlayerLayer(或一般的 CALayer)转换为 CAEAGLLayer 并使用 读取像素CVOpenGLESTextureCacheCreateTextureFromImage()

  2. 还是有其他更好的方法?

注意:性能是一个重要的考虑因素,否则一个简单的屏幕捕获技术就足够了。

4

2 回答 2

2

据我所知,Apple 不提供对 h.264 解码器的直接访问,也没有办法解决这个问题。您可以使用的一个 API 是资产接口,您可以在其中给它一个 URL,然后磁盘上的该文件被读取为 CoreVideo 像素缓冲区。您可以尝试从您的 URL 下载,然后一次写入一个新资源(tmp 目录中的文件)一个视频帧。然后,一旦下载完成并且新的 h264 文件被完全写入,关闭写入会话,然后将文件作为资产读取器打开。您将无法使用这种方法进行流式传输,需要先下载整个文件。否则,您可以尝试使用 AVPlayerLayer 方法来查看它是否直接支持流式传输。请注意,纹理缓存逻辑并不容易实现,

于 2013-08-20T21:15:58.737 回答
2

这现在可以在现代 iOS 上实现。如果你能够用 Core Image 来表示你的实时处理——并且你现在应该能够给予 Core Image 对自定义过滤器的广泛支持——你可以利用它AVAsynchronousCIImageFilteringRequest来传递给AVPlayerItem每个文档。

如果您宁愿完全手动处理事情,您可以签出AVPlayerItemVideoOutputCVMetalTextureCache. 使用这些,您可以直接从视频中读取样本缓冲区,并将它们从纹理缓冲池中转换为金属纹理。从那里,你可以对纹理做任何你想做的事情。请注意,使用这种方法,您负责显示生成的纹理(在您自己的 Metal 或 SceneKit 渲染管道中)。

这是一篇展示这种技术的博客文章。

或者,如果您不想管理自己的渲染管道,您仍然可以使用AVPlayerItemVideoOutput抓取样本缓冲区,使用 vImage 和 Core Image 之类的东西处理它们(理想情况下使用基本的 Metal-backedCIContext以获得最大性能!),然后将它们发送到AVSampleBufferDisplayLayer直接显示在层树中。这样您就可以根据自己的喜好处理帧,并且仍然让 AVFoundation 管理图层的显示。

于 2019-09-12T19:52:03.280 回答