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