2013-02-11 12 views
5

Ero qui per chiedere, come posso convertire un AVFrame in una trama opengl. In realtà, ho creato un renderer, mi ha prodotto l'audio (l'audio funziona) e il video, ma il video non è in uscita. Qui è il mio codice:FFMPEG a OpenGL Texture

creazione Struttura:

glGenTextures(1,&_texture); 
glBindTexture(GL_TEXTURE_2D,_texture); 
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

Info Codice: _texture variabile è un GLuint che mantiene l'ID consistenza

funzione che ottiene l'AVFrame e convertirlo in OpenGL Texture :

int VideoGL::NextVideoFrame(){ 
// Get a packet from the queue 
AVPacket *videopacket = this->DEQUEUE(VIDEO); 
int frameFinished; 
if(videopacket!=0){ 
    avcodec_decode_video2(_codec_context_video, _std_frame,&frameFinished,videopacket); 

    if(frameFinished){ 

     sws_scale(sws_ctx, _std_frame->data, _std_frame->linesize, 0, _codec_context_video->height, _rgb_frame->data, _rgb_frame->linesize); 

     if(_firstrendering){ 
     glBindTexture(GL_TEXTURE_2D,_texture); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _codec_context_video->width,_codec_context_video->height,0,GL_RGB,GL_UNSIGNED_BYTE,_rgb_frame->data[0]); 

     _firstrendering = false; 

     }else{ 

      glActiveTexture(_texture); 
      glBindTexture(GL_TEXTURE_2D,_texture); 
      glTexSubImage2D(GL_TEXTURE_2D,0,0,0,_codec_context_video->width,_codec_context_video->height,GL_RGB,GL_UNSIGNED_BYTE,_rgb_frame->data[0]); 

     } 
     av_free_packet(videopacket); 
     return 0; 
    }else{ 

     av_free_packet(videopacket); 
     return -1; 
    } 

}else{ 
    return -1; 
} 
return 0; 
} 

Codice Informazioni: V'è una coda dove un thread memorizza gli AVFrame, questa funzione viene spesso chiamata per ottenere gli AVFrame, finché non ottiene un NULL che non viene più chiamato.

Questo in realtà non funziona. (Ho provato a guardare alcune domande nello stack overflow, non funziona ancora) Qualche esempio o qualcuno che mi aiuti a correggere qualche errore lì?

Dati aggiuntivi: Ho provato a cambiare il GL_RGB per GL_RGBA e ha cominciato a giocare con i formati, in ogni caso si blocca quando provo GL_RGBA (Poiché la larghezza e l'altezza sono molto grandi, in ogni caso ho cercato di ridimensionare loro). Ho provato a cambiare le dimensioni in Power Of 2, non funziona ancora.

1 Edit:

funzione Discussione:

DWORD WINAPI VideoGL::VidThread(LPVOID myparam){ 

VideoGL * instance = (VideoGL*) myparam; 
instance->wave_audio->Start(); 

int quantity=0; 

AVPacket packet; 
while(av_read_frame(instance->_format_context,&packet) >= 0){ 
    if(packet.stream_index==instance->videoStream){ 
     instance->ENQUEUE(VIDEO,&packet); 
    } 
    if(packet.stream_index==instance->audioStream){ 
     instance->ENQUEUE(AUDIO,&packet); 
    } 
} 

instance->ENQUEUE(AUDIO,NULL); 
instance->ENQUEUE(VIDEO,NULL); 

return 0; 
} 

Discussione funzione di creazione:

CreateThread(NULL, 0, VidThread, this, NULL, NULL); 

Dove questo si riferisce alla classe che contiene la NextVideoFrame, ei membri _texture.

risolto:

ho seguito alcuni dei suggerimenti datenwolf, e ora il video viene visualizzata correttamente con l'audio/video:

Screenshot took

+0

'NextVideoFrame()' è in esecuzione sul thread secondario menzionato o sul thread principale? – genpfault

+0

Pubblicherò il CreateThread e il thread, È preferibile non distinguerlo guardando il codice – Spamdark

+0

Il Thread secondario memorizza solo AVFrame in coda, il NextVideoFrame viene chiamato in un altro posto, una funzione che aggiorna la texture con NextVideoFrame e quindi lo disegna sullo schermo (opengl) – Spamdark

risposta

5

OpenGL con multithreading è un po 'complicato. C'è solo uno o nessun contesto OpenGL attivo per thread e un determinato contesto OpenGL può essere attivo in un solo thread alla volta. La migrazione di un contesto tra i thread è possibile, ma non si dovrebbe giocare hot OpenGL-context-potato tra i thread.

Ci sono due modi possibili:

  • Utilizzo memoria mappata oggetti Pixel Buffer (mappa in un thread, aggiornare nell'altro)

  • Utilizzare un contesto OpenGL secondario, condividendone le trame con la altro. Quindi associa un contesto a ciascun thread (puoi utilizzare lo stesso drawable, ovvero HDC su Windows). Quindi è possibile aggiornare la trama in un thread mentre l'altro lo disegna.Gli aggiornamenti delle texture introducono punti di sincronizzazione tra i thread, quindi non è possibile scrivere accidentalmente in una trama mentre è in corso l'accesso per il disegno.

+0

Ottima idea! Di recente ho esaminato una delle tue risposte su una [domanda stackoverflow] (http://stackoverflow.com/questions/6495523/ffmpeg-video-to-opengl-texture) e mi ha aiutato molto. Ecco uno screenshot! Funziona bene ora! [Screenshot] (http://oi45.tinypic.com/71ldh3.jpg) – Spamdark

+0

Mente condividendo il tuo codice con noi ora lo hai risolto? –

+0

@MikeVersteeg: è stato diretto da me o da Spamdark? Se in seguito devi aggiungere un '@' davanti al nome utente per notarlo. – datenwolf