diff options
author | Artem Dyomin <artem.dyomin@qt.io> | 2023-05-12 17:49:13 +0200 |
---|---|---|
committer | Artem Dyomin <artem.dyomin@qt.io> | 2023-06-02 13:12:21 +0200 |
commit | 24c854fff9af00461b0920074b23d156e345a804 (patch) | |
tree | 6f71d2c9a8e1b76d12eaa2e25e7da839bad02d5c /src | |
parent | dda06373eba84999a89e539035860fc45f2fa5f5 (diff) |
Add QWindowCapure and QCapturableWindow for window capturing
The design of QMediaCaptureSession already uses different types and
setters/gettes for each video source, like QCamera, QImageCapture,
and QScreenCapture, so a new source type, QWindowCapure, has been
added instead of extending QScreenCapture.
For now we only cover the case of capturing windows enumerated though
the capturing API itself, via a list of QCapturableWindow instances,
as this is considered the primary use-case for such an API.
An extension to this would be to add a QWindow overload to either
QCapturableWindow's constructor or QWindowCapture::setWindow, to
allow capturing of windows in the application itself, either created
by Qt, or via QWindow::fromWinId(), but this has been left out
for the initial API to keep things minimal.
A WId overload has been intentionally left out of this API, as
the path for capturing by WId should go via QWindow::fromWinId().
Finally, capture of windows from other applications without
enumerating them via QWindowCapure is left out, as adding such
an API would require us to build a more generic WId replacement
that isn't tied to a single type for each OS, like WId is (it's
a NSView* on macOS e.g., but windows can also be represented by
CGWindowID).
Task-number: QTBUG-103226
Change-Id: I99e3b8bde62250aba35abcedbc8680a299a3cbb2
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src')
17 files changed, 571 insertions, 136 deletions
diff --git a/src/multimedia/CMakeLists.txt b/src/multimedia/CMakeLists.txt index 1cdbd5927..cd70634f2 100644 --- a/src/multimedia/CMakeLists.txt +++ b/src/multimedia/CMakeLists.txt @@ -63,6 +63,8 @@ qt_internal_add_module(Multimedia recording/qmediacapturesession.cpp recording/qmediacapturesession.h recording/qmediarecorder.cpp recording/qmediarecorder.h recording/qmediarecorder_p.h recording/qscreencapture.cpp recording/qscreencapture.h + recording/qwindowcapture.cpp recording/qwindowcapture.h + recording/qcapturablewindow.cpp recording/qcapturablewindow.h recording/qcapturablewindow_p.h video/qabstractvideobuffer.cpp video/qabstractvideobuffer_p.h video/qmemoryvideobuffer.cpp video/qmemoryvideobuffer_p.h video/qvideoframe.cpp video/qvideoframe.h diff --git a/src/multimedia/platform/qplatformmediaintegration_p.h b/src/multimedia/platform/qplatformmediaintegration_p.h index 27f00cdc0..6f60208de 100644 --- a/src/multimedia/platform/qplatformmediaintegration_p.h +++ b/src/multimedia/platform/qplatformmediaintegration_p.h @@ -16,6 +16,7 @@ #include <private/qtmultimediaglobal_p.h> #include <private/qmultimediautils_p.h> +#include <qcapturablewindow.h> #include <qmediarecorder.h> #include <qstring.h> @@ -47,6 +48,7 @@ class QAudioOutput; class QPlatformAudioInput; class QPlatformAudioOutput; class QPlatformVideoDevices; +class QCapturableWindow; class Q_MULTIMEDIA_EXPORT QPlatformMediaIntegration { @@ -76,6 +78,10 @@ public: virtual QMaybe<QPlatformVideoSink *> createVideoSink(QVideoSink *) { return notAvailable; } + virtual QList<QCapturableWindow> capturableWindows() { return {}; }; + + bool isCapturableWindowValid(const QCapturableWindowPrivate &) { return false; } + protected: std::unique_ptr<QPlatformVideoDevices> m_videoDevices; }; diff --git a/src/multimedia/platform/qplatformscreencapture.cpp b/src/multimedia/platform/qplatformscreencapture.cpp index de7f74d9d..afb1a6c78 100644 --- a/src/multimedia/platform/qplatformscreencapture.cpp +++ b/src/multimedia/platform/qplatformscreencapture.cpp @@ -16,7 +16,7 @@ QPlatformScreenCapture::QPlatformScreenCapture(QScreenCapture *screenCapture) void QPlatformScreenCapture::setWindow(QWindow *w) { if (w) { - emit m_screenCapture->errorOccurred(QScreenCapture::WindowCapturingNotSupported, + emit m_screenCapture->errorOccurred(QScreenCapture::InternalError, QLatin1String("Window capture is not supported")); } } @@ -29,7 +29,7 @@ QWindow *QPlatformScreenCapture::window() const void QPlatformScreenCapture::setWindowId(WId id) { if (id) { - emit m_screenCapture->errorOccurred(QScreenCapture::WindowCapturingNotSupported, + emit m_screenCapture->errorOccurred(QScreenCapture::InternalError, QLatin1String("Window capture is not supported")); } } diff --git a/src/multimedia/platform/qplatformscreencapture_p.h b/src/multimedia/platform/qplatformscreencapture_p.h index b5a865e22..a162fc7e6 100644 --- a/src/multimedia/platform/qplatformscreencapture_p.h +++ b/src/multimedia/platform/qplatformscreencapture_p.h @@ -32,9 +32,11 @@ public: virtual void setScreen(QScreen *s) = 0; virtual QScreen *screen() const = 0; + // TODO: move the methods and implementations to QPlatformWindowCapture virtual void setWindow(QWindow *w); virtual QWindow *window() const; + // to be removed virtual void setWindowId(WId id); virtual WId windowId() const; diff --git a/src/multimedia/recording/qcapturablewindow.cpp b/src/multimedia/recording/qcapturablewindow.cpp new file mode 100644 index 000000000..0be0208ff --- /dev/null +++ b/src/multimedia/recording/qcapturablewindow.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qcapturablewindow.h" +#include "qcapturablewindow_p.h" +#include "qplatformmediaintegration_p.h" + +QT_BEGIN_NAMESPACE + +QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCapturableWindowPrivate) + +/*! + \class QCapturableWindow + \inmodule QtMultimedia + \ingroup multimedia + \ingroup multimedia_video + \since 6.6 + + \brief Used for getting the basic information of a capturable window. + + The class contains a set of window information, except the method + QCapturableWindow::isValid which pulls the current state + whenever it's called. + + \sa QWindowCapture +*/ +/*! + \qmlvaluetype CapturableWindow + \instantiates QCapturableWindow + \brief The CapturableWindow type is used getting basic + of a window that is available for capturing via WindowCapture. + + \inqmlmodule QtMultimedia + \ingroup multimedia_qml + \ingroup multimedia_video_qml + + The class contains a dump of window information, except the property + 'isValid' which pulls the actual window state every time. + + \sa WindowCapture +*/ + +/*! + \fn QCapturableWindow::QCapturableWindow(QCapturableWindow &&other) + + Constructs a QCapturableWindow by moving from \a other. +*/ + +/*! + \fn void QCapturableWindow::swap(QCapturableWindow &other) noexcept + + Swaps the current window information with \a other. +*/ + +/*! + \fn QCapturableWindow &QCapturableWindow::operator=(QCapturableWindow &&other) + + Moves \a other into this QCapturableWindow. +*/ + +/*! + Constructs a null capturable window information that doesn't refer to any window. +*/ +QCapturableWindow::QCapturableWindow() = default; + +/*! + Destroys the window information. + */ +QCapturableWindow::~QCapturableWindow() = default; + +/*! + Construct a new window information using \a other QCapturableWindow. +*/ +QCapturableWindow::QCapturableWindow(const QCapturableWindow &other) = default; + +/*! + Assigns the \a other window information to this QCapturableWindow. +*/ +QCapturableWindow& QCapturableWindow::operator=(const QCapturableWindow &other) = default; + +/*! + Returns \c true if current window information and \a other refer to the same window, + otherwise returns \c false. +*/ +bool QCapturableWindow::operator==(const QCapturableWindow &other) const +{ + return d == other.d || (d && other.d && d->id == other.d->id); +} + +/*! + Returns \c true if current window information and \a other refer to different windows, + otherwise returns \c false. +*/ +bool QCapturableWindow::operator!=(const QCapturableWindow &other) const +{ + return !(*this == other); +} + +/*! + \qmlproperty string QtMultimedia::QCapturableWindow::isValid + + This property identifies whether a window information is valid. + + An invalid window information refers to non-existing window or doesn't refer to any one. +*/ + +/*! + Identifies whether a window information is valid. + + An invalid window information refers to non-existing window or doesn't refer to any one. + + Returns true if the window is valid, and false if it is not. +*/ +bool QCapturableWindow::isValid() const +{ + return d && QPlatformMediaIntegration::instance()->isCapturableWindowValid(*d); +} + +/*! + \qmlproperty string QtMultimedia::QCapturableWindow::description + + This property holds the description of the reffered window. +*/ + +/*! + Returns a description of the window. In most cases it represents the window title. +*/ +QString QCapturableWindow::description() const +{ + return d ? d->description : QString{}; +} + +QCapturableWindow::QCapturableWindow(QCapturableWindowPrivate *capturablePrivate) + : d(capturablePrivate) +{ +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QCapturableWindow &window) +{ + dbg << QString::fromUtf8("Capturable window '%1'").arg(window.description()); + return dbg; +} +#endif + + +QT_END_NAMESPACE + +#include "moc_qcapturablewindow.cpp" diff --git a/src/multimedia/recording/qcapturablewindow.h b/src/multimedia/recording/qcapturablewindow.h new file mode 100644 index 000000000..56fc673a0 --- /dev/null +++ b/src/multimedia/recording/qcapturablewindow.h @@ -0,0 +1,62 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QCAPTURABLEWINDOW_H +#define QCAPTURABLEWINDOW_H + +#include <QtMultimedia/qtmultimediaglobal.h> +#include <QtCore/qmetatype.h> +#include <QtCore/qshareddata.h> + +QT_BEGIN_NAMESPACE + +class QCapturableWindowPrivate; +QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QCapturableWindowPrivate, Q_MULTIMEDIA_EXPORT) + +class QMediaCaptureSession; +class QWindowCapturePrivate; + +class Q_MULTIMEDIA_EXPORT QCapturableWindow +{ + Q_GADGET + Q_PROPERTY(QString description READ description CONSTANT) + Q_PROPERTY(bool isValid READ isValid CONSTANT) +public: + QCapturableWindow(); + + ~QCapturableWindow(); + + QCapturableWindow(const QCapturableWindow &other); + + QCapturableWindow(QCapturableWindow &&other) noexcept = default; + + QCapturableWindow& operator=(const QCapturableWindow &other); + + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCapturableWindow); + + void swap(QCapturableWindow &other) noexcept + { d.swap(other.d); } + + bool operator==(const QCapturableWindow &other) const; + + bool operator!=(const QCapturableWindow &other) const; + + bool isValid() const; + + QString description() const; + +private: + QCapturableWindow(QCapturableWindowPrivate *capturablePrivate); + + QExplicitlySharedDataPointer<QCapturableWindowPrivate> d; +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, const QCapturableWindow &); +#endif + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QCapturableWindow) + +#endif // QCAPTURABLEWINDOW_H diff --git a/src/multimedia/recording/qcapturablewindow_p.h b/src/multimedia/recording/qcapturablewindow_p.h new file mode 100644 index 000000000..f4c370def --- /dev/null +++ b/src/multimedia/recording/qcapturablewindow_p.h @@ -0,0 +1,33 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QCAPTURABLEWINDOW_P_H +#define QCAPTURABLEWINDOW_P_H + +#include <QtGui/qwindowdefs.h> +#include <QtCore/QSharedData> + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class QCapturableWindowPrivate : public QSharedData { +public: + using Id = size_t; + + QString description; + Id id = 0; +}; + +QT_END_NAMESPACE + +#endif // QCAPTURABLEWINDOW_P_H diff --git a/src/multimedia/recording/qmediacapturesession.cpp b/src/multimedia/recording/qmediacapturesession.cpp index 97b62b38e..45e8bb98a 100644 --- a/src/multimedia/recording/qmediacapturesession.cpp +++ b/src/multimedia/recording/qmediacapturesession.cpp @@ -8,6 +8,7 @@ #include "qimagecapture.h" #include "qvideosink.h" #include "qscreencapture.h" +#include "qwindowcapture.h" #include <qpointer.h> @@ -27,6 +28,7 @@ public: QAudioOutput *audioOutput = nullptr; QCamera *camera = nullptr; QScreenCapture *screenCapture = nullptr; + QWindowCapture *windowCapture = nullptr; QImageCapture *imageCapture = nullptr; QMediaRecorder *recorder = nullptr; QVideoSink *videoSink = nullptr; @@ -45,7 +47,6 @@ public: captureSession->setVideoPreview(sink); emit q->videoOutputChanged(); } - }; /*! @@ -59,14 +60,16 @@ public: The QMediaCaptureSession is the central class that manages capturing of media on the local device. - You can connect a camera and a microphone to QMediaCaptureSession using setCamera() and setAudioInput(). - A preview of the captured media can be seen by setting a QVideoSink of QVideoWidget using setVideoOutput() - and heard by routing the audio to an output device using setAudioOutput(). + You can connect a video input to QMediaCaptureSession using setCamera(), setScreenCapture() or setWindowCapture(). + A preview of the captured media can be seen by setting a QVideoWidget or QGraphicsVideoItem using setVideoOutput(). + + You can connect a microphone to QMediaCaptureSession using setAudioInput(). + The captured sound can be heard by routing the audio to an output device using setAudioOutput(). You can capture still images from a camera by setting a QImageCapture object on the capture session, and record audio/video using a QMediaRecorder. - \sa QCamera, QAudioDevice, QMediaRecorder, QImageCapture, QMediaRecorder + \sa QCamera, QAudioDevice, QMediaRecorder, QImageCapture, QScreenCapture, QWindowCapture, QMediaRecorder, QGraphicsVideoItem */ /*! @@ -85,9 +88,12 @@ public: Connect a camera and a microphone to a CaptureSession by assigning Camera and AudioInput objects to the relevant properties. - Capture a screen or window view by connecting a ScreenCapture object to + Capture a screen by connecting a ScreenCapture object to the screenCapture property. + Capture a window by connecting a WindowCapture object to + the windowCapture property. + Enable a preview of the captured media by assigning a VideoOutput element to the videoOutput property. @@ -116,7 +122,7 @@ public: } \endqml - \sa Camera, MediaDevices, MediaRecorder, ImageCapture, AudioInput, VideoOutput + \sa Camera, MediaDevices, MediaRecorder, ImageCapture, ScreenCapture, WindowCapture, AudioInput, VideoOutput */ /*! @@ -204,7 +210,7 @@ void QMediaCaptureSession::setAudioInput(QAudioInput *input) \brief The camera used to capture video. Record video or take images by adding a camera to the capture session - using this property, + using this property. */ QCamera *QMediaCaptureSession::camera() const { @@ -238,9 +244,9 @@ void QMediaCaptureSession::setCamera(QCamera *camera) \qmlproperty ScreenCapture QtMultimedia::CaptureSession::screenCapture \since 6.5 - \brief The object used to capture a window or screen view. + \brief The object used to capture a screen. - Record a screen or window view by adding a screen capture objet + Record a screen by adding a screen capture objet to the capture session using this property. */ @@ -248,9 +254,9 @@ void QMediaCaptureSession::setCamera(QCamera *camera) \property QMediaCaptureSession::screenCapture \since 6.5 - \brief The object used to capture a window or screen view. + \brief The object used to capture a screen. - Record a screen or window view by adding a screen capture objet + Record a screen by adding a screen capture object to the capture session using this property. */ QScreenCapture *QMediaCaptureSession::screenCapture() @@ -280,6 +286,34 @@ void QMediaCaptureSession::setScreenCapture(QScreenCapture *screenCapture) } emit screenCaptureChanged(); } + +/*! + \qmlproperty WindowCapture QtMultimedia::CaptureSession::windowCapture + \since 6.6 + + \brief The object used to capture a window. + + Record a window by adding a window capture object + to the capture session using this property. +*/ + +/*! + \property QMediaCaptureSession::windowCapture + \since 6.6 + + \brief The object used to capture a window. + + Record a window by adding a window capture objet + to the capture session using this property. +*/ +QWindowCapture *QMediaCaptureSession::windowCapture() { + return d_ptr ? d_ptr->windowCapture : nullptr; +} + +void QMediaCaptureSession::setWindowCapture(QWindowCapture *) { + // TODO: implement +} + /*! \qmlproperty ImageCapture QtMultimedia::CaptureSession::imageCapture diff --git a/src/multimedia/recording/qmediacapturesession.h b/src/multimedia/recording/qmediacapturesession.h index daef2a3ab..c613c3615 100644 --- a/src/multimedia/recording/qmediacapturesession.h +++ b/src/multimedia/recording/qmediacapturesession.h @@ -18,6 +18,7 @@ class QMediaRecorder; class QPlatformMediaCaptureSession; class QVideoSink; class QScreenCapture; +class QWindowCapture; class QMediaCaptureSessionPrivate; class Q_MULTIMEDIA_EXPORT QMediaCaptureSession : public QObject @@ -28,6 +29,8 @@ class Q_MULTIMEDIA_EXPORT QMediaCaptureSession : public QObject Q_PROPERTY(QCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged) Q_PROPERTY( QScreenCapture *screenCapture READ screenCapture WRITE setScreenCapture NOTIFY screenCaptureChanged) + Q_PROPERTY( + QWindowCapture *windowCapture READ windowCapture WRITE setWindowCapture NOTIFY windowCaptureChanged) Q_PROPERTY(QImageCapture *imageCapture READ imageCapture WRITE setImageCapture NOTIFY imageCaptureChanged) Q_PROPERTY(QMediaRecorder *recorder READ recorder WRITE setRecorder NOTIFY recorderChanged) Q_PROPERTY(QObject *videoOutput READ videoOutput WRITE setVideoOutput NOTIFY videoOutputChanged) @@ -47,6 +50,9 @@ public: QScreenCapture *screenCapture(); void setScreenCapture(QScreenCapture *screenCapture); + QWindowCapture *windowCapture(); + void setWindowCapture(QWindowCapture *windowCapture); + QMediaRecorder *recorder(); void setRecorder(QMediaRecorder *recorder); @@ -65,6 +71,7 @@ Q_SIGNALS: void audioInputChanged(); void cameraChanged(); void screenCaptureChanged(); + void windowCaptureChanged(); void imageCaptureChanged(); void recorderChanged(); void videoOutputChanged(); diff --git a/src/multimedia/recording/qscreencapture.cpp b/src/multimedia/recording/qscreencapture.cpp index bd687b8eb..864fcf779 100644 --- a/src/multimedia/recording/qscreencapture.cpp +++ b/src/multimedia/recording/qscreencapture.cpp @@ -22,28 +22,26 @@ public: \ingroup multimedia_video \since 6.5 - \brief The QScreenCapture class is used for capturing a screen or - a window. + \brief This class is used for capturing a screen. - The class captures a screen or window. It is managed by - the QMediaCaptureSession class where the captured view can be displayed - in a window or recorded to a file. + The class captures a screen. It is managed by + the QMediaCaptureSession class where the captured screen can be displayed + in a video preview object or recorded to a file. \snippet multimedia-snippets/media.cpp Media recorder */ /*! \qmltype ScreenCapture \instantiates QScreenCapture - \brief The ScreenCapture type is used for capturing a screen or - a window. + \brief This type is used for capturing a screen. \inqmlmodule QtMultimedia \ingroup multimedia_qml \ingroup multimedia_video_qml - ScreenCapture captures a screen or a window. It is managed by - MediaCaptureSession where the captured view can be displayed in a window - or recorded to a file. + ScreenCapture captures a screen. It is managed by + MediaCaptureSession where the captured screen can be displayed + in a video preview object or recorded to a file. \since 6.5 The code below shows a simple capture session with ScreenCapture playing @@ -91,10 +89,8 @@ QScreenCapture::~QScreenCapture() \value NoError No error \value InternalError Internal screen capturing driver error \value CapturingNotSupported Capturing is not supported - \value WindowCapturingNotSupported Window capturing is not supported. - This enum value was added in Qt 6.6. - \value CaptureFailed Capturing screen or window view failed - \value NotFound Selected screen or window not found + \value CaptureFailed Capturing screen failed + \value NotFound Selected screen not found */ /*! @@ -111,68 +107,6 @@ QMediaCaptureSession *QScreenCapture::captureSession() const } /*! - \qmlproperty Window QtMultimedia::ScreenCapture::window - Describes the window for capturing. - - \since 6.6 -*/ - -/*! - \property QScreenCapture::window - \brief the window for capturing. - - \since 6.6 -*/ -void QScreenCapture::setWindow(QWindow *window) -{ - Q_D(QScreenCapture); - - if (d->platformScreenCapture) { - d->platformScreenCapture->setScreen(nullptr); - d->platformScreenCapture->setWindowId(0); - d->platformScreenCapture->setWindow(window); - } -} - -QWindow *QScreenCapture::window() const -{ - Q_D(const QScreenCapture); - - return d->platformScreenCapture ? d->platformScreenCapture->window() - : nullptr; -} - -/*! - \qmlproperty Window QtMultimedia::ScreenCapture::windowId - Describes the window ID for capturing. -*/ - -/*! - \property QScreenCapture::windowId - \brief the window ID for capturing. - - \since 6.6 -*/ -void QScreenCapture::setWindowId(WId id) -{ - Q_D(QScreenCapture); - - if (d->platformScreenCapture) { - d->platformScreenCapture->setScreen(nullptr); - d->platformScreenCapture->setWindow(nullptr); - d->platformScreenCapture->setWindowId(id); - } -} - -WId QScreenCapture::windowId() const -{ - Q_D(const QScreenCapture); - - return d->platformScreenCapture ? d->platformScreenCapture->windowId() - : 0; -} - -/*! \qmlproperty bool QtMultimedia::ScreenCapture::active Describes whether the capturing is currently active. */ @@ -197,7 +131,7 @@ bool QScreenCapture::isActive() const } /*! - \qmlproperty bool QtMultimedia::ScreenCapture::screen + \qmlproperty Screen QtMultimedia::ScreenCapture::screen Describes the screen for capturing. */ diff --git a/src/multimedia/recording/qscreencapture.h b/src/multimedia/recording/qscreencapture.h index 4dc2cc1d3..e99e71921 100644 --- a/src/multimedia/recording/qscreencapture.h +++ b/src/multimedia/recording/qscreencapture.h @@ -13,7 +13,6 @@ QT_BEGIN_NAMESPACE - class QMediaCaptureSession; class QPlatformScreenCapture; class QScreenCapturePrivate; @@ -22,8 +21,6 @@ class Q_MULTIMEDIA_EXPORT QScreenCapture : public QObject { Q_OBJECT Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) - Q_PROPERTY(WId windowId READ windowId WRITE setWindowId NOTIFY windowIdChanged) - Q_PROPERTY(QWindow *window READ window WRITE setWindow NOTIFY windowChanged) Q_PROPERTY(QScreen *screen READ screen WRITE setScreen NOTIFY screenChanged) Q_PROPERTY(Error error READ error NOTIFY errorChanged) Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) @@ -33,7 +30,6 @@ public: NoError, InternalError, CapturingNotSupported, - WindowCapturingNotSupported, CaptureFailed, NotFound, }; @@ -44,12 +40,6 @@ public: QMediaCaptureSession *captureSession() const; - void setWindow(QWindow *window); - QWindow *window() const; - - void setWindowId(WId id); - WId windowId() const; - void setScreen(QScreen *screen); QScreen *screen() const; @@ -66,8 +56,6 @@ public Q_SLOTS: Q_SIGNALS: void activeChanged(bool); void errorChanged(); - void windowIdChanged(WId); - void windowChanged(QWindow *); void screenChanged(QScreen *); void errorOccurred(QScreenCapture::Error error, const QString &errorString); diff --git a/src/multimedia/recording/qwindowcapture.cpp b/src/multimedia/recording/qwindowcapture.cpp new file mode 100644 index 000000000..549468930 --- /dev/null +++ b/src/multimedia/recording/qwindowcapture.cpp @@ -0,0 +1,161 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qwindowcapture.h" +#include "qplatformmediaintegration_p.h" + +QT_BEGIN_NAMESPACE + +class QWindowCapturePrivate : public QObjectData +{ +public: + // TODO add impl +}; + +/*! + \class QWindowCapture + \inmodule QtMultimedia + \ingroup multimedia + \ingroup multimedia_video + \since 6.6 + + \brief This class is used for capturing a window. + + The class captures a window. It is managed by + the QMediaCaptureSession class where the captured window can be displayed + in a video preview object or recorded to a file. + + \sa QMediaCaptureSession, QCapturableWindow +*/ +/*! + \qmltype WindowCapture + \instantiates QWindowCapture + \inqmlmodule QtMultimedia + \ingroup multimedia_qml + \ingroup multimedia_video_qml + \since 6.6 + + \brief This type is used for capturing a window. + + WindowCapture captures a window. It is managed by + MediaCaptureSession where the captured window can be displayed + in a video preview object or recorded to a file. + + \sa CaptureSession, CapturableWindow +*/ + +/*! + \enum QWindowCapture::Error + + Enumerates error codes that can be signaled by the QWindowCapture class. + errorString() provides detailed information about the error cause. + + \value NoError No error + \value InternalError Internal window capturing driver error + \value CapturingNotSupported Window capturing is not supported + \value CaptureFailed Capturing window failed + \value NotFound Selected window not found +*/ + +/*! + Constructs a new QWindowCapture object with \a parent. +*/ +QWindowCapture::QWindowCapture(QObject *parent) : QObject(parent) { } + +/*! + Destroys the object. + */ +QWindowCapture::~QWindowCapture() = default; + +/*! + \qmlmethod list<CapturableWindow> QtMultimedia::CapturableWindow::capturableWindows() + + Returns a list of CapturableWindow objects that is available for capturing. +*/ +/*! + \fn QList<QCapturableWindow> QWindowCapture::capturableWindows() + + Returns a list of QCapturableWindow objects that is available for capturing. + */ +QList<QCapturableWindow> QWindowCapture::capturableWindows() +{ + return QPlatformMediaIntegration::instance()->capturableWindows(); +} + +QMediaCaptureSession *QWindowCapture::captureSession() const +{ + return nullptr; +} + +/*! + \qmlproperty Window QtMultimedia::WindowCapture::window + Describes the window for capturing. + + \sa QtMultimedia::WindowCapture::capturableWindows +*/ + +/*! + \property QWindowCapture::window + \brief the window for capturing. + + \sa QWindowCapture::capturableWindows +*/ +QCapturableWindow QWindowCapture::window() const +{ + return {}; +} + +void QWindowCapture::setWindow(QCapturableWindow /*window*/) { } + +/*! + \qmlproperty bool QtMultimedia::WindowCapture::active + Describes whether the capturing is currently active. +*/ + +/*! + \property QWindowCapture::active + \brief whether the capturing is currently active. +*/ +bool QWindowCapture::isActive() const +{ + return false; +} + +void QWindowCapture::setActive(bool /*active*/) { } + +/*! + \qmlproperty string QtMultimedia::WindowCapture::error + Returns a code of the last error. +*/ + +/*! + \property QWindowCapture::error + \brief the code of the last error. +*/ +QWindowCapture::Error QWindowCapture::error() const +{ + return NoError; +} + +/*! + \fn void QWindowCapture::errorOccurred(QWindowCapture::Error error, const QString &errorString) + + Signals when an \a error occurs, along with the \a errorString. +*/ +/*! + \qmlproperty string QtMultimedia::WindowCapture::errorString + Returns a human readable string describing the cause of error. +*/ + +/*! + \property QWindowCapture::errorString + \brief a human readable string describing the cause of error. +*/ +QString QWindowCapture::errorString() const +{ + return {}; +} + +QT_END_NAMESPACE + +#include "moc_qwindowcapture.cpp" diff --git a/src/multimedia/recording/qwindowcapture.h b/src/multimedia/recording/qwindowcapture.h new file mode 100644 index 000000000..7f2f2d79b --- /dev/null +++ b/src/multimedia/recording/qwindowcapture.h @@ -0,0 +1,68 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include <QtMultimedia/qtmultimediaexports.h> +#include <QtMultimedia/qcapturablewindow.h> +#include <QtCore/qobject.h> +#include <QtCore/qlist.h> + +#ifndef QWINDOWCAPTURE_H +#define QWINDOWCAPTURE_H + +QT_BEGIN_NAMESPACE + +class Q_MULTIMEDIA_EXPORT QWindowCapture : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) + Q_PROPERTY(QCapturableWindow window READ window WRITE setWindow NOTIFY windowChanged) + Q_PROPERTY(Error error READ error NOTIFY errorChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) +public: + enum Error { + NoError, + InternalError, + CapturingNotSupported, + CaptureFailed, + NotFound, + }; + Q_ENUM(Error) + + explicit QWindowCapture(QObject *parent = nullptr); + ~QWindowCapture() override; + + Q_INVOKABLE static QList<QCapturableWindow> capturableWindows(); + + QMediaCaptureSession *captureSession() const; + + void setWindow(QCapturableWindow window); + + QCapturableWindow window() const; + + bool isActive() const; + + Error error() const; + QString errorString() const; + +public Q_SLOTS: + void setActive(bool active); + void start() { setActive(true); } + void stop() { setActive(false); } + +Q_SIGNALS: + void activeChanged(bool); + void windowChanged(QCapturableWindow window); + void errorChanged(); + void errorOccurred(QWindowCapture::Error error, const QString &errorString); + +private: + void setCaptureSession(QMediaCaptureSession *captureSession); + + friend class QMediaCaptureSession; + Q_DISABLE_COPY(QWindowCapture) + Q_DECLARE_PRIVATE(QWindowCapture) +}; + +QT_END_NAMESPACE + +#endif // QWINDOWCAPTURE_H diff --git a/src/multimediaquick/qtmultimediaquicktypes_p.h b/src/multimediaquick/qtmultimediaquicktypes_p.h index e9dffe8be..93aed7193 100644 --- a/src/multimediaquick/qtmultimediaquicktypes_p.h +++ b/src/multimediaquick/qtmultimediaquicktypes_p.h @@ -147,6 +147,27 @@ struct QVideoSinkForeign QML_NAMED_ELEMENT(VideoSink) }; +struct QCapturableWindowForeign +{ + Q_GADGET + QML_FOREIGN(QCapturableWindow) + QML_NAMED_ELEMENT(capturableWindow) +}; + +namespace QCapturableWindowNamespaceForeign +{ + Q_NAMESPACE + QML_FOREIGN_NAMESPACE(QCapturableWindow) + QML_NAMED_ELEMENT(CapturableWindow) +}; + +struct QWindowCaptureForeign +{ + Q_GADGET + QML_FOREIGN(QWindowCapture) + QML_NAMED_ELEMENT(WindowCapture) +}; + QT_END_NAMESPACE #endif diff --git a/src/plugins/multimedia/ffmpeg/qavfscreencapture.mm b/src/plugins/multimedia/ffmpeg/qavfscreencapture.mm index 7f46d40fe..3fe7b6f4c 100644 --- a/src/plugins/multimedia/ffmpeg/qavfscreencapture.mm +++ b/src/plugins/multimedia/ffmpeg/qavfscreencapture.mm @@ -224,7 +224,7 @@ protected: << CGImageGetAlphaInfo(imageRef) << "ByteOrderInfo:" << CGImageGetByteOrderInfo(imageRef); - updateError(QScreenCapture::WindowCapturingNotSupported, + updateError(QScreenCapture::CapturingNotSupported, QLatin1String("Not supported pixel format")); return {}; } diff --git a/src/plugins/multimedia/ffmpeg/qffmpegscreencapturebase.cpp b/src/plugins/multimedia/ffmpeg/qffmpegscreencapturebase.cpp index 3d791d054..ce1b75158 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpegscreencapturebase.cpp +++ b/src/plugins/multimedia/ffmpeg/qffmpegscreencapturebase.cpp @@ -36,26 +36,6 @@ QScreen *QFFmpegScreenCaptureBase::screen() const return m_screen; } -void QFFmpegScreenCaptureBase::setWindow(QWindow *w) -{ - setSource(m_window, w, &QScreenCapture::windowChanged); -} - -QWindow *QFFmpegScreenCaptureBase::window() const -{ - return m_window; -} - -void QFFmpegScreenCaptureBase::setWindowId(WId id) -{ - setSource(m_wid, id, &QScreenCapture::windowIdChanged); -} - -WId QFFmpegScreenCaptureBase::windowId() const -{ - return m_wid; -} - template<typename Source, typename NewSource, typename Signal> void QFFmpegScreenCaptureBase::setSource(Source &source, NewSource newSource, Signal sig) { @@ -70,8 +50,6 @@ void QFFmpegScreenCaptureBase::setSource(Source &source, NewSource newSource, Si source = {}; Q_ASSERT(!m_screen); - Q_ASSERT(!m_wid); - Q_ASSERT(!m_window); } source = newSource; diff --git a/src/plugins/multimedia/ffmpeg/qffmpegscreencapturebase_p.h b/src/plugins/multimedia/ffmpeg/qffmpegscreencapturebase_p.h index e4466bb2a..1b89f76a8 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpegscreencapturebase_p.h +++ b/src/plugins/multimedia/ffmpeg/qffmpegscreencapturebase_p.h @@ -34,14 +34,6 @@ public: QScreen *screen() const final; - void setWindow(QWindow *w) final; - - QWindow *window() const final; - - void setWindowId(WId id) final; - - WId windowId() const final; - protected: virtual bool setActiveInternal(bool active) = 0; @@ -52,8 +44,6 @@ private: private: bool m_active = false; QPointer<QScreen> m_screen; - QPointer<QWindow> m_window; - WId m_wid = 0; }; QT_END_NAMESPACE |