QML Desktop Streaming



  • Hi, I have the following problem: I need to capture part of the desktop, specifically of the second monitor, given an x, an y, the width and the height. My question is: is it possible to stream a part of desktop and show it inside a box in a qml project.
    My first thought is to somehow find a c++ function that allows to do screenshot of my second monitor and after importing it inside qml I would call it like every 0.2 seconds with Timer to do screenshot and show it in a box in QML.

    Thank you.



  • You can use QScreen::grabWindow for that.

    To use that in QML, you could feed this in a VideoOutput.

    To do that you would have to put your QObject derived class instance as the source of the VideoOutput : http://doc.qt.io/qt-5/qml-qtmultimedia-videooutput.html#source-prop
    Your class needs to have a Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface WRITE setVideoSurface NOTIFY videoSurfaceChange)

    In your setVideoSurface method, you need to call the start method of QAbstractVideoSurface with a correct format (your size and the pixelformat, pixelformat should be QVideoFrame::Format_ARGB32 for desktop I guess).

    And then when you want to update the VideoOutput (via a QTimer for example), you call the present method of QAbstractVideoSurface with a QVideoFrame you constructed from the QPixmap you got in QScreen::grabWindow.



  • Thank you for the instructions, I'm new to all of this so I hope to get to the bottom of this :D



  • Hi, I need some help. I really don't have idea how to do it. This is what I have done so far:
    videostream.h

    #ifndef VIDEOSTREAM_H
    #define VIDEOSTREAM_H
    #include <QObject>
    #include <QAbstractVideoSurface>
    
    class videoStream: public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface WRITE setVideoSurface NOTIFY videoSurfaceChange)
    
    public:
    
        explicit videoStream(QObject *parent = nullptr);
        QAbstractVideoSurface* videoSurface();
        void setVideoSurface(const QAbstractVideoSurface &videoSurface);
        void updateScreen();
    
    signals:
        void videoSurfaceChange();
    
    private:
        QAbstractVideoSurface* m_videoSurface;
    };
    
    #endif // VIDEOSTREAM_H
    
    

    videoStream.cpp

    #include "videostream.h"
    #include <QVideoSurfaceFormat>
    #include <QSize>
    #include <QGuiApplication>
    #include <QWidget>
    #include <QWindow>
    
    videoStream::videoStream(QObject *parent):
        QObject(parent)
    {
    
    }
    QAbstractVideoSurface* videoStream::videoSurface()
    {
        return m_videoSurface;
    }
    
    void videoStream::setVideoSurface(const QAbstractVideoSurface &videoSurface)
    {
        QVideoSurfaceFormat* qvideosurfaceformat;
        qvideosurfaceformat=new QVideoSurfaceFormat(QSize(800,600),QVideoFrame::Format_ARGB32);
    
        videoSurface.start(&qvideosurfaceformat);
    
    }
    
    void videoStream::updateScreen(){
        QScreen *screen = QGuiApplication::primaryScreen();
        if (QWindow *window = QWidget::windowHandle())
            screen = window->QWindow::screen();
        if (!screen)
            return;
    
        m_videoSurface->present(screen->grabWindow(0));
    }
    
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include "videostream.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<BackEnd>("videostream", 1, 0, "VideoStream");
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    
    

    main.qml

    import QtQuick 2.9
    import QtQuick.Window 2.2
    import QtMultimedia 5.9
    import videostream 1.0
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        VideoStream{
            id:video_stream
        }
    
        Rectangle {
            width: 800
            height: 600
    
            VideoOutput {
                id: videoOutput
                source: video_stream.videoStream
                anchors.fill: parent
            }
        }
    Timer {
            interval: 500; running: true; repeat: true
            onTriggered: video_stream.updateScreen
      }
    }
    
    

    A part from errors with these lines

    videoSurface.start(&qvideosurfaceformat);
    
    if (QWindow *window = QWidget::windowHandle())
    
    m_videoSurface->present(screen->grabWindow(0));
    

    I have no idea what should I do



  • Nevermind, thanks anyway. I simply solved it by using QScreen::grabWindow inside QQuickImageProvider and with a Timer inside QML I request and show the image every 33ms to have 30 frames per second of the screen.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.