2013-02-11 3 views
5

Я был здесь, чтобы спросить, как преобразовать AVFrame в текстуру opengl. Фактически, я создал рендерер, который выводит меня аудио (аудио работает) и видео, но видео не выводит. Вот мой код:FFMPEG to OpenGL Texture

создание текстуры:

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: _texture переменная является GLuint, которая сохраняет текстуру ID

Функция которая получает AVFrame и преобразовать его в OpenGL текстуры :

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

Информация о кодах: есть очередь где поток хранит AVFrames, эту функцию часто вызывают, чтобы получить AVFrames, пока не получит NULL, который перестает быть вызванным.

Это на самом деле не работает. (Я пытался посмотреть на некоторые вопросы в переполнении стека, он все равно не работает) Любой пример, или кто-то, кто помогает мне исправить любую ошибку там?

Дополнительные данные: Я пытался изменить GL_RGB к GL_RGBA и начал играть с форматами, в любом случае это происходит сбой при попытке GL_RGBA (Поскольку ширина и высота очень большая, во всяком случае, я пытался изменить их). Я попытался изменить размеры до Power Of 2, кадры не работают.

1 Edit:

функция Автор:

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

Тема функции создания:

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

Где это относится к классу, который содержит NextVideoFrame, и члены _texture.

Решено:

Я последовал за некоторые советы datenwolf, и теперь видео правильно отображая с аудио/видео:

Screenshot took

+0

Является ли 'NextVideoFrame()' запущенным на упомянутой вами вторичной теме или в основном потоке? – genpfault

+0

Я опубликую CreateThread и поток. Лучше не понимать, что он смотрит на код. – Spamdark

+0

Вторичный поток хранит AVFrame в очереди, а в другом месте вызывается NextVideoFrame, функция, которая обновляет текстуру с помощью NextVideoFrame, а затем рисует его на экран (opengl) – Spamdark

ответ

5

OpenGL с многопоточной немного сложнее. В каждом потоке и присутствует только один или никакой активный контекст OpenGL, данный контекст OpenGL может быть активен только по одному потоку за раз. Миграция контекста между потоками возможна, но вы не должны воспроизводить горячий OpenGL-контекст-картофель между потоками.

Есть два возможных пути:

  • Использование памяти отображается Pixel Buffer Objects (карта в одном потоке, изменение в другой)

  • Использование вторичного контекста OpenGL, разделяя его текстуры с Другие. Затем привяжите один контекст к каждому потоку (вы можете использовать тот же drawable, т. Е. HDC в Windows). Затем вы можете обновлять текстуру в одном потоке, а другой - рисовать.Обновления текстур вводят точки синхронизации между потоками, поэтому вы не можете случайно записать текстуру, пока она доступна для рисования.

+0

Отличная идея! Недавно я просмотрел один из ваших ответов на вопрос [stackoverflow] (http://stackoverflow.com/questions/6495523/ffmpeg-video-to-opengl-texture), и это очень помогло мне. Вот скриншот! Теперь он работает нормально! [Снимок экрана] (http://oi45.tinypic.com/71ldh3.jpg) – Spamdark

+0

Ум, разделяющий ваш код с нами, теперь вы его исправили? –

+0

@MikeVersteeg: Это было направлено на меня или Spamdark? Если позже вы должны добавить «@» перед именем пользователя, чтобы заметить его/ее. – datenwolf