开发环境:VS2015+qt5.7+相机驱动
实现方案:通过驱动配置回调函数,获取相机数据,然后把数据放入到数据缓冲区;
然后开启一个线程读取缓冲队列的数据,拷贝到一帧图像的缓冲块,并使用opengl(QOpenglWidget)
进行显示(updata()-onFrameSwapped()中emit render消息,次线程SLot进行显示)。
显示代码如下:
void GLThreadWidget::UpdateShowImage()
{
update();
}
void GLThreadWidget::onFrameSwapped()
{
m_renderer->unlockRenderer();
if (IsShowUpdateflag() == true)
{
emit renderRequested();//f发送消息
}
}
//槽函数
void Renderer::render()
{
if (m_exiting)
return;
bool needrender = m_glwidget->IsShowUpdateflag();
if (needrender == false)
return;
QImage * pimage = m_glwidget->GetCurImage();
if (pimage == nullptr)
return;
QOpenGLContext *ctx = m_glwidget->context();
if (!ctx) // QOpenGLWidget not yet initialized
{
m_glwidget->SetShowUpdateFlagFalse();
return;
}
if (ctx->thread() == QThread::currentThread())
{
//qDebug() << "ctx->thread()" << ctx->thread();
m_glwidget->SetShowUpdateFlagFalse();
return;
}
// Grab the context.
m_grabMutex.lock();
emit contextWanted();
m_grabCond.wait(&m_grabMutex);
QMutexLocker lock(&m_renderMutex);
m_grabMutex.unlock();
if (m_exiting)
return;
Q_ASSERT(ctx->thread() == QThread::currentThread());
// Make the context (and an offscreen surface) current for this thread. The
// QOpenGLWidget's fbo is bound in the context.
m_glwidget->makeCurrent();
if (!m_inited)
{
m_inited = true;
initializeOpenGLFunctions();
initShaders();
initTextures();
initBuffArray();
}
//initializeOpenGLFunctions();
GLfloat *pViewRect = m_glwidget->GetViewPortForRender();
glViewport(pViewRect[0], pViewRect[1], pViewRect[2], pViewRect[3]);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
// pimage = m_glwidget->GetCurImage();
int width;
int height;
m_glwidget->GetImageSize(width, height);
m_texture->destroy();
m_texture->create();
m_texture->setSize(width, height);
m_texture->setData((*pimage).mirrored());
m_program->bind();
m_texture->bind();
QMatrix4x4 m;
this->m_program->setUniformValue(m_projviewUniform, m);
this->m_program->setUniformValue(m_textureUniform, 0);
// Draw cube geometry using indices from VBO 1
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
m_texture->release();
m_program->release();
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
// Make no context current on this thread and move the QOpenGLWidget's
// context back to the gui thread.
m_glwidget->doneCurrent();
ctx->moveToThread(qGuiApp->thread());
// Schedule composition. Note that this will use QueuedConnection, meaning
// that update() will be invoked on the gui thread.
QMetaObject::invokeMethod(m_glwidget, "update", Qt::QueuedConnection);
m_glwidget->SetShowUpdateFlagFalse();
// qDebug() << "render finished";
}
方案结果:刚开始能够正常显示,当手在移动的时候,图像也能实时的进行移动。但是
过一段时间之后,图像出现回抖现象。
比如说,手在移动的时候,能看出来显示后面的一帧图像时,又显示了前一帧图像,
看到就是手往回移了一点然后又立马往前移动。
针对此问题怀疑是数据缓冲区对列乱了,但通过使用序号验证,
读取数据用于显示时,显示的序号都是从小到大的,没有出现变小的情况。
异常现象视频:http://v.youku.com/v_show/id_XMzI0MDg5NjYyNA==.html?spm=a2h3j.8428770.3416059.1
正常现象视频:http://v.youku.com/v_show/id_XMzI0MDg5Mzg3Ng==.html?spm=a2h3j.8428770.3416059.1