Qt崩溃与QGLWidget :: convertToGLFormat();

时间:2015-08-07 11:05:07

标签: qt opengl video try-catch textures

我想在QGraphicsScene中显示一个视频纹理,它有一个QGLWidget视口。

我用openCV阅读视频,我抓住每一帧,将其转换为QImage然后我做:

QImage img=QGLWidget::convertToGLFormat(videoFrame);//videoFrame is the frame got from openCV video reading and converted to QImage

我的问题是它适用于很多视频(我使用的是.mp4),但是与其他人(仍然是.mp4)一样,这行代码会让我的应用程序崩溃,而我无法找到原因。

我的问题是如何在不知道确切原因的情况下防止崩溃?我尝试过:

QImage img;
try{
    img=QGLWidget::convertToGLFormat(videoFrame);
}
catch(...)
{
    img=QImage("defaultImg.jpg");
}

但它仍然在

崩溃
img=QGLWidget::convertToGLFormat(videoFrame);

并且不执行catch部分。

编辑: 我得到的图像是:

QImage VideoPlayer::getVideoFrame()
{
    IplImage* frame= cvQueryFrame( capture );
    m=cv::Mat(frame);//m is a member of class VideoPlayer

    return cvMatToQImage(m);
}

QImage VideoPlayer::cvMatToQImage(cv::Mat inMat)
{
    cv::Mat temp;
    cv::cvtColor(inMat, temp,CV_BGR2RGB);
    QImage cvMatToQImg((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);

    return QImage(cvMatToQImg);
}

在我的QgraphicsScene子类中:

QImage videoFrame = videoPlayerInstance->getVideoFrame();
QImage img=QGLWidget::convertToGLFormat(videoFrame);//crashes here
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());

Qt doc说:

  

QImage QGLWidget :: convertToGLFormat(const QImage& img)转换   将img转换为OpenGL函数所期望的未命名格式,例如   glTexImage2D()。返回的图像不能用作QImage,但是   可以使用QImage :: width(),QImage :: height()和QImage :: bits()   OpenGL的。使用的GL格式是GL_RGBA。

实际上,因为在glTexImage2D中使用了width(),height()和bits()。我得到并可以从videoFrame输出它们没有问题和崩溃。 而且,它适用于某些.mp4。

1 个答案:

答案 0 :(得分:0)

Qt代码不会抛出异常,因此try...catch块是多余的。它崩溃是因为videoFrame为null或指向解除分配的数据或某些东西。这就是问题所在。 convertToGLFormat崩溃是将垃圾图像传递给它的一种症状。

具体来说,您在QImage中使用的cvMatToQImage构造函数正构建一个使用临时缓冲区的图像。构造函数的文档说明:

  

缓冲区必须在QImage的整个生命周期内保持有效,并且所有未复制或以其他方式从原始缓冲区中分离的副本都必须保持有效。

您应该强制图像保留矩阵。你可能也不会过早地通过强制使用矩阵参数的副本来进行悲观化 - 而是传递一个const引用。

static void cvMatQImageCleanup(void *info) {
  delete reinterpret_cast<cv::Mat*>(info);
}

QImage VideoPlayer::cvMatToQImage(const cv::Mat & inMat)
{
    auto temp = new cv::Mat;
    cv::cvtColor(inMat, *temp, CV_BGR2RGB);
    return QImage((uchar*) temp->data, temp->cols, temp->rows, temp->step, 
      QImage::Format_RGB888, &cvMatQImageCleanup, temp);
}