2017-03-10 58 views
1

解碼CPU上的4k(3840x2160 @ 60hz)視頻以渲染到OpenGL ES紋理的軟件過程的最佳方式是什麼?將4k視頻呈現爲OpenGL ES紋理的最快方法?

我目前的做法如下:

創建像素緩衝器對象:

glGenBuffers(1, &pbo_id); 
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_id); 

分配3840x2160x4(寬度×高度×BPP)到PBO:

glBufferData(GL_PIXEL_UNPACK_BUFFER, size, NULL, GL_STREAM_DRAW); 

地圖的PBO進入客戶端的內存空間:

GLubyte *ptr = (GLubyte *)glMapBufferRange(
           GL_PIXEL_UNPACK_BUFFER, 
           0, 
           size, 
           GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT); 

解碼直接進入該存儲器和手動沖洗:

glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, size); 

看來我能夠以每秒〜300幀執行此操作。這看起來很不錯,這是很多數據。

創建紋理:

glGenTextures(1, &texture_id); 
glBindTexture(GL_TEXTURE_2D, texture_id); 

複印PBO成質地:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0); 

這個階段是緩慢而限制了性能至〜60幀。

和渲染:

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

這一階段的限制進一步性能〜40個FPS。

這是最好的方法嗎?有沒有更好的方法在屏幕上獲取一次像素?每秒40幀速度不夠快。

筆記:

  • 映射內存到客戶端的地址空間使得與視頻解碼集成簡單,轉移到GPU不必等待被解碼整個幀。

  • 我可以使用兩個或多個PBO。將當前幀解碼爲一個PBO,然後渲染/顯示前一幀的PBO,以利用寫入PBO的異步特性?但是,這會增加額外的解碼延遲幀,我非常希望避免。

  • 我的頂點和片段着色器現在是直通的。我沒有鎖定/擊劍atm,但顯然會稍後需要它。

  • 我正在使用Linux,Wayland和EGL。直接使用DRM啞巴緩衝器我可以達到〜200 fps。

回答

1

我就可以使用兩個或更多的公益組織。將當前幀解碼爲一個PBO,然後渲染/顯示前一幀的PBO,以利用寫入PBO的異步特性?但是,這會增加額外的解碼延遲幀,我非常希望避免。

這不是雙緩衝紋理上傳應該如何:-)

工作當你使用兩個公益組織,你解碼當前幀成一個PBO然後渲染相同的PBO到顯示器。這裏發生的情況是渲染將在GPU上異步發生,並且您可以在GPU仍然忙於最後一幀時開始將下一幀上傳到另一個PBO。重點是你延遲重新使用另一幀的緩衝區,讓GPU有機會趕上,這減少了後續幀的延遲,但不影響當前幀的延遲。

這是一個非常典型的策略,用於像您所描述的那樣進行高性能紋理上傳。

其餘的優化通常比較小。如果片段和頂點着色器開始時相當合理,則更改不會導致任何顯着差異。請注意,刪除glClear()通常是而不是這些日子的優化。