2014-01-08 112 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方法(紋理上傳)。爭用將會很低。 –