Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Crash when using QMediaPlayer with QAbstractVideoSurface



  • I'm developing an QtQuick application that needs to show previews(thumbnails) of video .mp4 files. For this I am using c++ as a backend. The idea is that the Controller class is used to loop through videos and with the help of QMediaPlayer, combined with the implementation of QAbstractVideoSurface class, go through the video frames and provide list of QImage objects in the end. The problem is that application crashes when I want to use setVideoOutput function to connect QMediaPlayer object with MyVideoSurface object (Inherits QAbstractVideoSurface class). The type of error is Debug Assertion Failed. When I comment the call to setVideoOutput function, application is working fine. I am using Qt 5.12.2 version with msvc2017_64 compiler on Windows 10 platform.
    Controller.h:

    class Controller : public QObject
    {
        Q_OBJECT
        ...
        private:
        QMediaPlayer* m_mediaPlayer;
        MyVideoSurface* myVidSurface;
        ...
    }
    

    Controller.cpp:

    Controller::Controller(QObject *parent):
        QObject(parent)
    {
        this->m_mediaPlayer = new QMediaPlayer(nullptr,QMediaPlayer::VideoSurface);
        this->myVidSurface=new MyVideoSurface();
        this->m_mediaPlayer->setVideoOutput(this->myVidSurface); //this is the problematic part
    }
    

    MyVideoSurface.h:

    #ifndef MYVIDEOSURFACE_H
    #define MYVIDEOSURFACE_H
    
    #endif // MYVIDEOSURFACE_H
    #include <QAbstractVideoSurface>
    #include <QVideoFrame>
    #include <QImage>
    #include <QPixmap>
    
    class MyVideoSurface : public QAbstractVideoSurface
    {
        Q_OBJECT
        public:
            explicit MyVideoSurface(QObject *parent = 0);
            void stop();
    
        public slots:
              void fnClearPixmap();
        private:
              QImage::Format imageFormat;
              QPixmap imageCaptured;
              QVideoFrame currentFrame;
    
              QList<QVideoFrame::PixelFormat> supportedPixelFormats(
                      QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
              bool isFormatSupported(const QVideoSurfaceFormat &format) const;
              bool start(const QVideoSurfaceFormat &format);
              bool present(const QVideoFrame &frame);
        signals:
            void fnSurfaceStopped(QPixmap pix);
    };
    

    MyVideoSurface.cpp:

    #include "MyVideoSurface.h"
    #include <qabstractvideosurface.h>
    #include <qvideosurfaceformat.h>
    
    MyVideoSurface::MyVideoSurface(QObject *parent)
        :QAbstractVideoSurface(parent)
        ,imageFormat(QImage::Format_Invalid)
    {
    
    }
    
    QList<QVideoFrame::PixelFormat> MyVideoSurface::supportedPixelFormats(
            QAbstractVideoBuffer::HandleType handleType) const
    {
        if (handleType == QAbstractVideoBuffer::NoHandle) {
            return QList<QVideoFrame::PixelFormat>()
                    << QVideoFrame::Format_RGB32
                    << QVideoFrame::Format_ARGB32
                    << QVideoFrame::Format_ARGB32_Premultiplied
                    << QVideoFrame::Format_RGB565
                    << QVideoFrame::Format_RGB555;
        } else {
            return QList<QVideoFrame::PixelFormat>();
        }
    }
    
    bool MyVideoSurface::isFormatSupported(const QVideoSurfaceFormat &format) const
    {
        const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
        const QSize size = format.frameSize();
    
        return imageFormat != QImage::Format_Invalid
                && !size.isEmpty()
                && format.handleType() == QAbstractVideoBuffer::NoHandle;
    }
    
    bool MyVideoSurface::start(const QVideoSurfaceFormat &format)
    {
        const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
        const QSize size = format.frameSize();
    
        if (imageFormat != QImage::Format_Invalid && !size.isEmpty()) {
            this->imageFormat = imageFormat;
            QAbstractVideoSurface::start(format);
            return true;
        } else {
            return false;
        }
    }
    
    void MyVideoSurface::stop()
    {
        QAbstractVideoSurface::stop();
    }
    
    void MyVideoSurface::fnClearPixmap()
    {
        imageCaptured = QPixmap();
    }
    
    bool MyVideoSurface::present(const QVideoFrame &frame)
    {
        if (surfaceFormat().pixelFormat() != frame.pixelFormat()
                || surfaceFormat().frameSize() != frame.size()) {
            setError(IncorrectFormatError);
            stop();
    
            return false;
        } else {
            if(!imageCaptured.isNull()){
                emit fnSurfaceStopped(imageCaptured);
            }
    
            currentFrame = frame;
            if (currentFrame.map(QAbstractVideoBuffer::ReadOnly)) {
    
                QImage image(
                        currentFrame.bits(),
                        currentFrame.width(),
                        currentFrame.height(),
                        currentFrame.bytesPerLine(),
                        imageFormat);
                if(imageCaptured.isNull()){
                    imageCaptured = QPixmap::fromImage(image.copy(image.rect()));
                }
                currentFrame.unmap();
            }
            return true;
        }
    }
    

    Error that appears:
    297d1af8-a1d7-40a3-bab5-848fe1be18fe-image.png

    or:

    97f2070f-03d5-41c7-aaac-75a43fd7cb16-image.png


Log in to reply