FFMPEG到OpenGL纹理

Spa*_*ark 5 c++ opengl ffmpeg libavformat

我在这里问,如何将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 );
Run Code Online (Sandbox Code Playgroud)

代码信息:_texture变量是保持纹理ID的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;
}
Run Code Online (Sandbox Code Playgroud)

代码信息:有一个线程存储AVFrames的线程,这个函数经常被调用来获取AVFrame,直到它获得NULL它停止被调用.

这实际上不起作用.(我试着看看堆栈溢出中的一些问题,它仍然无法工作)任何一个例子,还是有人帮助我纠正那里的任何错误?

附加数据:我试图将GL_RGB更改为GL_RGBA并开始使用格式,无论如何当我尝试GL_RGBA时崩溃(因为宽度和高度非常大,无论如何我试图调整它们的大小).我试图将尺寸改为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;
}
Run Code Online (Sandbox Code Playgroud)

线程创建功能:

CreateThread(NULL, 0, VidThread, this, NULL, NULL);
Run Code Online (Sandbox Code Playgroud)

这指的是包含NextVideoFrame的类和_texture成员.

解决了:

我按照了一些datenwolf提示,现在视频正在显示音频/视频:

截图拍了

dat*_*olf 6

具有多线程的OpenGL有点棘手.每个线程只有一个或没有活动的OpenGL上下文,并且给定的OpenGL上下文一次只能在一个线程中处于活动状态.可以在线程之间迁移上下文,但是不应该在线程之间播放热门的OpenGL-context-potato.

有两种可能的方法:

  • 使用内存映射像素缓冲区对象(映射在一个线程中,在另一个线程中更新)

  • 使用辅助OpenGL上下文,与另一个共享其纹理.然后将一个上下文绑定到每个线程(您可以使用相同的drawable,即Windows上的HDC).然后你可以更新一个线程中的纹理,而另一个线程绘制它.纹理更新会在线程之间引入同步点,因此在访问纹理时,您无法意外地写入纹理.