我正在開發一個項目,用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幀的延遲(在移到下一幀之前,必須顯示每幀)。絕對不要將此設計用於視頻應用,請放下晚期幀。 –