QT QLabel setPixmap из QAbstractVideoSurface

Я реализую свой собственный класс для исследования видеокадров из QCamera под Windows. Это подкласс QAbstractVideoSurface. Итак, мой зонд генерирует QPixmap, который я пытался нарисовать на QLabel (как видоискатель). И у меня ошибка сегментации при вызове QLabel setPixmap.

Я уверен, что мой Qpixmap хорошо сделан, потому что я могу сохранить его на диске с помощью save (). Мой QLabel инициализирован и работает хорошо, потому что я могу загрузить QPixmap с диска и установить его на QLabel. Я думаю, что есть проблема с форматом растрового изображения, но не могу понять, как это исправить 🙁

Мой код

frameprobe.h

#ifndef FRAMEPROBE_H
#define FRAMEPROBE_H
#include <QAbstractVideoSurface>
#include <QList>
#include <QPixmap>

class FrameProbe : public QAbstractVideoSurface
{
Q_OBJECT
public:
explicit FrameProbe(QObject *parent = 0);

QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;

bool present(const QVideoFrame &frame);

signals:
void frameAvailable(QImage frame);
void frameReady(QPixmap frame);

public slots:
};

#endif // FRAMEPROBE_H

frameprobe.cpp

#include "frameprobe.h"
FrameProbe::FrameProbe(QObject *parent) :
QAbstractVideoSurface(parent)
{
}

QList<QVideoFrame::PixelFormat> FrameProbe::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
Q_UNUSED(handleType);
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_ARGB32_Premultiplied
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_RGB555
<< QVideoFrame::Format_ARGB8565_Premultiplied
<< QVideoFrame::Format_BGRA32
<< QVideoFrame::Format_BGRA32_Premultiplied
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_BGR24
<< QVideoFrame::Format_BGR565
<< QVideoFrame::Format_BGR555
<< QVideoFrame::Format_BGRA5658_Premultiplied
<< QVideoFrame::Format_AYUV444
<< QVideoFrame::Format_AYUV444_Premultiplied
<< QVideoFrame::Format_YUV444
<< QVideoFrame::Format_YUV420P
<< QVideoFrame::Format_YV12
<< QVideoFrame::Format_UYVY
<< QVideoFrame::Format_YUYV
<< QVideoFrame::Format_NV12
<< QVideoFrame::Format_NV21
<< QVideoFrame::Format_IMC1
<< QVideoFrame::Format_IMC2
<< QVideoFrame::Format_IMC3
<< QVideoFrame::Format_IMC4
<< QVideoFrame::Format_Y8
<< QVideoFrame::Format_Y16
<< QVideoFrame::Format_Jpeg
<< QVideoFrame::Format_CameraRaw
<< QVideoFrame::Format_AdobeDng;
}

bool FrameProbe::present(const QVideoFrame &frame)
{
if (frame.isValid()) {
QVideoFrame cloneFrame(frame);
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);

QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat());

const QImage image(cloneFrame.bits(),
cloneFrame.width(),
cloneFrame.height(),
imageFormat);
emit frameAvailable(image);
emit frameReady(QPixmap::fromImage(image));
cloneFrame.unmap();
return true;
}
return false;
}

код инициализации

  QCamera * MyCamera= new QCamera(CameraDeviceName);
MyCamera->setCaptureMode( QCamera::CaptureVideo );

Label = new QLabel();
Label->setText("Label");

FrameProbe * VSurface = new FrameProbe();

MyCamera->setViewfinder(VSurface);

connect(VSurface, SIGNAL(frameAvailable(QImage)), this, SLOT(video_probed(QImage)));
connect(VSurface, SIGNAL(frameReady(QPixmap)), this,SLOT(video_forward(QPixmap)));

ui->gridLayout->addWidget(Label,0,0);

MyCamera->start();

и слоты

void MainWindow::video_probed(QImage InVideoFrame){

FramesProbed++;
std::cout<<FramesProbed<<std::endl;

}
void MainWindow::video_forward(QPixmap InVideoFrame){

Label->setPixmap(InVideoFrame); //<<<<<<<<< Segmentation Fault here
}

Если я изменю слот video_forward на что-то вроде этого

void MainWindow::video_forward(QPixmap InVideoFrame){

InVideoFrame.save("c:\\temp\\a.jpg",0,-1);
QPixmap a;
a.load("c:\\temp\\a.jpg");

Label->setPixmap(a);
}

это работает. Конечно медленно 🙂 но работа …

PS: В FrameProbe :: present изображение имеет формат QImage :: Format_RGB32.

0

Решение

Решение:

bool FrameProbe::present(const QVideoFrame &frame)
{
...
emit frameAvailable(image.copy());
...
}

// slot video_probed
connect(VSurface, &FrameProbe::frameAvailable, [=](QImage a){
Label->setPixmap(QPixmap::fromImage(a));
});

Так почему разбился

Потому что вы используете ниже, чтобы построить QImage:

QImage :: QImage (uchar * data, int width, int height, Format format,
QImageCleanupFunction cleanupFunction = Q_NULLPTR, void * cleanupInfo =
Q_NULLPTR)

Первый парам data устанавливается из cloneFrame и он будет выпущен после cloneFrame.unmap();, data не будет существовать в QLabel::paintEvent стек.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]