我CMSampleBuffer
在我的系统广播扩展中接收到 YUV 420 的屏幕,但是当我尝试访问底层字节时,我得到不一致的结果:伪影是(似乎)过去和未来帧的混合。我正在访问字节以便将纵向框架旋转四分之一圈到横向,但问题减少到无法正确复制纹理。
人工制品的图案可以改变很多。它们可能遍布各处,并且似乎具有基本的“刷子形状”,即方形瓷砖,有时小,有时大,这似乎取决于手头的失败工作。它们可以同时出现在亮度和色度通道中,从而产生有趣的效果。人工制品的“颗粒”有时看起来是水平的,我猜在原始框架中是垂直的。
我确实有两个有效的解决方法:
- 使用旋转缓冲区
Metal
- 使用旋转缓冲区
CoreImage
(即使是“软件”也CIContext
可以)
我还不能发布这些变通办法的原因是系统广播扩展的内存限制非常低,只有 50MB,而且这两种解决方案的内存使用量可能会激增,并且似乎与系统的其他部分(AVAssetWriter
例如将帧转储到我的地址空间的守护进程)。我仍在努力了解这里的内存使用情况。
人工制品似乎是一个同步问题。但是我有一种感觉,这与其说是一个新的帧被写入我正在查看的缓冲区,不如说是某种陈旧的缓存。CPU还是GPU?GPU有缓存吗?人工制品的平铺性质让我想起了 iOS GPU,但那是一粒盐(不是硬件人)。
这让我想到了问题标题。如果这是一个缓存问题,并且Metal
/CoreImage
具有一致的像素视图,也许我可以让 Metal 刷新我想要的数据,因为被转换为 YUV 的 BGRA 屏幕捕获IOSurface
已经Metal
写满了着色器。
所以我拿了传入CMSampleBuffer
的CVPixelBuffer
'sIOSurface
并从中创建了一个MTLTexture
(有各种cacheMode
s 和storageMode
s,还没有尝试过hazardTrackingMode
s),然后用MTLTexture.getBytes(bytesPerRow:from:mipmapLevel:)
.
然而问题依然存在。出于内存原因,我真的很想让 CPU 深拷贝方法工作。
为了避免一些问题:
- 这不是每行字节数的问题,这会使图像倾斜
- 在 cpu 的情况下,我确实锁定了
CVPixelBuffer
的基地址 - 我什至锁定了底层
IOSurface
- 我尝试丢弃
IOSurface
锁定种子在锁定下更改的 s - 我会在必要时丢弃帧
- 我尝试过在各处放置随机内存围栏和互斥锁(不是硬件人员)
- 我还没
CoreImage
拆
这个问题是Apple Developer Forums上发布的一个问题的延续