在Qt/QML中的每一帧更新图像时运行时崩溃

Runtime crash when updating an image at each frame in Qt/QML

本文关键字:更新 一帧 图像 崩溃 运行时 QML Qt      更新时间:2023-10-16

应用程序运行良好,随机崩溃,调试器显示此错误:

0xc0000005:读取访问违规,

QOpenGLFunctions_3_2_兼容性::glBeginTransformFeedBack

但这并没有多大帮助,因为我不知道这个函数在哪里使用。

通过测试,我认为问题出在图像显示上。该程序从连接到相机的远程设备中检索原始数据,应用程序正在显示该数据,以在QML应用程序中显示视频。例如,当我在QML中评论图像的来源时,它不会崩溃。

在线程中:

bool success;
DWORD bytesRead;
DWORD lastError;
const unsigned int imgSize = IMG_HEIGHT * IMG_WIDTH * 1;
_rawData = new uchar[imgSize];
while(!_abort)
{
    if(_namedPipe != INVALID_HANDLE_VALUE)
    {
        /* Get raw data from the pipe */
        success = ReadFile(
            _namedPipe,
            _rawData,
            imgSize,
            &bytesRead,
            NULL);
        if(success)
        {
            /* Build an image from the raw data and send it to the PipeVideoStreamPlayer */
            QImage clImage(_rawData, IMG_WIDTH, IMG_HEIGHT, QImage::Format_Indexed8);
            _videostr->updateImage(clImage);
        }else
...

图像提供商:

PipeVideoStreamPlayer::PipeVideoStreamPlayer(QQuickView* ptrApp)
: QQuickView(),
  QQuickImageProvider(QQmlImageProviderBase::Image)
{
    _ptrApp = ptrApp;
}

更新功能:

void
PipeVideoStreamPlayer::updateImage(const QImage& image)
{
   _myImage = image;
    QObject* objMain = (QObject*) _ptrApp->rootObject();
    QQuickItem *obj = objMain->findChild<QQuickItem*>("videoStreamFrame");
    QMetaObject::invokeMethod(obj, "reload");
}

在QML中,每帧调用的图像+重载函数:

Image {
    objectName: "videoStreamFrame"
    cache: false
    anchors.centerIn: parent
    source: "image://videostream/yellow"
    function reload() {
        var oldSource = source;
        source = "";
        source = oldSource;
    }

该应用程序在崩溃前可以运行5分钟,有时只需10秒。如果我评论重载函数,它也不会崩溃。

编辑:

以下是我迄今为止所做的修改:

class StreamPainter : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QImage streamImage READ streamImage WRITE setStreamImage NOTIFY streamImageChanged)
public:
    StreamPainter(QObject *parent = 0);
    ~StreamPainter();
    QImage streamImage();
    void setStreamImage(QImage clImage);
signals:
    void streamImageChanged(QImage Image);
public slots:
private:
    QImage _streamImage;
};
QImage StreamPainter::streamImage()
{
    return _streamImage;
}
void StreamPainter::setStreamImage(QImage clImage)
{
    _streamImage = clImage;
    emit streamImageChanged(clImage);
}

设置上下文:

view->engine()->rootContext()->setContextProperty("streamImage", streamImage);

在我的线程中:

QImage clImage(_rawData, IMG_WIDTH, IMG_HEIGHT, QImage::Format_Indexed8);
_spvideostr->setStreamImage(clImage);

现在我需要在QML中显示图像,但如果没有ImageProvider,如何在这里显示?

我没有真正更改代码来显示图像,我认为在我的程序中如何使用thread会带来很多问题,但目前我通过在QML调用的request函数中的私有_myImage变量周围使用mutex和线程调用的updateImage来解决问题:

QImage PipeVideoStreamPlayer::requestImage(const QString & id, QSize * size, const QSize & requestedSize)
 {
    Q_UNUSED(id)
    Q_UNUSED(size)
    Q_UNUSED(requestedSize)
    _mutex.lock();
    _prevImage = _myImage;
    _mutex.unlock();
    return _prevImage;
 }

_myImage被锁定时,我发送上一个图像。由于这种情况不常发生,我应该不时地丢失一些帧,但它不会被看到。

void
PipeVideoStreamPlayer::updateImage(const QImage& image)
{
    _mutex.lock();
   _myImage = image;
   _mutex.unlock();
    QObject* objMain = (QObject*) _ptrApp->rootObject();
    QQuickItem *obj = objMain->findChild<QQuickItem*>("videoStreamFrame");
    QMetaObject::invokeMethod(obj, "reload");
}