FFMPEG в текстуру OpenGL

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

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

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

Информация о коде: переменная _texture - это GLuint, в котором хранится идентификатор текстуры.

Функция, которая получает 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 изменение:

Функция резьбы:

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, и теперь видео отображается правильно с аудио / видео:

Снимок экрана сделан


person Spamdark    schedule 11.02.2013    source источник
comment
NextVideoFrame() работает во вторичном потоке, о котором вы упомянули, или в основном потоке?   -  person genpfault    schedule 12.02.2013
comment
Я выложу CreateThread и ветку, лучше разобраться, глядя на код   -  person Spamdark    schedule 12.02.2013
comment
Вторичный поток сохраняет только AVFrame в очереди, NextVideoFrame вызывается в другом месте, функция, которая обновляет текстуру с помощью NextVideoFrame, а затем выводит ее на экран (opengl)   -  person Spamdark    schedule 12.02.2013


Ответы (1)


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

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

  • Использовать объекты пиксельного буфера с отображением памяти (отображение в одном потоке, обновление в другом)

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

person datenwolf    schedule 11.02.2013
comment
Отличная идея! Недавно я просмотрел один из ваших ответов на вопрос о переполнении стека, и это помогло мне много. Вот скриншот! Теперь все работает нормально! Снимок экрана - person Spamdark; 12.02.2013
comment
Не могли бы поделиться своим кодом с нами теперь, когда вы его исправили? - person Mike Versteeg; 24.04.2014
comment
@MikeVersteeg: Это было направлено на меня или на Spamdark? Если позже вы должны добавить '@' перед именем пользователя, чтобы заметить его / ее. - person datenwolf; 24.04.2014
comment
@Spamdark Не могли бы поделиться с нами своим кодом, теперь вы его исправили? - person Mike Versteeg; 24.04.2014
comment
@datenwolf Спасибо за подсказку! - person Mike Versteeg; 24.04.2014