QT QLabel setPixmap from QAbstractVideoSurface

Multi tool use
Multi tool use


QT QLabel setPixmap from QAbstractVideoSurface



I'm implementing my own class for probing video frames from QCamera under windows. It's a subclass of QAbstractVideoSurface. So, my probe generates QPixmap which I tried to draw on QLabel (as viewfinder). And I've got segmentation fault on QLabel setPixmap call.



I'm sure my Qpixmap is well made, because I can save it on the disk with a save(). My QLabel is inititalized and works well, because I can load QPixmap from the disk and set it to QLabel. I guess there is problem with a format of a pixmap, but can't clue how to correct it :(



My code



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;
}



init code


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();



and slots


void MainWindow::video_probed(QImage InVideoFrame){

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

}
void MainWindow::video_forward(QPixmap InVideoFrame){

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



If I change video_forward slot to something like this


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



it work. Of course slow :) but work...



PS: In the FrameProbe::present image have QImage::Format_RGB32 format.





Have you tried using valgrind? It is very helpful to see exactly what resource was accessed while not allocated.
– Benjamin Barrois
Jul 1 at 10:05





The problem is likely with implicit sharing of QPixmap internal data: doc.qt.io/qt-5/implicit-sharing.html. See video_forward function and there you have QPixmap object destroyed while leaving the function and it is shared with label. Also avoid sending objects by value as you do unless you sure. Better use const T& as Qt does if possible.
– Alexander V
Jul 1 at 16:24





@AlexanderV yes, it was my problem. Any actions which made a real copy of the Pixmap solves the problem.
– Abbey Road
Jul 3 at 10:43





1 Answer
1



Solution:


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

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



So why crashed:



Because you are using below to construct QImage:


QImage



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



The first param data is set from cloneFrame and it will be released after cloneFrame.unmap();. data won't exist in the QLabel::paintEvent stack.


data


cloneFrame


cloneFrame.unmap();


data


QLabel::paintEvent





Thank you! This is just sandbox, not a real application. I just separate QImage for later image processing and QPixmap for display as viewfinder in different slots.
– Abbey Road
Jul 2 at 10:48





@AbbeyRoad I see, The solution sending image.copy() didn't work?
– Jiu
Jul 3 at 0:20


image.copy()





image.copy() work like a charm. And any other solutions which made a real copy of data (e.g not implicit shared copy).
– Abbey Road
Jul 3 at 10:41






@AbbeyRoad image.copy() is copy the data of QImage...I didn't see other ways...
– Jiu
yesterday


image.copy()


QImage






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

coL4IpmKpJv1a,fDCoup2iWAIjh,7OQBLREj,KVqvd oxJFpg0 Gni0,YSKoZCnLLh,O0g
58uEh3W,Qukri,fp CWmOEz

Popular posts from this blog

PySpark - SparkContext: Error initializing SparkContext File does not exist

django NoReverseMatch Exception

List of Kim Possible characters