2013-02-11 21 views
5

Ich war hier um zu fragen, wie kann ich einen AVFrame in eine OpenGL-Textur konvertieren. Eigentlich habe ich einen Renderer erstellt der mir das Audio (Audio funktioniert) und das Video ausgibt, aber das Video wird nicht ausgegeben. Hier ist mein Code:FFMPEG zu OpenGL Textur

Textur Schöpfung:

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); 

-Code Info: _texture Variable ist ein GLuint, dass die Textur ID

Funktion hält, die die AVFrame und wandelt es in OpenGL Texture bekommt :

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; 
} 

Code Information: Es gibt eine Warteschlange wo ein Thread die AVFrames speichert, wird diese Funktion häufig aufgerufen, um die AVFrames zu holen, bis sie einen NULL erhält, wird sie nicht mehr aufgerufen.

Das funktioniert eigentlich nicht. (Ich habe versucht, einige Fragen im Stapelüberlauf zu betrachten, es funktioniert immer noch nicht) Irgendein Beispiel, oder jemand, der mir hilft, irgendeinen Fehler dort zu korrigieren?

Weitere Daten: Ich versuchte, die GL_RGB zu GL_RGBA zu ändern und begann mit den Formaten zu spielen, trotzdem es stürzt ab, wenn ich GL_RGBA versuchen (Da die Breite und Höhe sehr groß ist, trotzdem habe ich versucht, sie zu verkleinern). Ich habe versucht, die Größen zu Power Of 2 zu ändern, Stills funktioniert nicht.

1 Edit:

Thema Funktion:

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; 
} 

Themen-Erstellungsfunktion:

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

Wo dies auf die Klasse verweist, die NextVideoFrame enthält, und die _texture Mitglieder.

Gelöst:

ich einige der datenwolf Tipps befolgt, und nun wird das Video korrekt mit dem Audio/Video-Anzeige:

Screenshot took

+0

Wird 'NextVideoFrame()' auf dem von Ihnen erwähnten Sekundär-Thread oder im Haupt-Thread ausgeführt? – genpfault

+0

Ich poste den CreateThread und den Thread, es ist besser zu ersstandard es mit Blick auf den Code – Spamdark

+0

Der sekundäre Thread speichert nur den AVFrame in der Warteschlange, der NextVideoFrame wird an einer anderen Stelle aufgerufen, eine Funktion, die die Textur mit NextVideoFrame aktualisieren und dann zieht es auf den Bildschirm (opengl) – Spamdark

Antwort

5

OpenGL mit Multithreading ein bisschen schwierig ist. Es gibt nur einen oder keinen aktiven OpenGL-Kontext pro Thread und ein gegebener OpenGL-Kontext kann immer nur in einem Thread aktiv sein. Es ist möglich, einen Kontext zwischen Threads zu migrieren, aber Sie sollten nicht heißen OpenGL-Kontext-Potato zwischen Threads spielen.

Es gibt zwei Möglichkeiten:

  • Verwenden Speicher abgebildeten Pixel Buffer Objects (Karte in einem Thread, update im anderen)

  • Verwenden eines sekundärer OpenGL Zusammenhang seine Texturen Austausch mit der andere. Dann binden Sie einen Kontext an jeden Thread (Sie können das gleiche Zeichen verwenden, d. H. HDC unter Windows). Dann können Sie die Textur in dem einen Thread aktualisieren, während der andere es zeichnet.Texturaktualisierungen führen Synchronisationspunkte zwischen Threads ein, sodass Sie nicht versehentlich in eine Textur schreiben können, während auf sie zum Zeichnen zugegriffen wird.

+0

Großartige Idee! Ich habe kürzlich in einer deiner Antworten auf eine [stackoverflow Frage] (http://stackoverflow.com/questions/6495523/ffmpeg-video-to-engl-texture) geschaut und es hat mir sehr geholfen. Hier ist ein Screenshot! Es funktioniert jetzt gut! [Screenshot] (http://oi45.tinypic.com/71ldh3.jpg) – Spamdark

+0

Haben Sie Ihren Code mit uns geteilt, jetzt haben Sie ihn behoben? –

+0

@MikeVersteeg: War das auf mich oder Spamdark gerichtet? Wenn später müssen Sie ein '@' vor dem Benutzernamen hinzufügen, um ihn/sie zu bemerken. – datenwolf