2013-02-11 24 views
5

Bir AVFrame'i opengl dokuya nasıl dönüştürebilirim diye sormak için buradaydım. Aslında, bir ses oluşturucuya ses çıkardım (Ses çalışıyor) ve video çıktı, ancak video çıkmıyor. İşte benim kodudur:OpenGL Texture'a FFMPEG

Doku oluşturma:

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

Kod Bilgisi: _texture değişken doku numarası AVFrame alır ve OpenGL Dokuya dönüştürmek

Fonksiyonu tutan bir GLuint olduğunu :

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

Kod Bilgi: bir kuyruk var Bir iş parçacığı AVFrames depolamak nerede, bu işlev, genellikle bir NULL alır, böylece çağrılıyor durur AVFrames almak için çağrılır.

Bu aslında çalışmıyor. (Yığın taşmasıyla ilgili bazı sorulara bakmaya çalıştım, hala çalışmıyor) Herhangi bir örnek veya herhangi bir hatayı düzeltmeme yardımcı olan birisi var mı?

Ek veri: Zaten ben GL_RGBA çalıştığınızda (genişlik ve yükseklik çok büyük olduğu için, zaten onları yeniden boyutlandırmak için çalıştı) çöker GL_RGBA için GL_RGB değiştirmeye çalıştı ve biçimleri ile oynamaya başladı. Boyutları 2'ye çevirmeye çalıştım, hala çalışmıyor.

1 Düzenleme:

Konu fonksiyonu:

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

Konu oluşturma işlevi: Bu NextVideoFrame içeren sınıf atıfta

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

ve _texture üyeleri.

Ben datenwolf ipuçlarından bazılarını izledi ve artık video ses/video ile doğru görüntülüyor:

çözüldü çoklu kullanım ile

Screenshot took

+0

'NextVideoFrame()', bahsettiğiniz ikincil iş parçacığında mı yoksa ana iş parçacığında mı çalışıyor? – genpfault

+0

CreateThread ve iş parçacığı gönderirim, – Spamdark

+0

koduna bakmak istemez. İkincil iş parçacığı yalnızca AVFrame'i sıraya kaydeder, NextVideoFrame başka bir yerde çağrılır, NextVideoFrame ile doku güncelleştiren bir işlev ve sonra ekrana çeker (opengl) – Spamdark

cevap

5

OpenGL biraz zordur. ve iş parçacıkları başına yalnızca bir veya hiç etkin OpenGL içeriği yoktur, bir OpenGL içeriği her seferinde yalnızca bir iş parçacığı içinde etkin olabilir. Konular arasında bir bağlamı geçirmek mümkündür, ancak iş parçacıkları arasında sıcak OpenGL bağlamında patates oynamamanız gerekir.

  • kullanın bellek haritalı Piksel Tampon Nesneler (diğer bir iplik harita, güncelleme)

  • kullanın ikincil OpenGL bağlam ile olan dokular paylaşımı:

    iki olası yolu vardır diğer. Daha sonra her bir konuya bir bağlam bağlayın (aynı çekilebilir, yani Windows'ta HDC'yi kullanabilirsiniz). Ardından, dokuyu diğerini çizerken tek bir iş parçacığında güncelleyebilirsiniz.Doku güncellemeleri, dişler arasındaki senkronizasyon noktalarını sunar, böylece çizim için erişilirken yanlışlıkla bir dokuya yazamazsınız.

+0

Harika Fikir! Son zamanlarda bir [stackoverflow sorusu] (http://stackoverflow.com/questions/6495523/ffmpeg-video-to-opengl-texture) hakkındaki yanıtlarınızdan birini inceledim ve bana çok yardımcı oldu. İşte bir ekran görüntüsü! Şimdi iyi çalışıyor! [Ekran görüntüsü] (http://oi45.tinypic.com/71ldh3.jpg) – Spamdark

+0

Kodunuzu bizimle paylaştığınız için şimdi düzeltdiniz mi? –

+0

@MikeVersteeg: Bana mı yoksa Spamdark'a mı yönlendirildi? Daha sonra, onu fark etmek için Kullanıcı adının önüne bir '@' eklemeniz gerekir. – datenwolf