2014-01-08 80 views
1

我的问题:缓存Outputimages在OpenGLES 2.0

我有一个视频(带可以说25FPS),其具有与屏幕上opengles 2.0渲染。 为了阅读视频,我使用了一个解码器,将视频解码为opengl es纹理。使用渲染通道,我在屏幕上绘制这个纹理。

我所要做的就是从解码器中获取图像,将其上传到GPU,调用shaderprogram并在屏幕上渲染图像。如果视频有25FPS,我必须以40ms步长(1000ms/25FPS)更新屏幕。

在每个步骤中我有待办事项以下:

  • 从解码器获得的图像
  • 推它到GPU存储器
  • 渲染屏幕
  • 交换缓冲器

到目前为止它正在工作。 现在它发生了,解码器花费超过40ms的时间来解码一帧。这并不是一直发生,但有时会发生。

解决方案将构建缓存。也就是说,在显示第一张图片之前,我会渲染5张图片。这带来了一个问题,它必须发生异步,所以可以构建缓存并同时渲染屏幕。如果发生这种情况,您可以在视频中看到它,因为它不再“流畅”。

我的问题:

  • 是否有一个解决方案?
  • 是否有可能创建一个?缓冲区,可以在渲染表面的后缓冲区上复制(?!),以便我可以使用该类缓冲区创建缓存,并将其复制到后缓冲区而不会阻塞其他正在创建这个缓冲区的线程?

OR

  • 如何填补另一个缓冲区后备缓冲?

我已经试过:

  • 渲染帧缓冲(纹理)的缓存。这个工作几乎完美,除了纹理也必须被渲染。这意味着(因为它是异步的),如果构建一个缓存帧并为屏幕创建图像,则必须互斥(/同步)渲染方法,否则程序会崩溃。但是,同步处理需要完成异步操作。所以这不是一个好的解决方案。

回答

1

请记住,在OpenGL中,如果您不清除并重画屏幕,则前一图像将保留。如果一个新的框架没有及时准备好,那么就不要做任何事情。

这听起来像你有两个线程:一个解码帧和一个渲染它们。这可以。

如果调用render()并且新框架没有及时准备好,则应该立即返回render方法。不要清除或交换缓冲区。屏幕将被保留。

现在,用户/可能/通知当帧重复两次时偶尔打嗝。 25帧/秒是不自然的帧速率(OpenGL只支持60/30/15 /等),所以它不会完全对齐屏幕刷新率。

你可以住在这(用户可能不会注意到)。或者,您可以通过缓存帧来强制播放至30 fps。

一个好主意是在你的解码器和你的渲染器之间放置一个消息队列。它可能是一个或几个帧深。它可以是数组,链表或环形缓冲区。这允许解码器上传到许多缓存纹理,而渲染正在绘制不同的纹理。

解码器在队列进入时将队列添加到队列中。渲染器以固定速率(30 fps)运行。您可以暂停渲染,直到N帧已被缓冲。

+0

说明:从两个线程使用OpenGL ES可能会非常棘手。它“仅适用于上传/绘制”(至少在iOS和Nvidia Tegra上)。 如果您的设备不允许这样做,则必须将OGL上下文包装在一个互斥锁中。在调用OGL之前,每个线程都会重新绑定上下文。 技巧保持快速: 。测试上下文是否绑定到线程;只在需要时重新绑定。 。预先分配纹理。 。不要删除纹理;重新使用它们。 。如果您的设备允许,则直接解码到纹理内存中(跳过glTexSubImage2D)。 然后解码线程调用最多1个OGL方法(纹理上传)。争用将会很低。 –