2015-08-07 3 views
1

Я хочу отобразить видео текстуру в QGraphicsScene, которая имеет видовое окно QGLWidget.Qt Crash с QGLWidget :: convertToGLFormat();

Я прочитал видео с 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); 

и улов часть не выполняется.

EDIT: я получить изображение с этим:

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 int o неназванный формат, ожидаемый функциями OpenGL, например glTexImage2D(). Возвращаемое изображение не может использоваться как QImage, но QImage :: width(), QImage :: height() и QImage :: bits() могут использоваться с OpenGL. Используемый формат GL - GL_RGBA.

И действительно, поскольку width(), height() и bits() используются в glTexImage2D. И я получаю и могу выводить их из videoFrame без проблем и сбоев. И снова, он работает с некоторыми .mp4.

ответ

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); 
} 
+0

Спасибо вам большое! Для чего предназначена ваша статическая функция? Я недостаточно хорош на C++, чтобы понять это :). – SteveTJS

+0

Хорошо, я прочитал документ QImage для очистки. Еще раз спасибо. – SteveTJS

+0

@SteveTJS 'static' означает, что функция является локальной для единицы перевода. Это C-ism, но все еще имеет место на C++. Вы могли бы использовать анонимное пространство имен, если хотите, но это немного более подробный. –

Смежные вопросы