2013-05-06 10 views
7

Su Android, sto cercando di eseguire qualche elaborazione OpenGL sui fotogrammi delle telecamere, mostrare quei fotogrammi nell'anteprima della fotocamera e quindi codificare i fotogrammi in un file video. Sto cercando di farlo con OpenGL, usando GLSurfaceView e GLSurfaceView.Renderer e con FFMPEG per la codifica video.Utilizzo di oggetti Pixel Buffer (PBO) su Android

Ho elaborato con successo i fotogrammi dell'immagine utilizzando uno shader. Ora ho bisogno di codificare i frame elaborati in video. GLSurfaceView.Renderer fornisce il metodo onDrawFrame (GL10 ..). È in questo metodo che sto tentando di leggere i fotogrammi dell'immagine usando semplicemente glReadPixels() e quindi posizionare i fotogrammi su una coda per la codifica in video. A parte ciò, glReadPixels() è troppo lento - la mia frequenza dei fotogrammi è nelle singole cifre. Sto tentando di accelerare usando Pixel Buffer Objects. Questo non funziona. Dopo aver collegato il pbo, il frame rate rimane invariato. Questa è la mia prima volta che uso OpenGL e non so da dove cominciare a cercare il problema. Lo sto facendo bene? Qualcuno può darmi qualche indicazione? Grazie in anticipo.

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

Hai controllato gli esempi di Google Grafika? Non sarei troppo sorpreso se queste implementazioni OpenGL fossero abbastanza vicine a quelle ottimali che puoi raggiungere su Android; vale a dire https://github.com/google/grafika/blob/master/src/com/android/grafika/RecordFBOActivity.java – harism

+0

Per la chiamata a glReadPixels, prova a utilizzare glReadPixels (0, 0, larghezza, altezza, formato, GL_UNSIGNED_BYTE, 0); con zero passato alla fine, ma dovrai farlo tramite JNI, poiché java non consente nulla. Quindi usi il map buffer come al solito. –

risposta

0

non ho mai provato qualcosa di simile prima (video circuito di codifica OpenGL +), ma posso dirvi che la lettura dalla memoria del dispositivo è lento. Prova il doppio buffering, questo può essere d'aiuto dato che la GPU può mantenere il rendering sul secondo buffer mentre il controller DMA legge le cose.

Caricare un profiler (controllare il fornitore di GPU dei dispositivi), questo potrebbe darvi un'idea. Un'altra cosa che può aiutare è l'impostazione del formato interno di pbuffer in qualcos'altro, provare numeri più bassi e rilasciare un canale (alfa).

MODIFICA: Se si ha la sensazione, è possibile codificare il video sulla GPU, che aumenterà, la memoria e l'elaborazione, l'applicazione.

+0

TraxNet, grazie per la risposta. Proverò a perdere il canale alfa. Sono sicuro che aiuterà ma non farà una differenza abbastanza grande. La codifica della GPU sarebbe specifica del fornitore, non sarebbe? Devo correre su diversi dispositivi. –

+0

Probabilmente intende usare RenderScript per gli effetti collaterali della GPU. Quello sarebbe indipendente dal venditore. – akauppi

1

Come ricordo che glBufferData() non sta mappando il buffer interno nella memoria GPU, copia solo i dati dalla memoria nel buffer (inizializza).

Per accedere alla memoria, assegnata da glBufferData(), è necessario utilizzare glMapBufferRange(). Quella funzione restituisce un oggetto Java Buffer che puoi leggere.

Problemi correlati