2013-05-06 47 views
7

在Android上,我試圖對相機框架執行一些OpenGL處理​​,在相機預覽中顯示這些框架,然後在視頻文件中對框架進行編碼。我試圖用OpenGL來做到這一點,使用GLSurfaceView和GLSurfaceView.Renderer和FFMPEG進行視頻編碼。在Android上使用像素緩衝對象(PBO)

我已經使用着色器成功處理了圖像幀。現在我需要將處理後的幀編碼爲視頻。 GLSurfaceView.Renderer提供了onDrawFrame(GL10 ..)方法。正是在這種方法中,我試圖僅使用glReadPixels()讀取圖像幀,然後將這些幀放在隊列中以編碼爲視頻。就它自己而言,glReadPixels()太慢了 - 我的幀速率是單個數字。我正在嘗試使用像素緩衝區對象加快速度。這不起作用。插入pbo後,幀速率不變。這是我第一次使用OpenGL,我不知道從哪裏開始尋找問題。我做對了嗎?任何人都可以給我一些方向嗎?提前致謝。

public class MainRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { 

. 
. 

    public void onDrawFrame (GL10 gl10) { 

     //Create a buffer to hold the image frame  
     ByteBuffer byte_buffer = ByteBuffer.allocateDirect(this.width * this.height * 4); 
     byte_buffer.order(ByteOrder.nativeOrder()); 

     //Generate a pointer to the frame buffers 
     IntBuffer image_buffers = IntBuffer.allocate(1); 
     GLES20.glGenBuffers(1, image_buffers); 

     //Create the buffer 
     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, image_buffers.get(0)); 
     GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, byte_buffer.limit(), byte_buffer, GLES20.GL_STATIC_DRAW); 
     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, image_buffers.get(0)); 

     //Read the pixel data into the buffer 
     gl10.glReadPixels(0, 0, this.width, this.height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, byte_buffer); 

     //encode the frame to video 
     enQueueForEncoding(byte_buffer); 

     //unbind the buffer 
     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 
    } 

. 
. 

} 
+0

您是否檢查過Google Grafika示例?如果這些OpenGL實現非常接近您在Android上可以達到的最佳效果,不會感到驚訝;即https://github.com/google/grafika/blob/master/src/com/android/grafika/RecordFBOActivity.java – harism 2014-07-09 10:32:19

+0

對於你的glReadPixels調用,嘗試使用glReadPixels(0,0,寬度,高度,格式,GL_UNSIGNED_BYTE, 0);在最後傳遞零,但是你需要通過JNI來完成,因爲java不允許爲空。然後像往常一樣使用地圖緩衝區。 – 2015-02-20 16:06:49

回答

0

我從來沒有嘗試過這樣的事情(opengl + video enconding),但我可以告訴你,從設備內存讀取是慢的。嘗試雙緩衝,這可能會有所幫助,因爲當DMA控制器讀回內容時,GPU可以繼續渲染到第二個緩衝區。

加載分析器(檢查您的設備的GPU供應商),這可能會給你一些想法。另一個可能幫助的事情是將內部pbuffer格式設置爲其他內容,嘗試較低的數字並刪除一個通道(alpha)。

編輯:如果你覺得這樣,你可以在GPU上編碼視頻,這將提升,內存和處理智慧,你的應用程序。

+0

TraxNet,謝謝你的回覆。我會嘗試失去Alpha通道。我相信它會有所幫助,但它不會產生足夠大的差異。在GPU上編碼將是供應商特定的,不是嗎?我需要運行不同的設備。 – 2013-05-06 21:55:10

+0

他可能意味着使用RenderScript進行GPU副作用。這將是獨立於供應商的。 – akauppi 2014-06-11 05:16:43

1

我記得glBufferData()沒有將內部緩衝區映射到GPU內存,它只是將數據從內存中複製到緩衝區(初始化)。

要訪問由glBufferData()分配的內存,應該使用glMapBufferRange()。該函數返回您可以讀取的Java緩衝區對象。

相關問題