我正在开发一个项目,用OpenGL显示视频流,然后在外部屏幕上显示QOpenGLWidget
上的内容。所以我做的是在OpenGL小部件上显示流,然后使用glReadPixels
和两个像素包缓冲区对象来获取缓冲区并将其发送到另一个屏幕。问题是,与使用PBOs时相比,当我不是时,我会失去表现。Qt/OpenGL:我是否正确使用PBO?
这里是代码的有趣的部分:
的代码来创建将是外屏上发送帧:
screenBuffer
是存储从QOpenGLWidget
帧的内存缓冲区
在代码中的这一点上,PBO已经充满了数据从paintGL
功能
void GLWidget::videodisplay(unsigned char *copy){
update();
unsigned char* frame = publicCreateOutputVideoFrame();
if(pboIndex){
pbo1->bind();
pbo1->read(0, screenBuffer, vWidth*vHeight*3);
}else{
pbo2->bind();
pbo2->read(0, screenBuffer, vWidth*vHeight*3);
}
pboIndex = !pboIndex;
unsigned char* yuvFrame = convertRGBtoYUV(screenBuffer);
memcpy(frame, yuvFrame, vWidth*vHeight*2);
publicDisplayVideoFrameSync();
delete yuvFrame;
yuvFrame = NULL;
delete copy;
copy = NULL;
}
初始化的PBO的:
void GLWidget::InitializeGL(){
pbo1 = new QOpenGLBuffer(QOpenGLBuffer::PixelPackBuffer);
pbo1->create();
pbo1->bind();
pbo1->allocate(vWidth*vHeight*3);
pbo1->release();
pbo2 = new QOpenGLBuffer(QOpenGLBuffer::PixelPackBuffer);
pbo2->create();
pbo2->bind();
pbo2->allocate(vWidth*vHeight*3);
pbo2->release();
}
这里我用PBO与glReadPixels
void GLWidget::paintGL(){
glClear(GL_COLOR_BUFFER_BIT);
program->bind();
{
vao.bind();
glBindTexture(GL_TEXTURE_2D, tex);
glDrawArrays(GL_QUADS, 0, 4);
glBindTexture(GL_TEXTURE_2D, 0);
vao.release();
}
program->release();
if(!isZoomed){
programMouse->bind();
{
vaoMouse.bind();
glLineWidth(2.0);
glDrawArrays(GL_LINES, 0, 8);
vaoMouse.release();
}
programMouse->release();
}
if(pboIndex){
pbo2->bind();
}else{
pbo1->bind();
}
glReadPixels(0, 0, vWidth, vHeight, GL_RGB, GL_UNSIGNED_BYTE, 0);
if(pboIndex){
pbo2->release();
}else{
pbo1->release();
}
}
pboIndex
只是切换值的第一和第二PBO之间交替一个布尔值。
显然,由于我失去表现,我做错了什么?我是以错误的方式使用公益组织,或者我没有正确理解我应该使用它们的情况。
感谢
当然,如果你天真地增加缓冲区长度,会引入额外的延迟。一些API(例如Direct3D)使用FIFO队列来呈现帧渲染,这为队列中的每个缓冲区添加了1帧的延迟(在移到下一帧之前,必须显示每帧)。绝对不要将此设计用于视频应用,请放下晚期帧。 –