Android 的 MediaProjection API 有一些问题(实际上更多,但这些是更关键的问题)。阅读图形架构并没有真正的帮助,所以我只是想了解我是否跳过了代码流中的某些内容。
让我们假设:
我有一个专用的 GL 渲染线程,已初始化,并在其上生成了 GL 纹理。我为纹理设置了 WxH 的默认缓冲区大小。
我使用 GL 纹理创建了一个 SurfaceTexture,并为此表面纹理创建了一个 Surface。
通过 MediaProjection 创建一个大小为 WxH 的虚拟显示器,并将其表面设置为上述表面。
问题 1:一切正常(全帧正确输入)或不正常(所有帧都是黑色的;或者例如每帧只有一半可见 - 所有帧的一半相同;或者屏幕的某些部分与其他部分重复部分,有时甚至歪斜)。
问题 2:虽然时间花在一些全屏 GL 游戏中,但经过 FIXED 时间(大约 4 分钟)后,所有传入帧都被冻结(例如,我收到“新”帧,但实际上是一个相同的图像) . 用 glReadPixels 阅读可以确认结果 - 问题是,实际显示超出了该帧。强制它“恢复”的唯一方法是调出状态栏或导航栏,它会立即开始向我发送正确的帧。当然,再过4分钟,它又发生了……
问题 3:在 VirtualDisplay 上调用 resize(),在对 GL 纹理也调用 setDefaultBUfferSize() 之后,最终在 90% 的情况下显示问题 #1(黑色/剪切帧,其他屏幕区域的伪影...... )
我在同一个线程中使用 updateTextureImage -> GL 纹理绘制的调用序列,所以我的正常理解是永远不会发生我以某种方式从半满的 GL 缓冲区或其他东西中读取的情况......对吗?
我还通过将 VirtualDisplay 直接渲染到 MediaCodec 的表面(不涉及自定义 GL)来测试这个问题 - 相同的行为。 更新实际上由于 MediaCodec 具有固定大小的创建表面,因此无法重现该错误,因为我们只能调整虚拟显示器的大小,而不能调整编码器的表面大小,因此这不是真正的错误(但即使这样也可以VirtualDisplay 以某种方式相应地调整表面大小)。
我觉得关闭虚拟显示器时有东西泄漏,或者在创建 VirtualDisplay 之间没有正确初始化,因为它不一致。很可能会发生全新的 MediaProjection 屏幕捕获许可,具有全新的虚拟显示器,具有刚刚创建的表面纹理,最终只会给我半切帧......让我有一张大扑克脸。 ..
PS:所有这一切都发生在装有 Android 6.0.1 的 Nexus 6 上。