Кэширование выходных изображений в OpenGLES 2.0

Моя проблема:

У меня есть видео (скажем, 25 кадров в секунду), которое нужно отображать с помощью opengles 2.0 на экране. Для чтения видео я использую декодер, который декодирует это видео в текстуры OpenGL. С помощью renderpass я рисую эту текстуру на экране.

Что мне нужно сделать, так это получить изображение из декодера, загрузить его в графический процессор, вызвать шейдерную программу и отобразить изображение на экране. Если видео имеет 25 кадров в секунду, мне нужно обновить экран с шагом 40 мс (1000 мс / 25 кадров в секунду).

На каждом этапе я должен сделать следующее:

  • получить изображение из декодера
  • запихнуть его в память gpu
  • визуализировать экран
  • поменять местами буферы

Пока это работает. Теперь случается, что декодеру требуется больше 40 мс для декодирования кадра. Это происходит не постоянно, а иногда.

Решением будет создание кеша. Это означает, что я делаю рендеринг, т.е. 5 изображений, прежде чем показывать первое. Это связано с проблемой, это должно происходить асинхронно, чтобы кеш мог создаваться и экран отображался одновременно. Если это произойдет, вы можете увидеть это на видео, потому что оно больше не «текучее».

Мой вопрос:

  • Есть ли решение для этого?
  • Можно ли создать ?-буфер, который можно скопировать (?!) в задний буфер поверхности рендеринга, чтобы я мог создать кеш с такими буферами и скопировать его в задний буфер, не блокируя другой поток, который создает эти буферы?

OR

  • Как заполнить задний буфер другим буфером?

Я уже пробовал:

  • Рендеринг кадрового буфера (текстур) в виде кеша. Это работает почти идеально, за исключением того, что текстура также должна быть визуализирована. Это означает, что (поскольку это асинхронно), если создается кэш-кадр и создается изображение для экрана, вы должны мьютексировать (/синхронизировать) методы рендеринга, иначе программа выйдет из строя. Но синхронизация сводится к тому, чтобы сделать ее асинхронной. Так что это не очень хорошее решение.

person andre    schedule 08.01.2014    source источник


Ответы (1)


Помните, что в OpenGL, если вы не очистите и не перерисуете экран, сохранится предыдущее изображение. Если новый кадр не будет готов вовремя, просто ничего не делайте.

Похоже, у вас есть два потока: один кадры декодирования и один их рендеринг. Это хорошо.

Если вызывается метод render(), а новый кадр не готов вовремя, ваш метод рендеринга должен вернуться немедленно. Не очищайте и не меняйте местами буферы. Экран сохранится.

Теперь пользователь /может/ замечать случайные сбои, когда кадр повторяется дважды. 25 кадров в секунду — это неестественная частота кадров (OpenGL поддерживает только 60/30/15/и т. д.), поэтому она не будет идеально соответствовать частоте обновления экрана.

Вы можете жить с этим (пользователь, скорее всего, не заметит). Или вы можете увеличить скорость воспроизведения до 30 кадров в секунду, буферизовав кадры.

Хорошей идеей будет разместить очередь сообщений между декодером и средством визуализации. Это может быть один или несколько кадров в глубину. Это может быть массив, связанный список или кольцевой буфер. Это позволяет декодеру загружать во множество кэшированных текстур, в то время как рендеринг рисует другую текстуру.

Декодер добавляет кадры в очередь по мере их поступления. Рендерер работает с фиксированной скоростью (30 кадров в секунду). Вы можете приостановить рендеринг до тех пор, пока не будет буферизовано N кадров.

person Sean Kelleher    schedule 08.01.2014
comment
Уточнение: использование OpenGL ES из двух потоков может быть сложным. Он работает только для загрузки/отрисовки (по крайней мере, на iOS и Nvidia Tegra). Если ваше устройство не позволяет этого, вы должны заключить контекст OGL в мьютекс. Каждый поток будет повторно связывать контекст перед вызовом OGL. Уловки, чтобы сохранить вещи быстро: . Проверьте, привязан ли контекст к потоку; перевязывать только при необходимости. . Предварительно распределите текстуры. . Не удаляйте текстуры; использовать их повторно. . Декодируйте непосредственно в память текстур, если ваше устройство позволяет (пропустите glTexSubImage2D). Затем поток декодирования вызывает не более 1 метода OGL (загрузка текстуры). Конкуренция будет низкой. - person Sean Kelleher; 10.01.2014