5

我是来问的,如何将 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 变量是一个保存纹理 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;
}

代码信息:有一个线程存储 AVFrames 的队列,这个函数经常被调用来获取 AVFrames,直到它得到一个 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;
}

线程创建函数:

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

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

解决了:

我遵循了一些 datenwolf 提示,现在视频与音频/视频一起正确显示:

截图

4

1 回答 1

6

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

有两种可能的方式:

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

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

于 2013-02-11T22:41:09.420 回答