multithreading - OpenGL 视频播放器的纹理缓冲区

标签 multithreading opengl textures video-processing

我正在使用 OpenGL、Ffmpeg 和 SDL 播放视频,目前正在优化获取帧、解码它们、将它们从 YUV 转换为 RGB、将它们上传到纹理并在四边形上显示纹理的过程。这些阶段中的每一个都由一个单独的线程执行,它们写入由 SDL 互斥锁和条件控制的共享缓冲区(除了纹理的上传和显示,因为它们需要在相同的上下文中)。

我让播放器在单独的线程上使用解码、转换和 OpenGL 上下文正常工作,但意识到因为视频是每秒 25 帧,我只从缓冲区获取转换后的帧,将其上传到 OpenGL 并绑定(bind)/显示它OpenGL 线程中的 40 毫秒。由于这个 40 毫秒的间隔,渲染循环会循环大约 6 到 10 次,而不是为它显示的每一帧显示下一帧。

因此,我决定为纹理设置一个缓冲区并设置一个使用 glGenTextures() 和我需要的 glParameters 等创建和初始化的纹理数组可能是个好主意。

当自上次帧刷新后还不到 40 毫秒时,将运行一个方法,该方法从转换缓冲区中抓取下一个转换后的帧,并通过绑定(bind)它然后调用 glTexSubImage2D() 将其上传到纹理缓冲区中的下一个空闲纹理。自上次帧刷新以来已经 40 毫秒时,运行一个单独的方法,该方法从纹理缓冲区中获取下一个 GLuint 纹理并将其与 glBindTexture() 绑定(bind)。如此有效,我只是将之前所做的事情(从转换缓冲区抓取、上传、显示)拆分为单独的方法(从转换缓冲区抓取、上传到纹理缓冲区 | 和 | 从纹理缓冲区抓取、显示)以利用40ms 刷新之间浪费的时间。

这听起来合理吗?因为在运行时,视频一直以零星的方式停止,有时会播放大约 4 帧(每 40 毫秒)但随后有 2 秒的间隙,然后显示 1 帧,然后是 3 秒的间隙并且视频完全无法观看。

该代码与我管理转换线程的方式几乎相同,该线程从解码缓冲区抓取解码帧,将它们从 YUV 转换为 RGB,然后将它们放入转换缓冲区,因此看不到可能出现的巨大瓶颈。

瓶颈可能在 OpenGL 方面吗?我将新图像数据存储到 10 个不同纹理的事实是否存在问题,因为当从纹理缓冲区中抓取新纹理时,就视频内存上的内存位置而言,原始数据可能距最后一个数据一百万英里?这是我唯一尝试回答的问题,但我不太了解 OpenGL 在内部是如何工作的,所以这就是我在这里发帖的原因。

有人有什么想法吗?

最佳答案

我不是 OpenGL 专家,但我对瓶颈的猜测是纹理在系统内存中正确初始化,但在“错误”时间发送到视频内存(就像一次而不是尽快),停滞管道。使用 glTexSubImage2D 时,您无法保证纹理何时到达视频内存,直到您绑定(bind)它。

谷歌搜索似乎像素缓冲区对象可以让您更好地控制它们何时在视频内存中:http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=262523

关于multithreading - OpenGL 视频播放器的纹理缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6775055/

相关文章:

java - Spring MVC : How do I store an application scoped key-value map (considering thread-safety)?

c# - 如何使用 Dispatcher 设置 Image.Source 属性?

c++ - 每个 VCL 表单都应该有自己的消息循环/线程泵吗?

c++ - Opengl 在 2d 或 3d 中显示顶点

java - 多线程和 Selenium

opengl - 将基本 3D 模型导入 OpenGL 应用程序

opengl - 在 OpenGL 中,有没有办法获取着色器程序使用的所有制服和属性的列表?

memory - CUDA:纹理内存的访问时间是否类似于合并的全局内存?

android - java.lang.Error : signal 11 (SIGSEGV), 代码 1 (SEGV_MAPERR) Unity Spine Android

c# - 为什么所有立方体的纹理 UV 贴图都发生了变化?