📜 ⬆️ ⬇️

A simple way to connect an arbitrary video source in Qml

Preamble


All of the following is given in the context of Qt version 5.3.1 (as the most relevant at the moment), but it makes sense in the context of any version of the 5.x branch, and perhaps even 4.8.x (did not check as unnecessary).

Operating system - Windows, development environment - QtCreator 3.1.2 in conjunction with MinGW and gcc 4.8.2 The essence does not change from using other platforms / IDE / compilers.

The simplest of the available options was chosen as the video source, namely, the desktop. Those. The application will display a copy of everything that happens on the desktop. In multi-monitor configurations, we will use the main screen as the source.

So let's get started


As a starting point, you can read the documentation: "Video Overview: Working with Low Level Video Frames" .
')
A few theses that need to be gleaned from this article:



Write the code


Create a new project “Qt Quick Application”. It is important to select this type of application type, since in the future we will create a Qml component using C ++.

Next, create a class, a descendant of QObject, and start expanding it.

As a result, it’s quite simple and laconic, I won’t pour a lot of water, but I’ll just give the code, with some comments:

DesktopVideoProducer.h:

#pragma once #include <QAbstractVideoSurface> #include <QVideoSurfaceFormat> class DesktopVideoProducer : public QObject { Q_OBJECT public: //         Qml    static void registerQmlType(); explicit DesktopVideoProducer( QObject *parent = 0 ); ~DesktopVideoProducer(); //  property,   Q_PROPERTY( QAbstractVideoSurface* videoSurface READ videoSurface WRITE setVideoSurface ) QAbstractVideoSurface* videoSurface() const; void setVideoSurface( QAbstractVideoSurface* s ); protected: void timerEvent( QTimerEvent* ); private: void closeSurface(); private: QAbstractVideoSurface* _surface; QVideoSurfaceFormat _format; }; 

DesktopVideoProducer.cpp:
 #include "DesktopVideoProducer.h" #include <QtQml/qqml.h> #include <QApplication> #include <QScreen> #include <QDesktopWidget> void DesktopVideoProducer::registerQmlType() { //      DesktopVideoProducer, //  0.1,   DesktopVideoProducer. //       QtCreator, //   . // @uri DesktopVideoProducer qmlRegisterType<DesktopVideoProducer>( "DesktopVideoProducer", 0, 1, "DesktopVideoProducer" ); } DesktopVideoProducer::DesktopVideoProducer( QObject *parent ) : QObject( parent ), _surface( 0 ) { startTimer( 1000 / 15 ); //15 fps } DesktopVideoProducer::~DesktopVideoProducer() { closeSurface(); } QAbstractVideoSurface* DesktopVideoProducer::videoSurface() const { return _surface; } void DesktopVideoProducer::setVideoSurface( QAbstractVideoSurface* s ) { closeSurface(); _surface = s; } void DesktopVideoProducer::closeSurface() { if( _surface && _surface->isActive() ) _surface->stop(); } void DesktopVideoProducer::timerEvent( QTimerEvent* ) { if( !_surface ) return; QScreen* screen = QGuiApplication::primaryScreen(); QDesktopWidget* desktop = QApplication::desktop(); if( !screen || !desktop ) return; // screenshot        QVideoFrame QPixmap screenPixmap = screen->grabWindow( desktop->screen()->winId() ); QImage screenImage = screenPixmap.toImage(); QVideoFrame::PixelFormat pixelFormat = QVideoFrame::pixelFormatFromImageFormat( screenImage.format() ); //    -   (   )- //  ()  surface if( screenPixmap.size() != _format.frameSize() || pixelFormat != _format.pixelFormat() ) { closeSurface(); _format = QVideoSurfaceFormat( screenPixmap.size(), pixelFormat ); _surface->start( _format ); } //     _surface->present( QVideoFrame( screenImage ) ); } 

main.qml:
 import QtQuick 2.2 import QtQuick.Window 2.1 import QtMultimedia 5.0 import DesktopVideoProducer 0.1 Window { visible: true width: 360 height: 360 DesktopVideoProducer { id: videoProducer; } VideoOutput { anchors.fill: parent; source: videoProducer; } } 


main.cpp:
 #include <QApplication> #include <QQmlApplicationEngine> #include"DesktopVideoProducer.h" int main(int argc, char *argv[]) { // DesktopVideoProducer    Qml DesktopVideoProducer::registerQmlType(); //   QApplication::desktop() QGuiApplication  //QGuiApplication app(argc, argv); QApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); return app.exec(); } 


PS: The complete project is available for download from GitHub .

Source: https://habr.com/ru/post/229747/


All Articles