【问题标题】:Qt Crash with QGLWidget::convertToGLFormat();Qt 崩溃与 QGLWidget::convertToGLFormat();
【发布时间】:2023-03-18 14:32:01
【问题描述】:

我想在具有 QGLWidget 视口的 QGraphicsScene 中显示视频纹理。

我使用 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 文档说:

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。

【问题讨论】:

    标签: qt opengl video try-catch textures


    【解决方案1】:

    Qt 代码不会抛出异常,所以try...catch 块是多余的。它崩溃是因为videoFrame 为空或指向已释放的数据等。这就是问题所在。 convertToGLFormat 崩溃是传递垃圾图像的症状。

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

    缓冲区必须在 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);
    }
    

    【讨论】:

    • 非常感谢!!你的静态函数是做什么用的?我在 C++ 方面还不够好,无法理解这一点:)。
    • @SteveTJS static 表示该函数是翻译单元的本地函数。这是一种 C 主义,但在 C++ 中仍然占有一席之地。如果你愿意,你可以使用匿名命名空间,但它有点冗长。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-21
    • 1970-01-01
    相关资源
    最近更新 更多