diff options
Diffstat (limited to 'src/multimedia/recording')
21 files changed, 2776 insertions, 2437 deletions
diff --git a/src/multimedia/recording/qaudiorecorder.cpp b/src/multimedia/recording/qaudiorecorder.cpp deleted file mode 100644 index 1db5c54a2..000000000 --- a/src/multimedia/recording/qaudiorecorder.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qaudiorecorder.h" -#include "qaudioinputselectorcontrol.h" -#include "qmediaobject_p.h" -#include "qmediarecorder_p.h" -#include <qmediaservice.h> -#include <qmediaserviceprovider_p.h> - -#include <QtCore/qdebug.h> -#include <QtCore/qurl.h> -#include <QtCore/qstringlist.h> -#include <QtCore/qmetaobject.h> - -#include <qaudioformat.h> - -QT_BEGIN_NAMESPACE - -/*! - \class QAudioRecorder - \inmodule QtMultimedia - \ingroup multimedia - \ingroup multimedia_recording - - \brief The QAudioRecorder class is used for the recording of audio. - - The QAudioRecorder class is a high level media recording class and contains - the same functionality as \l QMediaRecorder. - - \snippet multimedia-snippets/media.cpp Audio recorder - - In addition QAudioRecorder provides functionality for selecting the audio input. - - \snippet multimedia-snippets/media.cpp Audio recorder inputs - - The \l {Audio Recorder Example} shows how to use this class in more detail. - - \sa QMediaRecorder, QAudioInputSelectorControl -*/ - -class QAudioRecorderObject : public QMediaObject -{ -public: - QAudioRecorderObject(QObject *parent, QMediaService *service) - :QMediaObject(parent, service) - { - } - - ~QAudioRecorderObject() - { - } -}; - -class QAudioRecorderPrivate : public QMediaRecorderPrivate -{ - Q_DECLARE_NON_CONST_PUBLIC(QAudioRecorder) - -public: - void initControls() - { - Q_Q(QAudioRecorder); - audioInputSelector = nullptr; - - QMediaService *service = mediaObject ? mediaObject->service() : nullptr; - - if (service != nullptr) - audioInputSelector = qobject_cast<QAudioInputSelectorControl*>(service->requestControl(QAudioInputSelectorControl_iid)); - - if (audioInputSelector) { - q->connect(audioInputSelector, SIGNAL(activeInputChanged(QString)), - SIGNAL(audioInputChanged(QString))); - q->connect(audioInputSelector, SIGNAL(availableInputsChanged()), - SIGNAL(availableAudioInputsChanged())); - } - } - - QAudioRecorderPrivate(): - QMediaRecorderPrivate(), - provider(nullptr), - audioInputSelector(nullptr) {} - - QMediaServiceProvider *provider; - QAudioInputSelectorControl *audioInputSelector; -}; - - - -/*! - Constructs an audio recorder. - The \a parent is passed to QMediaObject. -*/ - -QAudioRecorder::QAudioRecorder(QObject *parent): - QMediaRecorder(*new QAudioRecorderPrivate, nullptr, parent) -{ - Q_D(QAudioRecorder); - d->provider = QMediaServiceProvider::defaultServiceProvider(); - - QMediaService *service = d->provider->requestService(Q_MEDIASERVICE_AUDIOSOURCE); - setMediaObject(new QAudioRecorderObject(this, service)); - d->initControls(); -} - -/*! - Destroys an audio recorder object. -*/ - -QAudioRecorder::~QAudioRecorder() -{ - Q_D(QAudioRecorder); - QMediaService *service = d->mediaObject ? d->mediaObject->service() : nullptr; - QMediaObject *mediaObject = d->mediaObject; - setMediaObject(nullptr); - - if (service && d->audioInputSelector) - service->releaseControl(d->audioInputSelector); - - if (d->provider && service) - d->provider->releaseService(service); - - delete mediaObject; -} - -/*! - Returns a list of available audio inputs -*/ - -QStringList QAudioRecorder::audioInputs() const -{ - Q_D(const QAudioRecorder); - if (d->audioInputSelector) - return d->audioInputSelector->availableInputs(); - else - return QStringList(); -} - -/*! - Returns the readable translated description of the audio input device with \a name. -*/ - -QString QAudioRecorder::audioInputDescription(const QString& name) const -{ - Q_D(const QAudioRecorder); - - if (d->audioInputSelector) - return d->audioInputSelector->inputDescription(name); - else - return QString(); -} - -/*! - Returns the default audio input name. -*/ - -QString QAudioRecorder::defaultAudioInput() const -{ - Q_D(const QAudioRecorder); - - if (d->audioInputSelector) - return d->audioInputSelector->defaultInput(); - else - return QString(); -} - -/*! - \property QAudioRecorder::audioInput - \brief the active audio input name. - -*/ - -/*! - Returns the active audio input name. -*/ - -QString QAudioRecorder::audioInput() const -{ - Q_D(const QAudioRecorder); - - if (d->audioInputSelector) - return d->audioInputSelector->activeInput(); - else - return QString(); -} - -/*! - Set the active audio input to \a name. -*/ - -void QAudioRecorder::setAudioInput(const QString& name) -{ - Q_D(const QAudioRecorder); - - if (d->audioInputSelector) - return d->audioInputSelector->setActiveInput(name); -} - -/*! - \fn QAudioRecorder::audioInputChanged(const QString& name) - - Signal emitted when active audio input changes to \a name. -*/ - -/*! - \fn QAudioRecorder::availableAudioInputsChanged() - - Signal is emitted when the available audio inputs change. -*/ - -QT_END_NAMESPACE - -#include "moc_qaudiorecorder.cpp" diff --git a/src/multimedia/recording/qaudiorecorder.h b/src/multimedia/recording/qaudiorecorder.h deleted file mode 100644 index e57794b40..000000000 --- a/src/multimedia/recording/qaudiorecorder.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QAUDIORECORDER_H -#define QAUDIORECORDER_H - -#include <QtMultimedia/qmediarecorder.h> -#include <QtMultimedia/qmediaobject.h> -#include <QtMultimedia/qmediaencodersettings.h> -#include <QtMultimedia/qmediaenumdebug.h> - -#include <QtCore/qpair.h> - -QT_BEGIN_NAMESPACE - -class QString; -class QSize; -class QAudioFormat; -QT_END_NAMESPACE - -QT_BEGIN_NAMESPACE - -class QAudioRecorderPrivate; -class Q_MULTIMEDIA_EXPORT QAudioRecorder : public QMediaRecorder -{ - Q_OBJECT - Q_PROPERTY(QString audioInput READ audioInput WRITE setAudioInput NOTIFY audioInputChanged) -public: - explicit QAudioRecorder(QObject *parent = nullptr); - ~QAudioRecorder(); - - QStringList audioInputs() const; - QString defaultAudioInput() const; - QString audioInputDescription(const QString& name) const; - - QString audioInput() const; - -public Q_SLOTS: - void setAudioInput(const QString& name); - -Q_SIGNALS: - void audioInputChanged(const QString& name); - void availableAudioInputsChanged(); - -private: - Q_DISABLE_COPY(QAudioRecorder) - Q_DECLARE_PRIVATE(QAudioRecorder) -}; - -QT_END_NAMESPACE - -#endif // QAUDIORECORDER_H diff --git a/src/multimedia/recording/qcapturablewindow.cpp b/src/multimedia/recording/qcapturablewindow.cpp new file mode 100644 index 000000000..34b6a1f5d --- /dev/null +++ b/src/multimedia/recording/qcapturablewindow.cpp @@ -0,0 +1,156 @@ +// 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 + \since 6.6 + + 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; + +/*! + \fn bool QCapturableWindow::operator==(const QCapturableWindow &lhs, const QCapturableWindow &rhs) + + Returns \c true if window information \a lhs and \a rhs refer to the same window, + otherwise returns \c false. +*/ + +/*! + \fn bool QCapturableWindow::operator!=(const QCapturableWindow &lhs, const QCapturableWindow &rhs) + + Returns \c true if window information \a lhs and \a rhs refer to different windows, + otherwise returns \c false. +*/ +bool operator==(const QCapturableWindow &lhs, const QCapturableWindow &rhs) noexcept +{ + return lhs.d == rhs.d || (lhs.d && rhs.d && lhs.d->id == rhs.d->id); +} + +/*! + \qmlproperty string QtMultimedia::CapturableWindow::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::CapturableWindow::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 +{ + if (!d) + return {}; + + if (d->description.isEmpty() && d->id) + return QLatin1String("Window 0x") + QString::number(d->id, 16); + + return d->description; +} + +QCapturableWindow::QCapturableWindow(QCapturableWindowPrivate *capturablePrivate) + : d(capturablePrivate) +{ +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QCapturableWindow &window) +{ + dbg << QStringLiteral("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..f18dbf72d --- /dev/null +++ b/src/multimedia/recording/qcapturablewindow.h @@ -0,0 +1,66 @@ +// 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 QCapturableWindow +{ + Q_GADGET_EXPORT(Q_MULTIMEDIA_EXPORT) + Q_PROPERTY(QString description READ description CONSTANT) + Q_PROPERTY(bool isValid READ isValid CONSTANT) +public: + Q_MULTIMEDIA_EXPORT QCapturableWindow(); + + Q_MULTIMEDIA_EXPORT ~QCapturableWindow(); + + Q_MULTIMEDIA_EXPORT QCapturableWindow(const QCapturableWindow &other); + + QCapturableWindow(QCapturableWindow &&other) noexcept = default; + + Q_MULTIMEDIA_EXPORT QCapturableWindow& operator=(const QCapturableWindow &other); + + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCapturableWindow); + + void swap(QCapturableWindow &other) noexcept + { d.swap(other.d); } + + Q_MULTIMEDIA_EXPORT friend bool operator==(const QCapturableWindow &lhs, const QCapturableWindow &rhs) noexcept; + + friend bool operator!=(const QCapturableWindow &lhs, const QCapturableWindow &rhs) noexcept + { return !(lhs == rhs); } + + Q_MULTIMEDIA_EXPORT bool isValid() const; + + Q_MULTIMEDIA_EXPORT QString description() const; + +#ifndef QT_NO_DEBUG_STREAM + Q_MULTIMEDIA_EXPORT friend QDebug operator<<(QDebug, const QCapturableWindow &); +#endif + +private: + Q_MULTIMEDIA_EXPORT QCapturableWindow(QCapturableWindowPrivate *capturablePrivate); + friend class QCapturableWindowPrivate; + + QExplicitlySharedDataPointer<QCapturableWindowPrivate> d; +}; + +Q_DECLARE_SHARED(QCapturableWindow) + +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..9cb186a77 --- /dev/null +++ b/src/multimedia/recording/qcapturablewindow_p.h @@ -0,0 +1,41 @@ +// 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> +#include <QtMultimedia/qcapturablewindow.h> + +// +// 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; + + static const QCapturableWindowPrivate *handle(const QCapturableWindow &window) + { + return window.d.get(); + } + + QCapturableWindow create() { return QCapturableWindow(this); } +}; + +QT_END_NAMESPACE + +#endif // QCAPTURABLEWINDOW_P_H diff --git a/src/multimedia/recording/qmediacapturesession.cpp b/src/multimedia/recording/qmediacapturesession.cpp new file mode 100644 index 000000000..9df09acef --- /dev/null +++ b/src/multimedia/recording/qmediacapturesession.cpp @@ -0,0 +1,688 @@ +// Copyright (C) 2022 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 "qmediacapturesession.h" +#include "qmediacapturesession_p.h" +#include "qaudiodevice.h" +#include "qcamera.h" +#include "qmediarecorder.h" +#include "qimagecapture.h" +#include "qvideosink.h" +#include "qscreencapture.h" +#include "qwindowcapture.h" +#include "qvideoframeinput.h" + +#include "qplatformmediaintegration_p.h" +#include "qplatformmediacapture_p.h" +#include "qaudioinput.h" +#include "qaudiobufferinput.h" +#include "qaudiooutput.h" + +QT_BEGIN_NAMESPACE + +void QMediaCaptureSessionPrivate::setVideoSink(QVideoSink *sink) +{ + Q_Q(QMediaCaptureSession); + + if (sink == videoSink) + return; + if (videoSink) + videoSink->setSource(nullptr); + videoSink = sink; + if (sink) + sink->setSource(q); + if (captureSession) + captureSession->setVideoPreview(sink); + emit q->videoOutputChanged(); +} + +/*! + \class QMediaCaptureSession + + \brief The QMediaCaptureSession class allows capturing of audio and video content. + \inmodule QtMultimedia + \ingroup multimedia + \ingroup multimedia_video + \ingroup multimedia_audio + + The QMediaCaptureSession is the central class that manages capturing of media on the local + device. + + You can connect a video input to QMediaCaptureSession using setCamera(), + setScreenCapture(), setWindowCapture() or setVideoFrameInput(). + 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(), or set your + custom audio input using setAudioBufferInput(). + 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, QScreenCapture, QWindowCapture, + QVideoFrameInput, QMediaRecorder, QGraphicsVideoItem +*/ + +/*! + \qmltype CaptureSession + \since 6.2 + \instantiates QMediaCaptureSession + \brief Allows capturing of audio and video content. + + \inqmlmodule QtMultimedia + \ingroup multimedia_qml + \ingroup multimedia_audio_qml + \ingroup multimedia_video_qml + + This is the central type that manages capturing of media on the local device. + + Connect a camera and a microphone to a CaptureSession by assigning Camera + and AudioInput objects to the relevant properties. + + 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. + + Route audio to an output device by assigning an AudioOutput object + to the audioOutput property. + + Capture still images from a camera by assigning an ImageCapture to the + imageCapture property. + + Record audio/video by assigning a MediaRecorder to the recorder property. + +\qml + CaptureSession { + id: captureSession + camera: Camera { + id: camera + } + imageCapture: ImageCapture { + id: imageCapture + } + + recorder: MediaRecorder { + id: recorder + } + videoOutput: preview + } +\endqml + + \sa Camera, MediaDevices, MediaRecorder, ImageCapture, ScreenCapture, WindowCapture, AudioInput, VideoOutput +*/ + +/*! + Creates a session for media capture from the \a parent object. + */ +QMediaCaptureSession::QMediaCaptureSession(QObject *parent) + : QObject{ *new QMediaCaptureSessionPrivate, parent } +{ + QT6_ONLY(Q_UNUSED(unused)) + + Q_D(QMediaCaptureSession); + + auto maybeCaptureSession = QPlatformMediaIntegration::instance()->createCaptureSession(); + if (maybeCaptureSession) { + d->captureSession.reset(maybeCaptureSession.value()); + d->captureSession->setCaptureSession(this); + } else { + qWarning() << "Failed to initialize QMediaCaptureSession" << maybeCaptureSession.error(); + } +} + +/*! + Destroys the session. + */ +QMediaCaptureSession::~QMediaCaptureSession() +{ + Q_D(QMediaCaptureSession); + + setCamera(nullptr); + setRecorder(nullptr); + setImageCapture(nullptr); + setScreenCapture(nullptr); + setWindowCapture(nullptr); + setVideoFrameInput(nullptr); + setAudioBufferInput(nullptr); + setAudioInput(nullptr); + setAudioOutput(nullptr); + d->setVideoSink(nullptr); + d->captureSession.reset(); +} +/*! + \qmlproperty AudioInput QtMultimedia::CaptureSession::audioInput + + This property holds the audio input that is being used to capture audio. +*/ + +/*! + \property QMediaCaptureSession::audioInput + + Returns the device that is being used to capture audio. +*/ +QAudioInput *QMediaCaptureSession::audioInput() const +{ + Q_D(const QMediaCaptureSession); + return d->audioInput; +} + +/*! + Sets the audio input device to \a input. If setting it to an empty + QAudioDevice the capture session will use the default input as + defined by the operating system. +*/ +void QMediaCaptureSession::setAudioInput(QAudioInput *input) +{ + Q_D(QMediaCaptureSession); + + QAudioInput *oldInput = d->audioInput; + if (oldInput == input) + return; + + // To avoid double emit of audioInputChanged + // from recursive setAudioInput(nullptr) call. + d->audioInput = nullptr; + + if (d->captureSession) + d->captureSession->setAudioInput(nullptr); + if (oldInput) + oldInput->setDisconnectFunction({}); + if (input) { + input->setDisconnectFunction([this](){ setAudioInput(nullptr); }); + if (d->captureSession) + d->captureSession->setAudioInput(input->handle()); + } + d->audioInput = input; + emit audioInputChanged(); +} + +/*! + \property QMediaCaptureSession::audioBufferInput + \since 6.8 + + \brief The object used to send custom audio buffers to \l QMediaRecorder. +*/ +QAudioBufferInput *QMediaCaptureSession::audioBufferInput() const +{ + Q_D(const QMediaCaptureSession); + + return d->audioBufferInput; +} + +void QMediaCaptureSession::setAudioBufferInput(QAudioBufferInput *input) +{ + Q_D(QMediaCaptureSession); + + // TODO: come up with an unification of the captures setup + QAudioBufferInput *oldInput = d->audioBufferInput; + if (oldInput == input) + return; + d->audioBufferInput = input; + if (d->captureSession) + d->captureSession->setAudioBufferInput(nullptr); + if (oldInput) { + if (oldInput->captureSession() && oldInput->captureSession() != this) + oldInput->captureSession()->setAudioBufferInput(nullptr); + oldInput->setCaptureSession(nullptr); + } + if (input) { + if (input->captureSession()) + input->captureSession()->setAudioBufferInput(nullptr); + if (d->captureSession) + d->captureSession->setAudioBufferInput(input->platformAudioBufferInput()); + input->setCaptureSession(this); + } + emit audioBufferInputChanged(); +} + +/*! + \qmlproperty Camera QtMultimedia::CaptureSession::camera + + \brief The camera used to capture video. + + Record video or take images by adding a camera to the capture session using + this property. +*/ + +/*! + \property QMediaCaptureSession::camera + + \brief The camera used to capture video. + + Record video or take images by adding a camera to the capture session + using this property. +*/ +QCamera *QMediaCaptureSession::camera() const +{ + Q_D(const QMediaCaptureSession); + + return d->camera; +} + +void QMediaCaptureSession::setCamera(QCamera *camera) +{ + Q_D(QMediaCaptureSession); + + // TODO: come up with an unification of the captures setup + QCamera *oldCamera = d->camera; + if (oldCamera == camera) + return; + d->camera = camera; + if (d->captureSession) + d->captureSession->setCamera(nullptr); + if (oldCamera) { + if (oldCamera->captureSession() && oldCamera->captureSession() != this) + oldCamera->captureSession()->setCamera(nullptr); + oldCamera->setCaptureSession(nullptr); + } + if (camera) { + if (camera->captureSession()) + camera->captureSession()->setCamera(nullptr); + if (d->captureSession) + d->captureSession->setCamera(camera->platformCamera()); + camera->setCaptureSession(this); + } + emit cameraChanged(); +} + +/*! + \qmlproperty ScreenCapture QtMultimedia::CaptureSession::screenCapture + \since 6.5 + + \brief The object used to capture a screen. + + Record a screen by adding a screen capture objet + to the capture session using this property. +*/ + +/*! + \property QMediaCaptureSession::screenCapture + \since 6.5 + + \brief The object used to capture a screen. + + Record a screen by adding a screen capture object + to the capture session using this property. +*/ +QScreenCapture *QMediaCaptureSession::screenCapture() +{ + Q_D(QMediaCaptureSession); + + return d->screenCapture; +} + +void QMediaCaptureSession::setScreenCapture(QScreenCapture *screenCapture) +{ + Q_D(QMediaCaptureSession); + + // TODO: come up with an unification of the captures setup + QScreenCapture *oldScreenCapture = d->screenCapture; + if (oldScreenCapture == screenCapture) + return; + d->screenCapture = screenCapture; + if (d->captureSession) + d->captureSession->setScreenCapture(nullptr); + if (oldScreenCapture) { + if (oldScreenCapture->captureSession() && oldScreenCapture->captureSession() != this) + oldScreenCapture->captureSession()->setScreenCapture(nullptr); + oldScreenCapture->setCaptureSession(nullptr); + } + if (screenCapture) { + if (screenCapture->captureSession()) + screenCapture->captureSession()->setScreenCapture(nullptr); + if (d->captureSession) + d->captureSession->setScreenCapture(screenCapture->platformScreenCapture()); + screenCapture->setCaptureSession(this); + } + 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() +{ + Q_D(QMediaCaptureSession); + return d->windowCapture; +} + +void QMediaCaptureSession::setWindowCapture(QWindowCapture *windowCapture) +{ + Q_D(QMediaCaptureSession); + + // TODO: come up with an unification of the captures setup + QWindowCapture *oldCapture = d->windowCapture; + if (oldCapture == windowCapture) + return; + d->windowCapture = windowCapture; + if (d->captureSession) + d->captureSession->setWindowCapture(nullptr); + if (oldCapture) { + if (oldCapture->captureSession() && oldCapture->captureSession() != this) + oldCapture->captureSession()->setWindowCapture(nullptr); + oldCapture->setCaptureSession(nullptr); + } + if (windowCapture) { + if (windowCapture->captureSession()) + windowCapture->captureSession()->setWindowCapture(nullptr); + if (d->captureSession) + d->captureSession->setWindowCapture(windowCapture->platformWindowCapture()); + windowCapture->setCaptureSession(this); + } + emit windowCaptureChanged(); +} + +/*! + \property QMediaCaptureSession::videoFrameInput + \since 6.8 + + \brief The object used to send custom video frames to + \l QMediaRecorder or a video output. +*/ +QVideoFrameInput *QMediaCaptureSession::videoFrameInput() const +{ + Q_D(const QMediaCaptureSession); + return d->videoFrameInput; +} + +void QMediaCaptureSession::setVideoFrameInput(QVideoFrameInput *input) +{ + Q_D(QMediaCaptureSession); + // TODO: come up with an unification of the captures setup + QVideoFrameInput *oldInput = d->videoFrameInput; + if (oldInput == input) + return; + d->videoFrameInput = input; + if (d->captureSession) + d->captureSession->setVideoFrameInput(nullptr); + if (oldInput) { + if (oldInput->captureSession() && oldInput->captureSession() != this) + oldInput->captureSession()->setVideoFrameInput(nullptr); + oldInput->setCaptureSession(nullptr); + } + if (input) { + if (input->captureSession()) + input->captureSession()->setVideoFrameInput(nullptr); + if (d->captureSession) + d->captureSession->setVideoFrameInput(input->platformVideoFrameInput()); + input->setCaptureSession(this); + } + emit videoFrameInputChanged(); +} + +/*! + \qmlproperty ImageCapture QtMultimedia::CaptureSession::imageCapture + + \brief The object used to capture still images. + + Add an ImageCapture interface to the capture session to enable + capturing of still images from the camera. +*/ +/*! + \property QMediaCaptureSession::imageCapture + + \brief the object used to capture still images. + + Add a QImageCapture object to the capture session to enable + capturing of still images from the camera. +*/ +QImageCapture *QMediaCaptureSession::imageCapture() +{ + Q_D(QMediaCaptureSession); + + return d->imageCapture; +} + +void QMediaCaptureSession::setImageCapture(QImageCapture *imageCapture) +{ + Q_D(QMediaCaptureSession); + + // TODO: come up with an unification of the captures setup + QImageCapture *oldImageCapture = d->imageCapture; + if (oldImageCapture == imageCapture) + return; + d->imageCapture = imageCapture; + if (d->captureSession) + d->captureSession->setImageCapture(nullptr); + if (oldImageCapture) { + if (oldImageCapture->captureSession() && oldImageCapture->captureSession() != this) + oldImageCapture->captureSession()->setImageCapture(nullptr); + oldImageCapture->setCaptureSession(nullptr); + } + if (imageCapture) { + if (imageCapture->captureSession()) + imageCapture->captureSession()->setImageCapture(nullptr); + if (d->captureSession) + d->captureSession->setImageCapture(imageCapture->platformImageCapture()); + imageCapture->setCaptureSession(this); + } + emit imageCaptureChanged(); +} +/*! + \qmlproperty MediaRecorder QtMultimedia::CaptureSession::recorder + + \brief The recorder object used to capture audio/video. + + Add a MediaRcorder object to the capture session to enable + recording of audio and/or video from the capture session. +*/ +/*! + \property QMediaCaptureSession::recorder + + \brief The recorder object used to capture audio/video. + + Add a QMediaRecorder object to the capture session to enable + recording of audio and/or video from the capture session. +*/ + +QMediaRecorder *QMediaCaptureSession::recorder() +{ + Q_D(QMediaCaptureSession); + return d->recorder; +} + +void QMediaCaptureSession::setRecorder(QMediaRecorder *recorder) +{ + Q_D(QMediaCaptureSession); + QMediaRecorder *oldRecorder = d->recorder; + if (oldRecorder == recorder) + return; + d->recorder = recorder; + if (d->captureSession) + d->captureSession->setMediaRecorder(nullptr); + if (oldRecorder) { + if (oldRecorder->captureSession() && oldRecorder->captureSession() != this) + oldRecorder->captureSession()->setRecorder(nullptr); + oldRecorder->setCaptureSession(nullptr); + } + if (recorder) { + if (recorder->captureSession()) + recorder->captureSession()->setRecorder(nullptr); + if (d->captureSession) + d->captureSession->setMediaRecorder(recorder->platformRecoder()); + recorder->setCaptureSession(this); + } + emit recorderChanged(); +} +/*! + \qmlproperty VideoOutput QtMultimedia::CaptureSession::videoOutput + + \brief The VideoOutput that is the video preview for the capture session. + + A VideoOutput based preview is expected to have an invokable videoSink() + method that returns a QVideoSink. + + The previously set preview is detached. + +*/ +/*! + \property QMediaCaptureSession::videoOutput + + Returns the video output for the session. +*/ +QObject *QMediaCaptureSession::videoOutput() const +{ + Q_D(const QMediaCaptureSession); + return d->videoOutput; +} +/*! + Sets a QObject, (\a output), to a video preview for the capture session. + + A QObject based preview is expected to have an invokable videoSink() + method that returns a QVideoSink. + + The previously set preview is detached. +*/ +void QMediaCaptureSession::setVideoOutput(QObject *output) +{ + Q_D(QMediaCaptureSession); + if (d->videoOutput == output) + return; + QVideoSink *sink = qobject_cast<QVideoSink *>(output); + if (!sink && output) { + auto *mo = output->metaObject(); + mo->invokeMethod(output, "videoSink", Q_RETURN_ARG(QVideoSink *, sink)); + } + d->videoOutput = output; + d->setVideoSink(sink); +} + +/*! + Sets a QVideoSink, (\a sink), to a video preview for the capture session. + + A QObject based preview is expected to have an invokable videoSink() + method that returns a QVideoSink. + + The previously set preview is detached. +*/ +void QMediaCaptureSession::setVideoSink(QVideoSink *sink) +{ + Q_D(QMediaCaptureSession); + d->videoOutput = nullptr; + d->setVideoSink(sink); +} + +/*! + Returns the QVideoSink for the session. +*/ +QVideoSink *QMediaCaptureSession::videoSink() const +{ + Q_D(const QMediaCaptureSession); + return d->videoSink; +} +/*! + Sets the audio output device to \a{output}. + + Setting an audio output device enables audio routing from an audio input device. +*/ +void QMediaCaptureSession::setAudioOutput(QAudioOutput *output) +{ + Q_D(QMediaCaptureSession); + + QAudioOutput *oldOutput = d->audioOutput; + if (oldOutput == output) + return; + + // We don't want to end up with signal emitted + // twice (from recursive call setAudioInput(nullptr) + // from oldOutput->setDisconnectFunction(): + d->audioOutput = nullptr; + + if (d->captureSession) + d->captureSession->setAudioOutput(nullptr); + if (oldOutput) + oldOutput->setDisconnectFunction({}); + if (output) { + output->setDisconnectFunction([this](){ setAudioOutput(nullptr); }); + if (d->captureSession) + d->captureSession->setAudioOutput(output->handle()); + } + d->audioOutput = output; + emit audioOutputChanged(); +} +/*! + \qmlproperty AudioOutput QtMultimedia::CaptureSession::audioOutput + \brief The audio output device for the capture session. + + Add an AudioOutput device to the capture session to enable + audio routing from an AudioInput device. +*/ +/*! + \property QMediaCaptureSession::audioOutput + + Returns the audio output for the session. +*/ +QAudioOutput *QMediaCaptureSession::audioOutput() const +{ + Q_D(const QMediaCaptureSession); + return d->audioOutput; +} + +/*! + \internal +*/ +QPlatformMediaCaptureSession *QMediaCaptureSession::platformSession() const +{ + Q_D(const QMediaCaptureSession); + return d->captureSession.get(); +} +/*! + \qmlsignal QtMultimedia::CaptureSession::audioInputChanged() + This signal is emitted when an audio input has changed. + \sa CaptureSession::audioInput +*/ + +/*! + \qmlsignal QtMultimedia::CaptureSession::cameraChanged() + This signal is emitted when the selected camera has changed. + \sa CaptureSession::camera +*/ + +/*! + \qmlsignal QtMultimedia::CaptureSession::imageCaptureChanged() + This signal is emitted when the selected interface has changed. + \sa CaptureSession::camera +*/ + +/*! + \qmlsignal QtMultimedia::CaptureSession::recorderChanged() + This signal is emitted when the selected recorder has changed. + \sa CaptureSession::recorder +*/ + +/*! + \qmlsignal QtMultimedia::CaptureSession::videoOutputChanged() + This signal is emitted when the selected video output has changed. + \sa CaptureSession::videoOutput +*/ + +/*! + \qmlsignal QtMultimedia::CaptureSession::audioOutputChanged() + This signal is emitted when the selected audio output has changed. + \sa CaptureSession::audioOutput +*/ +QT_END_NAMESPACE + +#include "moc_qmediacapturesession.cpp" diff --git a/src/multimedia/recording/qmediacapturesession.h b/src/multimedia/recording/qmediacapturesession.h new file mode 100644 index 000000000..219c382d1 --- /dev/null +++ b/src/multimedia/recording/qmediacapturesession.h @@ -0,0 +1,106 @@ +// Copyright (C) 2016 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 QMEDIACAPTURESESSION_H +#define QMEDIACAPTURESESSION_H + +#include <QtCore/qobject.h> +#include <QtMultimedia/qtmultimediaglobal.h> + +QT_BEGIN_NAMESPACE + +class QCamera; +class QAudioInput; +class QAudioBufferInput; +class QAudioOutput; +class QCameraDevice; +class QImageCapture; +class QMediaRecorder; +class QPlatformMediaCaptureSession; +class QVideoSink; +class QScreenCapture; +class QWindowCapture; +class QVideoFrameInput; + +class QMediaCaptureSessionPrivate; +class Q_MULTIMEDIA_EXPORT QMediaCaptureSession : public QObject +{ + Q_OBJECT + Q_PROPERTY(QAudioInput *audioInput READ audioInput WRITE setAudioInput NOTIFY audioInputChanged) + Q_PROPERTY(QAudioBufferInput *audioBufferInput READ audioBufferInput WRITE setAudioBufferInput + NOTIFY audioBufferInputChanged) + Q_PROPERTY(QAudioOutput *audioOutput READ audioOutput WRITE setAudioOutput NOTIFY audioOutputChanged) + 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(QVideoFrameInput *videoFrameInput READ videoFrameInput WRITE setVideoFrameInput + NOTIFY videoFrameInputChanged) + 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) +public: + explicit QMediaCaptureSession(QObject *parent = nullptr); + ~QMediaCaptureSession(); + + QAudioInput *audioInput() const; + void setAudioInput(QAudioInput *input); + + QAudioBufferInput *audioBufferInput() const; + void setAudioBufferInput(QAudioBufferInput *input); + + QCamera *camera() const; + void setCamera(QCamera *camera); + + QImageCapture *imageCapture(); + void setImageCapture(QImageCapture *imageCapture); + + QScreenCapture *screenCapture(); + void setScreenCapture(QScreenCapture *screenCapture); + + QWindowCapture *windowCapture(); + void setWindowCapture(QWindowCapture *windowCapture); + + QVideoFrameInput *videoFrameInput() const; + void setVideoFrameInput(QVideoFrameInput *input); + + QMediaRecorder *recorder(); + void setRecorder(QMediaRecorder *recorder); + + void setVideoOutput(QObject *output); + QObject *videoOutput() const; + + void setVideoSink(QVideoSink *sink); + QVideoSink *videoSink() const; + + void setAudioOutput(QAudioOutput *output); + QAudioOutput *audioOutput() const; + + QPlatformMediaCaptureSession *platformSession() const; + +Q_SIGNALS: + void audioInputChanged(); + void audioBufferInputChanged(); + void cameraChanged(); + void screenCaptureChanged(); + void windowCaptureChanged(); + void videoFrameInputChanged(); + void imageCaptureChanged(); + void recorderChanged(); + void videoOutputChanged(); + void audioOutputChanged(); + +private: + friend class QPlatformMediaCaptureSession; + + // ### Qt7: remove unused member + QT6_ONLY(void *unused = nullptr;) // for ABI compatibility + + Q_DISABLE_COPY(QMediaCaptureSession) + Q_DECLARE_PRIVATE(QMediaCaptureSession) +}; + +QT_END_NAMESPACE + +#endif // QMEDIACAPTURESESSION_H diff --git a/src/multimedia/recording/qmediacapturesession_p.h b/src/multimedia/recording/qmediacapturesession_p.h new file mode 100644 index 000000000..cba222993 --- /dev/null +++ b/src/multimedia/recording/qmediacapturesession_p.h @@ -0,0 +1,53 @@ +// Copyright (C) 2024 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 QMEDIACAPTURESESSION_P_H +#define QMEDIACAPTURESESSION_P_H + +// +// 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. +// + +#include <QtMultimedia/qmediacapturesession.h> + +#include <QtCore/qpointer.h> +#include <QtCore/private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +class QMediaCaptureSessionPrivate : public QObjectPrivate +{ +public: + static QMediaCaptureSessionPrivate *get(QMediaCaptureSession *session) + { + return reinterpret_cast<QMediaCaptureSessionPrivate *>(QObjectPrivate::get(session)); + } + + Q_DECLARE_PUBLIC(QMediaCaptureSession) + + std::unique_ptr<QPlatformMediaCaptureSession> captureSession; + QAudioInput *audioInput = nullptr; + QPointer<QAudioBufferInput> audioBufferInput; + QAudioOutput *audioOutput = nullptr; + QPointer<QCamera> camera; + QPointer<QScreenCapture> screenCapture; + QPointer<QWindowCapture> windowCapture; + QPointer<QVideoFrameInput> videoFrameInput; + QPointer<QImageCapture> imageCapture; + QPointer<QMediaRecorder> recorder; + QPointer<QVideoSink> videoSink; + QPointer<QObject> videoOutput; + + void setVideoSink(QVideoSink *sink); +}; + +QT_END_NAMESPACE + +#endif // QMEDIACAPTURESESSION_P_H diff --git a/src/multimedia/recording/qmediaencodersettings.cpp b/src/multimedia/recording/qmediaencodersettings.cpp deleted file mode 100644 index 0e169c2b0..000000000 --- a/src/multimedia/recording/qmediaencodersettings.cpp +++ /dev/null @@ -1,952 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmediaencodersettings.h" - -QT_BEGIN_NAMESPACE - -static void qRegisterEncoderSettingsMetaTypes() -{ - qRegisterMetaType<QAudioEncoderSettings>(); - qRegisterMetaType<QVideoEncoderSettings>(); - qRegisterMetaType<QImageEncoderSettings>(); -} - -Q_CONSTRUCTOR_FUNCTION(qRegisterEncoderSettingsMetaTypes) - - -class QAudioEncoderSettingsPrivate : public QSharedData -{ -public: - QAudioEncoderSettingsPrivate() : - isNull(true), - encodingMode(QMultimedia::ConstantQualityEncoding), - bitrate(-1), - sampleRate(-1), - channels(-1), - quality(QMultimedia::NormalQuality) - { - } - - QAudioEncoderSettingsPrivate(const QAudioEncoderSettingsPrivate &other): - QSharedData(other), - isNull(other.isNull), - encodingMode(other.encodingMode), - codec(other.codec), - bitrate(other.bitrate), - sampleRate(other.sampleRate), - channels(other.channels), - quality(other.quality), - encodingOptions(other.encodingOptions) - { - } - - bool isNull; - QMultimedia::EncodingMode encodingMode; - QString codec; - int bitrate; - int sampleRate; - int channels; - QMultimedia::EncodingQuality quality; - QVariantMap encodingOptions; - -private: - QAudioEncoderSettingsPrivate& operator=(const QAudioEncoderSettingsPrivate &other); -}; - -/*! - \class QAudioEncoderSettings - - \brief The QAudioEncoderSettings class provides a set of audio encoder settings. - - \inmodule QtMultimedia - \ingroup multimedia - \ingroup multimedia_recording - - A audio encoder settings object is used to specify the audio encoder - settings used by QMediaRecorder. Audio encoder settings are selected by - constructing a QAudioEncoderSettings object, setting the desired properties - and then passing it to a QMediaRecorder instance using the - QMediaRecorder::setEncodingSettings() function. - - \snippet multimedia-snippets/media.cpp Audio encoder settings - - \sa QMediaRecorder, QAudioEncoderSettingsControl -*/ - -/*! - Construct a null audio encoder settings object. -*/ -QAudioEncoderSettings::QAudioEncoderSettings() - :d(new QAudioEncoderSettingsPrivate) -{ -} - -/*! - Constructs a copy of the audio encoder settings object \a other. -*/ - -QAudioEncoderSettings::QAudioEncoderSettings(const QAudioEncoderSettings& other) - :d(other.d) -{ -} - -/*! - Destroys an audio encoder settings object. -*/ - -QAudioEncoderSettings::~QAudioEncoderSettings() -{ -} - -/*! - Assigns the value of \a other to an audio encoder settings object. -*/ - -QAudioEncoderSettings& QAudioEncoderSettings::operator=(const QAudioEncoderSettings &other) -{ - d = other.d; - return *this; -} - -/*! - Determines if \a other is of equal value to an audio encoder settings - object. - - Returns true if the settings objects are of equal value, and false if they - are not of equal value. -*/ - -bool QAudioEncoderSettings::operator==(const QAudioEncoderSettings &other) const -{ - return (d == other.d) || - (d->isNull == other.d->isNull && - d->encodingMode == other.d->encodingMode && - d->bitrate == other.d->bitrate && - d->sampleRate == other.d->sampleRate && - d->channels == other.d->channels && - d->quality == other.d->quality && - d->codec == other.d->codec && - d->encodingOptions == other.d->encodingOptions); -} - -/*! - Determines if \a other is of equal value to an audio encoder settings - object. - - Returns true if the settings objects are not of equal value, and true if - they are of equal value. -*/ - -bool QAudioEncoderSettings::operator!=(const QAudioEncoderSettings &other) const -{ - return !(*this == other); -} - -/*! - Identifies if an audio settings object is initialized. - - Returns true if the settings object is null, and false if it is not. -*/ - -bool QAudioEncoderSettings::isNull() const -{ - return d->isNull; -} - -/*! - Returns the audio encoding mode. - - \sa QMultimedia::EncodingMode -*/ -QMultimedia::EncodingMode QAudioEncoderSettings::encodingMode() const -{ - return d->encodingMode; -} - -/*! - Sets the audio encoding \a mode setting. - - If QMultimedia::ConstantQualityEncoding is set, the quality - encoding parameter is used and bit rate is ignored, - otherwise the bitrate is used. - - The audio codec, channels count and sample rate settings are used in all - the encoding modes. - - \sa encodingMode(), QMultimedia::EncodingMode -*/ -void QAudioEncoderSettings::setEncodingMode(QMultimedia::EncodingMode mode) -{ - d->encodingMode = mode; -} - -/*! - Returns the audio codec. -*/ -QString QAudioEncoderSettings::codec() const -{ - return d->codec; -} - -/*! - Sets the audio \a codec. -*/ -void QAudioEncoderSettings::setCodec(const QString& codec) -{ - d->isNull = false; - d->codec = codec; -} - -/*! - Returns the bit rate of the compressed audio stream in bits per second. -*/ -int QAudioEncoderSettings::bitRate() const -{ - return d->bitrate; -} - -/*! - Returns the number of audio channels. -*/ -int QAudioEncoderSettings::channelCount() const -{ - return d->channels; -} - -/*! - Sets the number of audio \a channels. - - A value of -1 indicates the encoder should make an optimal choice based on - what is available from the audio source and the limitations of the codec. -*/ -void QAudioEncoderSettings::setChannelCount(int channels) -{ - d->isNull = false; - d->channels = channels; -} - -/*! - Sets the audio bit \a rate in bits per second. -*/ -void QAudioEncoderSettings::setBitRate(int rate) -{ - d->isNull = false; - d->bitrate = rate; -} - -/*! - Returns the audio sample rate in Hz. -*/ -int QAudioEncoderSettings::sampleRate() const -{ - return d->sampleRate; -} - -/*! - Sets the audio sample \a rate in Hz. - - A value of -1 indicates the encoder should make an optimal choice based on what is avaialbe - from the audio source and the limitations of the codec. - */ -void QAudioEncoderSettings::setSampleRate(int rate) -{ - d->isNull = false; - d->sampleRate = rate; -} - -/*! - Returns the audio encoding quality. -*/ - -QMultimedia::EncodingQuality QAudioEncoderSettings::quality() const -{ - return d->quality; -} - -/*! - Set the audio encoding \a quality. - - Setting the audio quality parameter allows backend to choose the balanced - set of encoding parameters to achieve the desired quality level. - - The \a quality settings parameter is only used in the - \l {QMultimedia::ConstantQualityEncoding}{constant quality} \l{encodingMode()}{encoding mode}. -*/ -void QAudioEncoderSettings::setQuality(QMultimedia::EncodingQuality quality) -{ - d->isNull = false; - d->quality = quality; -} - -/*! - Returns the value of encoding \a option. - - \sa setEncodingOption(), encodingOptions() -*/ -QVariant QAudioEncoderSettings::encodingOption(const QString &option) const -{ - return d->encodingOptions.value(option); -} - -/*! - Returns the all the encoding options as QVariantMap. - - \sa encodingOption(), setEncodingOptions() -*/ -QVariantMap QAudioEncoderSettings::encodingOptions() const -{ - return d->encodingOptions; -} - -/*! - Set the encoding \a option to \a value. - - The supported set and meaning of encoding options are - system and selected codec specific. - - \sa encodingOption(), setEncodingOptions() -*/ -void QAudioEncoderSettings::setEncodingOption(const QString &option, const QVariant &value) -{ - d->isNull = false; - if (value.isNull()) - d->encodingOptions.remove(option); - else - d->encodingOptions.insert(option, value); -} - -/*! - Replace all the encoding options with \a options. - - The supported set and meaning of encoding options are - system and selected codec specific. - - \sa encodingOption(), setEncodingOption() -*/ -void QAudioEncoderSettings::setEncodingOptions(const QVariantMap &options) -{ - d->isNull = false; - d->encodingOptions = options; -} - -class QVideoEncoderSettingsPrivate : public QSharedData -{ -public: - QVideoEncoderSettingsPrivate() : - isNull(true), - encodingMode(QMultimedia::ConstantQualityEncoding), - bitrate(-1), - frameRate(0), - quality(QMultimedia::NormalQuality) - { - } - - QVideoEncoderSettingsPrivate(const QVideoEncoderSettingsPrivate &other): - QSharedData(other), - isNull(other.isNull), - encodingMode(other.encodingMode), - codec(other.codec), - bitrate(other.bitrate), - resolution(other.resolution), - frameRate(other.frameRate), - quality(other.quality), - encodingOptions(other.encodingOptions) - { - } - - bool isNull; - QMultimedia::EncodingMode encodingMode; - QString codec; - int bitrate; - QSize resolution; - qreal frameRate; - QMultimedia::EncodingQuality quality; - QVariantMap encodingOptions; - -private: - QVideoEncoderSettingsPrivate& operator=(const QVideoEncoderSettingsPrivate &other); -}; - -/*! - \class QVideoEncoderSettings - - \brief The QVideoEncoderSettings class provides a set of video encoder settings. - - \inmodule QtMultimedia - \ingroup multimedia - \ingroup multimedia_recording - - A video encoder settings object is used to specify the video encoder - settings used by QMediaRecorder. Video encoder settings are selected by - constructing a QVideoEncoderSettings object, setting the desired properties - and then passing it to a QMediaRecorder instance using the - QMediaRecorder::setEncodingSettings() function. - - \snippet multimedia-snippets/media.cpp Video encoder settings - - \sa QMediaRecorder, QVideoEncoderSettingsControl -*/ - -/*! - Constructs a null video encoder settings object. -*/ - -QVideoEncoderSettings::QVideoEncoderSettings() - :d(new QVideoEncoderSettingsPrivate) -{ -} - -/*! - Constructs a copy of the video encoder settings object \a other. -*/ - -QVideoEncoderSettings::QVideoEncoderSettings(const QVideoEncoderSettings& other) - :d(other.d) -{ -} - -/*! - Destroys a video encoder settings object. -*/ - -QVideoEncoderSettings::~QVideoEncoderSettings() -{ -} - -/*! - Assigns the value of \a other to a video encoder settings object. -*/ -QVideoEncoderSettings &QVideoEncoderSettings::operator=(const QVideoEncoderSettings &other) -{ - d = other.d; - return *this; -} - -/*! - Determines if \a other is of equal value to a video encoder settings object. - - Returns true if the settings objects are of equal value, and false if they - are not of equal value. -*/ -bool QVideoEncoderSettings::operator==(const QVideoEncoderSettings &other) const -{ - return (d == other.d) || - (d->isNull == other.d->isNull && - d->encodingMode == other.d->encodingMode && - d->bitrate == other.d->bitrate && - d->quality == other.d->quality && - d->codec == other.d->codec && - d->resolution == other.d->resolution && - qFuzzyCompare(d->frameRate, other.d->frameRate) && - d->encodingOptions == other.d->encodingOptions); -} - -/*! - Determines if \a other is of equal value to a video encoder settings object. - - Returns true if the settings objects are not of equal value, and false if - they are of equal value. -*/ -bool QVideoEncoderSettings::operator!=(const QVideoEncoderSettings &other) const -{ - return !(*this == other); -} - -/*! - Identifies if a video encoder settings object is uninitalized. - - Returns true if the settings are null, and false if they are not. -*/ -bool QVideoEncoderSettings::isNull() const -{ - return d->isNull; -} - -/*! - Returns the video encoding mode. - - \sa QMultimedia::EncodingMode -*/ -QMultimedia::EncodingMode QVideoEncoderSettings::encodingMode() const -{ - return d->encodingMode; -} - -/*! - Sets the video encoding \a mode. - - If QMultimedia::ConstantQualityEncoding is set, - the quality encoding parameter is used and bit rate is ignored, - otherwise the bitrate is used. - - The rest of encoding settings are respected regardless of encoding mode. - - \sa QMultimedia::EncodingMode -*/ -void QVideoEncoderSettings::setEncodingMode(QMultimedia::EncodingMode mode) -{ - d->isNull = false; - d->encodingMode = mode; -} - -/*! - Returns the video codec. -*/ - -QString QVideoEncoderSettings::codec() const -{ - return d->codec; -} - -/*! - Sets the video \a codec. -*/ -void QVideoEncoderSettings::setCodec(const QString& codec) -{ - d->isNull = false; - d->codec = codec; -} - -/*! - Returns bit rate of the encoded video stream in bits per second. -*/ -int QVideoEncoderSettings::bitRate() const -{ - return d->bitrate; -} - -/*! - Sets the bit rate of the encoded video stream to \a value. -*/ - -void QVideoEncoderSettings::setBitRate(int value) -{ - d->isNull = false; - d->bitrate = value; -} - -/*! - Returns the video frame rate. -*/ -qreal QVideoEncoderSettings::frameRate() const -{ - return d->frameRate; -} - -/*! - \fn QVideoEncoderSettings::setFrameRate(qreal rate) - - Sets the video frame \a rate. - - A value of 0 indicates the encoder should make an optimal choice based on what is available - from the video source and the limitations of the codec. -*/ - -void QVideoEncoderSettings::setFrameRate(qreal rate) -{ - d->isNull = false; - d->frameRate = rate; -} - -/*! - Returns the resolution of the encoded video. -*/ - -QSize QVideoEncoderSettings::resolution() const -{ - return d->resolution; -} - -/*! - Sets the \a resolution of the encoded video. - - An empty QSize indicates the encoder should make an optimal choice based on - what is available from the video source and the limitations of the codec. -*/ - -void QVideoEncoderSettings::setResolution(const QSize &resolution) -{ - d->isNull = false; - d->resolution = resolution; -} - -/*! - Sets the \a width and \a height of the resolution of the encoded video. - - \overload -*/ - -void QVideoEncoderSettings::setResolution(int width, int height) -{ - d->isNull = false; - d->resolution = QSize(width, height); -} - -/*! - Returns the video encoding quality. -*/ - -QMultimedia::EncodingQuality QVideoEncoderSettings::quality() const -{ - return d->quality; -} - -/*! - Sets the video encoding \a quality. - - Setting the video quality parameter allows backend to choose the balanced - set of encoding parameters to achieve the desired quality level. - - The \a quality settings parameter is only used in the - \l {QMultimedia::ConstantQualityEncoding}{constant quality} \l{encodingMode()}{encoding mode}. - The \a quality settings parameter is only used in the \l - {QMultimedia::ConstantQualityEncoding}{constant quality} - \l{encodingMode()}{encoding mode}. -*/ - -void QVideoEncoderSettings::setQuality(QMultimedia::EncodingQuality quality) -{ - d->isNull = false; - d->quality = quality; -} - -/*! - Returns the value of encoding \a option. - - \sa setEncodingOption(), encodingOptions() -*/ -QVariant QVideoEncoderSettings::encodingOption(const QString &option) const -{ - return d->encodingOptions.value(option); -} - -/*! - Returns the all the encoding options as QVariantMap. - - \sa encodingOption(), setEncodingOptions() -*/ -QVariantMap QVideoEncoderSettings::encodingOptions() const -{ - return d->encodingOptions; -} - -/*! - Set the encoding \a option \a value. - - The supported set and meaning of encoding options are - system and selected codec specific. - - \sa encodingOption(), setEncodingOptions() -*/ -void QVideoEncoderSettings::setEncodingOption(const QString &option, const QVariant &value) -{ - d->isNull = false; - if (value.isNull()) - d->encodingOptions.remove(option); - else - d->encodingOptions.insert(option, value); -} - -/*! - Replace all the encoding options with \a options. - - The supported set and meaning of encoding options are - system and selected codec specific. - - \sa encodingOption(), setEncodingOption() -*/ -void QVideoEncoderSettings::setEncodingOptions(const QVariantMap &options) -{ - d->isNull = false; - d->encodingOptions = options; -} - - -class QImageEncoderSettingsPrivate : public QSharedData -{ -public: - QImageEncoderSettingsPrivate() : - isNull(true), - quality(QMultimedia::NormalQuality) - { - } - - QImageEncoderSettingsPrivate(const QImageEncoderSettingsPrivate &other): - QSharedData(other), - isNull(other.isNull), - codec(other.codec), - resolution(other.resolution), - quality(other.quality), - encodingOptions(other.encodingOptions) - { - } - - bool isNull; - QString codec; - QSize resolution; - QMultimedia::EncodingQuality quality; - QVariantMap encodingOptions; - -private: - QImageEncoderSettingsPrivate& operator=(const QImageEncoderSettingsPrivate &other); -}; - -/*! - \class QImageEncoderSettings - - - \brief The QImageEncoderSettings class provides a set of image encoder - settings. - - \inmodule QtMultimedia - \ingroup multimedia - \ingroup multimedia_camera - - A image encoder settings object is used to specify the image encoder - settings used by QCameraImageCapture. Image encoder settings are selected - by constructing a QImageEncoderSettings object, setting the desired - properties and then passing it to a QCameraImageCapture instance using the - QCameraImageCapture::setImageSettings() function. - - \snippet multimedia-snippets/media.cpp Image encoder settings - - \sa QImageEncoderControl -*/ - -/*! - Constructs a null image encoder settings object. -*/ - -QImageEncoderSettings::QImageEncoderSettings() - :d(new QImageEncoderSettingsPrivate) -{ -} - -/*! - Constructs a copy of the image encoder settings object \a other. -*/ - -QImageEncoderSettings::QImageEncoderSettings(const QImageEncoderSettings& other) - :d(other.d) -{ -} - -/*! - Destroys a image encoder settings object. -*/ - -QImageEncoderSettings::~QImageEncoderSettings() -{ -} - -/*! - Assigns the value of \a other to a image encoder settings object. -*/ -QImageEncoderSettings &QImageEncoderSettings::operator=(const QImageEncoderSettings &other) -{ - d = other.d; - return *this; -} - -/*! - Determines if \a other is of equal value to a image encoder settings - object. - - Returns true if the settings objects are of equal value, and false if they - are not of equal value. -*/ -bool QImageEncoderSettings::operator==(const QImageEncoderSettings &other) const -{ - return (d == other.d) || - (d->isNull == other.d->isNull && - d->quality == other.d->quality && - d->codec == other.d->codec && - d->resolution == other.d->resolution && - d->encodingOptions == other.d->encodingOptions); - -} - -/*! - Determines if \a other is of equal value to a image encoder settings - object. - - Returns true if the settings objects are not of equal value, and false if - they are of equal value. -*/ -bool QImageEncoderSettings::operator!=(const QImageEncoderSettings &other) const -{ - return !(*this == other); -} - -/*! - Identifies if a image encoder settings object is uninitalized. - - Returns true if the settings are null, and false if they are not. -*/ -bool QImageEncoderSettings::isNull() const -{ - return d->isNull; -} - -/*! - Returns the image codec. -*/ - -QString QImageEncoderSettings::codec() const -{ - return d->codec; -} - -/*! - Sets the image \a codec. -*/ -void QImageEncoderSettings::setCodec(const QString& codec) -{ - d->isNull = false; - d->codec = codec; -} - -/*! - Returns the resolution of the encoded image. -*/ - -QSize QImageEncoderSettings::resolution() const -{ - return d->resolution; -} - -/*! - Sets the \a resolution of the encoded image. - - An empty QSize indicates the encoder should make an optimal choice based on - what is available from the image source and the limitations of the codec. -*/ - -void QImageEncoderSettings::setResolution(const QSize &resolution) -{ - d->isNull = false; - d->resolution = resolution; -} - -/*! - Sets the \a width and \a height of the resolution of the encoded image. - - \overload -*/ - -void QImageEncoderSettings::setResolution(int width, int height) -{ - d->isNull = false; - d->resolution = QSize(width, height); -} - -/*! - Returns the image encoding quality. -*/ - -QMultimedia::EncodingQuality QImageEncoderSettings::quality() const -{ - return d->quality; -} - -/*! - Sets the image encoding \a quality. -*/ - -void QImageEncoderSettings::setQuality(QMultimedia::EncodingQuality quality) -{ - d->isNull = false; - d->quality = quality; -} - -/*! - Returns the value of encoding \a option. - - \sa setEncodingOption(), encodingOptions() -*/ -QVariant QImageEncoderSettings::encodingOption(const QString &option) const -{ - return d->encodingOptions.value(option); -} - -/*! - Returns the all the encoding options as QVariantMap. - - \sa encodingOption(), setEncodingOptions() -*/ -QVariantMap QImageEncoderSettings::encodingOptions() const -{ - return d->encodingOptions; -} - -/*! - Set the encoding \a option \a value. - - The supported set and meaning of encoding options are - system and selected codec specific. - - \sa encodingOption(), setEncodingOptions() -*/ -void QImageEncoderSettings::setEncodingOption(const QString &option, const QVariant &value) -{ - d->isNull = false; - if (value.isNull()) - d->encodingOptions.remove(option); - else - d->encodingOptions.insert(option, value); -} - -/*! - Replace all the encoding options with \a options. - - The supported set and meaning of encoding options are - system and selected codec specific. - - \sa encodingOption(), setEncodingOption() -*/ -void QImageEncoderSettings::setEncodingOptions(const QVariantMap &options) -{ - d->isNull = false; - d->encodingOptions = options; -} - - -QT_END_NAMESPACE - diff --git a/src/multimedia/recording/qmediaencodersettings.h b/src/multimedia/recording/qmediaencodersettings.h deleted file mode 100644 index 0d6a9eddf..000000000 --- a/src/multimedia/recording/qmediaencodersettings.h +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMEDIAENCODERSETTINGS_H -#define QMEDIAENCODERSETTINGS_H - -#include <QtCore/qsharedpointer.h> -#include <QtCore/qstring.h> -#include <QtCore/qsize.h> -#include <QtCore/qvariant.h> -#include <QtMultimedia/qtmultimediaglobal.h> -#include <QtMultimedia/qmultimedia.h> - -QT_BEGIN_NAMESPACE - - - -class QAudioEncoderSettingsPrivate; -class Q_MULTIMEDIA_EXPORT QAudioEncoderSettings -{ -public: - QAudioEncoderSettings(); - QAudioEncoderSettings(const QAudioEncoderSettings& other); - - ~QAudioEncoderSettings(); - - QAudioEncoderSettings& operator=(const QAudioEncoderSettings &other); - bool operator==(const QAudioEncoderSettings &other) const; - bool operator!=(const QAudioEncoderSettings &other) const; - - bool isNull() const; - - QMultimedia::EncodingMode encodingMode() const; - void setEncodingMode(QMultimedia::EncodingMode); - - QString codec() const; - void setCodec(const QString& codec); - - int bitRate() const; - void setBitRate(int bitrate); - - int channelCount() const; - void setChannelCount(int channels); - - int sampleRate() const; - void setSampleRate(int rate); - - QMultimedia::EncodingQuality quality() const; - void setQuality(QMultimedia::EncodingQuality quality); - - QVariant encodingOption(const QString &option) const; - QVariantMap encodingOptions() const; - void setEncodingOption(const QString &option, const QVariant &value); - void setEncodingOptions(const QVariantMap &options); - -private: - QSharedDataPointer<QAudioEncoderSettingsPrivate> d; -}; - -class QVideoEncoderSettingsPrivate; -class Q_MULTIMEDIA_EXPORT QVideoEncoderSettings -{ -public: - QVideoEncoderSettings(); - QVideoEncoderSettings(const QVideoEncoderSettings& other); - - ~QVideoEncoderSettings(); - - QVideoEncoderSettings& operator=(const QVideoEncoderSettings &other); - bool operator==(const QVideoEncoderSettings &other) const; - bool operator!=(const QVideoEncoderSettings &other) const; - - bool isNull() const; - - QMultimedia::EncodingMode encodingMode() const; - void setEncodingMode(QMultimedia::EncodingMode); - - QString codec() const; - void setCodec(const QString &); - - QSize resolution() const; - void setResolution(const QSize &); - void setResolution(int width, int height); - - qreal frameRate() const; - void setFrameRate(qreal rate); - - int bitRate() const; - void setBitRate(int bitrate); - - QMultimedia::EncodingQuality quality() const; - void setQuality(QMultimedia::EncodingQuality quality); - - QVariant encodingOption(const QString &option) const; - QVariantMap encodingOptions() const; - void setEncodingOption(const QString &option, const QVariant &value); - void setEncodingOptions(const QVariantMap &options); - -private: - QSharedDataPointer<QVideoEncoderSettingsPrivate> d; -}; - -class QImageEncoderSettingsPrivate; -class Q_MULTIMEDIA_EXPORT QImageEncoderSettings -{ -public: - QImageEncoderSettings(); - QImageEncoderSettings(const QImageEncoderSettings& other); - - ~QImageEncoderSettings(); - - QImageEncoderSettings& operator=(const QImageEncoderSettings &other); - bool operator==(const QImageEncoderSettings &other) const; - bool operator!=(const QImageEncoderSettings &other) const; - - bool isNull() const; - - QString codec() const; - void setCodec(const QString &); - - QSize resolution() const; - void setResolution(const QSize &); - void setResolution(int width, int height); - - QMultimedia::EncodingQuality quality() const; - void setQuality(QMultimedia::EncodingQuality quality); - - QVariant encodingOption(const QString &option) const; - QVariantMap encodingOptions() const; - void setEncodingOption(const QString &option, const QVariant &value); - void setEncodingOptions(const QVariantMap &options); - -private: - QSharedDataPointer<QImageEncoderSettingsPrivate> d; -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QAudioEncoderSettings) -Q_DECLARE_METATYPE(QVideoEncoderSettings) -Q_DECLARE_METATYPE(QImageEncoderSettings) - - -#endif diff --git a/src/multimedia/recording/qmediarecorder.cpp b/src/multimedia/recording/qmediarecorder.cpp index 617627985..ea38b231a 100644 --- a/src/multimedia/recording/qmediarecorder.cpp +++ b/src/multimedia/recording/qmediarecorder.cpp @@ -1,61 +1,24 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmediarecorder.h" +// Copyright (C) 2016 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 "qmediarecorder_p.h" -#include <qmediarecordercontrol.h> -#include "qmediaobject_p.h" -#include <qmediaservice.h> -#include <qmediaserviceprovider_p.h> -#include <qmetadatawritercontrol.h> -#include <qaudioencodersettingscontrol.h> -#include <qvideoencodersettingscontrol.h> -#include <qmediacontainercontrol.h> -#include <qmediaavailabilitycontrol.h> +#include <private/qplatformmediarecorder_p.h> +#include <qaudiodevice.h> #include <qcamera.h> -#include <qcameracontrol.h> +#include <qscreencapture.h> +#include <qwindowcapture.h> +#include <qmediacapturesession.h> +#include <private/qplatformcamera_p.h> +#include <private/qplatformsurfacecapture_p.h> +#include <private/qplatformmediaintegration_p.h> +#include <private/qplatformmediacapture_p.h> #include <QtCore/qdebug.h> #include <QtCore/qurl.h> #include <QtCore/qstringlist.h> #include <QtCore/qmetaobject.h> +#include <QtCore/qtimer.h> #include <qaudioformat.h> @@ -66,179 +29,103 @@ QT_BEGIN_NAMESPACE \inmodule QtMultimedia \ingroup multimedia \ingroup multimedia_recording + \ingroup multimedia_video + \ingroup multimedia_audio - \brief The QMediaRecorder class is used for the recording of media content. + \brief The QMediaRecorder class is used for encoding and recording a capture session. - The QMediaRecorder class is a high level media recording class. It's not - intended to be used alone but for accessing the media recording functions - of other media objects, like QCamera. + The QMediaRecorder class is a class for encoding and recording media generated in a + QMediaCaptureSession. \snippet multimedia-snippets/media.cpp Media recorder - - \sa QAudioRecorder */ +/*! + \qmltype MediaRecorder + \instantiates QMediaRecorder + \brief For encoding and recording media generated in a CaptureSession. -static void qRegisterMediaRecorderMetaTypes() -{ - qRegisterMetaType<QMediaRecorder::State>("QMediaRecorder::State"); - qRegisterMetaType<QMediaRecorder::Status>("QMediaRecorder::Status"); - qRegisterMetaType<QMediaRecorder::Error>("QMediaRecorder::Error"); -} - -Q_CONSTRUCTOR_FUNCTION(qRegisterMediaRecorderMetaTypes) - - -QMediaRecorderPrivate::QMediaRecorderPrivate(): - mediaObject(nullptr), - control(nullptr), - formatControl(nullptr), - audioControl(nullptr), - videoControl(nullptr), - metaDataControl(nullptr), - availabilityControl(nullptr), - settingsChanged(false), - notifyTimer(nullptr), - state(QMediaRecorder::StoppedState), - error(QMediaRecorder::NoError) -{ -} - -#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v))) - -void QMediaRecorderPrivate::_q_stateChanged(QMediaRecorder::State ps) -{ - Q_Q(QMediaRecorder); - - if (ps == QMediaRecorder::RecordingState) - notifyTimer->start(); - else - notifyTimer->stop(); - -// qDebug() << "Recorder state changed:" << ENUM_NAME(QMediaRecorder,"State",ps); - if (state != ps) { - emit q->stateChanged(ps); - } - - state = ps; -} - - -void QMediaRecorderPrivate::_q_error(int error, const QString &errorString) -{ - Q_Q(QMediaRecorder); - - this->error = QMediaRecorder::Error(error); - this->errorString = errorString; + \inqmlmodule QtMultimedia + \ingroup multimedia_qml + \ingroup multimedia_audio_qml + \ingroup multimedia_video_qml - emit q->error(this->error); -} + The MediaRecorder element can be used within a CaptureSession to record and encode audio and + video captured from a microphone and camera -void QMediaRecorderPrivate::_q_serviceDestroyed() -{ - mediaObject = nullptr; - control = nullptr; - formatControl = nullptr; - audioControl = nullptr; - videoControl = nullptr; - metaDataControl = nullptr; - availabilityControl = nullptr; - settingsChanged = true; -} + \since 6.2 + The code below shows a simple capture session containing a MediaRecorder using the default + camera and default audio input. -void QMediaRecorderPrivate::_q_updateActualLocation(const QUrl &location) -{ - if (actualLocation != location) { - actualLocation = location; - emit q_func()->actualLocationChanged(actualLocation); +\qml + CaptureSession { + id: captureSession + camera: Camera { + id: camera + active: true + } + audioInput: AudioInput {} + recorder: MediaRecorder { + id: recorder + } } -} - -void QMediaRecorderPrivate::_q_notify() -{ - emit q_func()->durationChanged(q_func()->duration()); -} - -void QMediaRecorderPrivate::_q_updateNotifyInterval(int ms) -{ - notifyTimer->setInterval(ms); -} - -void QMediaRecorderPrivate::applySettingsLater() -{ - if (control && !settingsChanged) { - settingsChanged = true; - QMetaObject::invokeMethod(q_func(), "_q_applySettings", Qt::QueuedConnection); +\endqml + + The code below shows how the recording can be started and stopped. +\qml + CameraButton { + text: "Record" + visible: recorder.recorderState !== MediaRecorder.RecordingState + onClicked: recorder.record() } -} -void QMediaRecorderPrivate::_q_applySettings() -{ - if (control && settingsChanged) { - settingsChanged = false; - control->applySettings(); + CameraButton { + id: stopButton + text: "Stop" + visible: recorder.recorderState === MediaRecorder.RecordingState + onClicked: recorder.stop() } -} +\endqml -void QMediaRecorderPrivate::_q_availabilityChanged(QMultimedia::AvailabilityStatus availability) + \sa CaptureSession, Camera, AudioInput, ImageCapture +*/ +QMediaRecorderPrivate::QMediaRecorderPrivate() { - Q_Q(QMediaRecorder); - Q_UNUSED(error); - Q_UNUSED(availability); - - // Really this should not always emit, but - // we can't really tell from here (isAvailable - // may not have changed, or the mediaobject's overridden - // availability() may not have changed). - q->availabilityChanged(q->availability()); - q->availabilityChanged(q->isAvailable()); + // Force an early initialization of the mime database + // to avoid a delay when recording for the first time. + encoderSettings.mimeType(); } -void QMediaRecorderPrivate::restartCamera() +QString QMediaRecorderPrivate::msgFailedStartRecording() { - //restart camera if it can't apply new settings in the Active state - QCamera *camera = qobject_cast<QCamera*>(mediaObject); - if (camera && camera->captureMode() == QCamera::CaptureVideo) { - QMetaObject::invokeMethod(camera, - "_q_preparePropertyChange", - Qt::DirectConnection, - Q_ARG(int, QCameraControl::VideoEncodingSettings)); - } + return QMediaRecorder::tr("Failed to start recording"); } - /*! - Constructs a media recorder which records the media produced by \a mediaObject. - - The \a parent is passed to QMediaObject. + Constructs a media recorder which records the media produced by a microphone and camera. + The media recorder is a child of \a{parent}. */ -QMediaRecorder::QMediaRecorder(QMediaObject *mediaObject, QObject *parent): - QObject(parent), - d_ptr(new QMediaRecorderPrivate) +QMediaRecorder::QMediaRecorder(QObject *parent) + : QObject(parent), + d_ptr(new QMediaRecorderPrivate) { Q_D(QMediaRecorder); - d->q_ptr = this; - d->notifyTimer = new QTimer(this); - connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify())); + auto &mediaIntegration = *QPlatformMediaIntegration::instance(); - setMediaObject(mediaObject); -} - -/*! - \internal -*/ -QMediaRecorder::QMediaRecorder(QMediaRecorderPrivate &dd, QMediaObject *mediaObject, QObject *parent): - QObject(parent), - d_ptr(&dd) -{ - Q_D(QMediaRecorder); d->q_ptr = this; - - d->notifyTimer = new QTimer(this); - connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify())); - - setMediaObject(mediaObject); + auto maybeControl = mediaIntegration.createRecorder(this); + if (maybeControl) { + // The first format info initialization may take some time, + // for users it seems to be more suitable to have a delay on the object construction + // rather than on QMediaRecorder::record + mediaIntegration.formatInfo(); + + d->control = maybeControl.value(); + } else { + d->initErrorMessage = maybeControl.error(); + qWarning() << "Failed to initialize QMediaRecorder" << maybeControl.error(); + } } /*! @@ -247,219 +134,76 @@ QMediaRecorder::QMediaRecorder(QMediaRecorderPrivate &dd, QMediaObject *mediaObj QMediaRecorder::~QMediaRecorder() { + if (d_ptr->captureSession) + d_ptr->captureSession->setRecorder(nullptr); + delete d_ptr->control; delete d_ptr; } /*! - Returns the QMediaObject instance that this QMediaRecorder is bound too, - or 0 otherwise. + \internal */ -QMediaObject *QMediaRecorder::mediaObject() const +QPlatformMediaRecorder *QMediaRecorder::platformRecoder() const { - return d_func()->mediaObject; + return d_ptr->control; } /*! \internal */ -bool QMediaRecorder::setMediaObject(QMediaObject *object) +void QMediaRecorder::setCaptureSession(QMediaCaptureSession *session) { Q_D(QMediaRecorder); + d->captureSession = session; +} +/*! + \qmlproperty QUrl QtMultimedia::MediaRecorder::outputLocation + \brief The destination location of media content. - if (object == d->mediaObject) - return true; - - if (d->mediaObject) { - if (d->control) { - disconnect(d->control, SIGNAL(stateChanged(QMediaRecorder::State)), - this, SLOT(_q_stateChanged(QMediaRecorder::State))); - - disconnect(d->control, SIGNAL(statusChanged(QMediaRecorder::Status)), - this, SIGNAL(statusChanged(QMediaRecorder::Status))); - - disconnect(d->control, SIGNAL(mutedChanged(bool)), - this, SIGNAL(mutedChanged(bool))); - - disconnect(d->control, SIGNAL(volumeChanged(qreal)), - this, SIGNAL(volumeChanged(qreal))); - - disconnect(d->control, SIGNAL(durationChanged(qint64)), - this, SIGNAL(durationChanged(qint64))); - - disconnect(d->control, SIGNAL(actualLocationChanged(QUrl)), - this, SLOT(_q_updateActualLocation(QUrl))); - - disconnect(d->control, SIGNAL(error(int,QString)), - this, SLOT(_q_error(int,QString))); - } - - disconnect(d->mediaObject, SIGNAL(notifyIntervalChanged(int)), this, SLOT(_q_updateNotifyInterval(int))); - - QMediaService *service = d->mediaObject->service(); - - if (service) { - disconnect(service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed())); - - if (d->control) - service->releaseControl(d->control); - if (d->formatControl) - service->releaseControl(d->formatControl); - if (d->audioControl) - service->releaseControl(d->audioControl); - if (d->videoControl) - service->releaseControl(d->videoControl); - if (d->metaDataControl) { - disconnect(d->metaDataControl, SIGNAL(metaDataChanged()), - this, SIGNAL(metaDataChanged())); - disconnect(d->metaDataControl, SIGNAL(metaDataChanged(QString,QVariant)), - this, SIGNAL(metaDataChanged(QString,QVariant))); - disconnect(d->metaDataControl, SIGNAL(metaDataAvailableChanged(bool)), - this, SIGNAL(metaDataAvailableChanged(bool))); - disconnect(d->metaDataControl, SIGNAL(writableChanged(bool)), - this, SIGNAL(metaDataWritableChanged(bool))); - - service->releaseControl(d->metaDataControl); - } - if (d->availabilityControl) { - disconnect(d->availabilityControl, SIGNAL(availabilityChanged(QMultimedia::AvailabilityStatus)), - this, SLOT(_q_availabilityChanged(QMultimedia::AvailabilityStatus))); - service->releaseControl(d->availabilityControl); - } - } - } - - d->control = nullptr; - d->formatControl = nullptr; - d->audioControl = nullptr; - d->videoControl = nullptr; - d->metaDataControl = nullptr; - d->availabilityControl = nullptr; - - d->mediaObject = object; - - if (d->mediaObject) { - QMediaService *service = d->mediaObject->service(); - - d->notifyTimer->setInterval(d->mediaObject->notifyInterval()); - connect(d->mediaObject, SIGNAL(notifyIntervalChanged(int)), SLOT(_q_updateNotifyInterval(int))); - - if (service) { - d->control = qobject_cast<QMediaRecorderControl*>(service->requestControl(QMediaRecorderControl_iid)); - - if (d->control) { - d->formatControl = qobject_cast<QMediaContainerControl *>(service->requestControl(QMediaContainerControl_iid)); - d->audioControl = qobject_cast<QAudioEncoderSettingsControl *>(service->requestControl(QAudioEncoderSettingsControl_iid)); - d->videoControl = qobject_cast<QVideoEncoderSettingsControl *>(service->requestControl(QVideoEncoderSettingsControl_iid)); - - QMediaControl *control = service->requestControl(QMetaDataWriterControl_iid); - if (control) { - d->metaDataControl = qobject_cast<QMetaDataWriterControl *>(control); - if (!d->metaDataControl) { - service->releaseControl(control); - } else { - connect(d->metaDataControl, - SIGNAL(metaDataChanged()), - SIGNAL(metaDataChanged())); - connect(d->metaDataControl, SIGNAL(metaDataChanged(QString,QVariant)), - this, SIGNAL(metaDataChanged(QString,QVariant))); - connect(d->metaDataControl, - SIGNAL(metaDataAvailableChanged(bool)), - SIGNAL(metaDataAvailableChanged(bool))); - connect(d->metaDataControl, - SIGNAL(writableChanged(bool)), - SIGNAL(metaDataWritableChanged(bool))); - } - } - - d->availabilityControl = service->requestControl<QMediaAvailabilityControl*>(); - if (d->availabilityControl) { - connect(d->availabilityControl, SIGNAL(availabilityChanged(QMultimedia::AvailabilityStatus)), - this, SLOT(_q_availabilityChanged(QMultimedia::AvailabilityStatus))); - } - - connect(d->control, SIGNAL(stateChanged(QMediaRecorder::State)), - this, SLOT(_q_stateChanged(QMediaRecorder::State))); - - connect(d->control, SIGNAL(statusChanged(QMediaRecorder::Status)), - this, SIGNAL(statusChanged(QMediaRecorder::Status))); - - connect(d->control, SIGNAL(mutedChanged(bool)), - this, SIGNAL(mutedChanged(bool))); - - connect(d->control, SIGNAL(volumeChanged(qreal)), - this, SIGNAL(volumeChanged(qreal))); - - connect(d->control, SIGNAL(durationChanged(qint64)), - this, SIGNAL(durationChanged(qint64))); - - connect(d->control, SIGNAL(actualLocationChanged(QUrl)), - this, SLOT(_q_updateActualLocation(QUrl))); - - connect(d->control, SIGNAL(error(int,QString)), - this, SLOT(_q_error(int,QString))); - - connect(service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed())); - - - d->applySettingsLater(); - - return true; - } - } + Setting the location can fail, for example when the service supports only + local file system locations but a network URL was passed. If the operation + fails an errorOccured() signal is emitted. - d->mediaObject = nullptr; - return false; - } + The location can be relative or empty. If empty the recorder uses the + system specific place and file naming scheme. - return true; -} + \sa errorOccurred() +*/ /*! \property QMediaRecorder::outputLocation \brief the destination location of media content. Setting the location can fail, for example when the service supports only - local file system locations but a network URL was passed. If the service - does not support media recording this setting the output location will - always fail. + local file system locations but a network URL was passed. If the operation + fails an errorOccured() signal is emitted. - The \a location can be relative or empty; - in this case the recorder uses the system specific place and file naming scheme. - After recording has stated, QMediaRecorder::outputLocation() returns the actual output location. + The output location can be relative or empty; in the latter case the recorder + uses the system specific place and file naming scheme. */ /*! - \property QMediaRecorder::actualLocation - \brief the actual location of the last media content. + \qmlproperty QUrl QtMultimedia::MediaRecorder::actualLocation + \brief The actual location of the last media content. The actual location is usually available after recording starts, and reset when new location is set or new recording starts. */ /*! - Returns true if media recorder service ready to use. + \property QMediaRecorder::actualLocation + \brief The actual location of the last media content. - \sa availabilityChanged() + The actual location is usually available after recording starts, + and reset when new location is set or new recording starts. */ -bool QMediaRecorder::isAvailable() const -{ - return availability() == QMultimedia::Available; -} /*! - Returns the availability of this functionality. - - \sa availabilityChanged() + Returns \c true if media recorder service ready to use. */ -QMultimedia::AvailabilityStatus QMediaRecorder::availability() const +bool QMediaRecorder::isAvailable() const { - if (d_func()->control == nullptr) - return QMultimedia::ServiceMissing; - - if (d_func()->availabilityControl) - return d_func()->availabilityControl->availability(); - - return QMultimedia::Available; + return d_func()->control && d_func()->captureSession; } QUrl QMediaRecorder::outputLocation() const @@ -467,41 +211,68 @@ QUrl QMediaRecorder::outputLocation() const return d_func()->control ? d_func()->control->outputLocation() : QUrl(); } -bool QMediaRecorder::setOutputLocation(const QUrl &location) +void QMediaRecorder::setOutputLocation(const QUrl &location) { Q_D(QMediaRecorder); - d->actualLocation.clear(); - return d->control ? d->control->setOutputLocation(location) : false; + if (!d->control) { + emit errorOccurred(QMediaRecorder::ResourceError, d->initErrorMessage); + return; + } + d->control->setOutputLocation(location); + d->control->clearActualLocation(); + if (!location.isEmpty() && !d->control->isLocationWritable(location)) + emit errorOccurred(QMediaRecorder::LocationNotWritable, tr("Output location not writable")); } -QUrl QMediaRecorder::actualLocation() const +/*! + Set the output IO device for media content. + + The \a device must have been opened in the \l{QIODevice::WriteOnly}{WriteOnly} or + \l{QIODevice::ReadWrite}{ReadWrite} modes before the recording starts. + + The media recorder doesn't take ownership of the specified \a device. + If the recording has been started, the device must be kept alive and open until + the signal \c recorderStateChanged(StoppedState) is emitted. + + \sa outputDevice() +*/ +void QMediaRecorder::setOutputDevice(QIODevice *device) { - return d_func()->actualLocation; + Q_D(QMediaRecorder); + d->control->setOutputDevice(device); } /*! - Returns the current media recorder state. + Returns the output IO device for media content. - \sa QMediaRecorder::State + \sa setOutputDevice() */ +QIODevice *QMediaRecorder::outputDevice() const +{ + Q_D(const QMediaRecorder); + return d->control->outputDevice(); +} -QMediaRecorder::State QMediaRecorder::state() const +QUrl QMediaRecorder::actualLocation() const { - return d_func()->control ? QMediaRecorder::State(d_func()->control->state()) : StoppedState; + Q_D(const QMediaRecorder); + return d->control ? d->control->actualLocation() : QUrl(); } /*! - Returns the current media recorder status. + Returns the current media recorder state. - \sa QMediaRecorder::Status + \sa QMediaRecorder::RecorderState */ -QMediaRecorder::Status QMediaRecorder::status() const +QMediaRecorder::RecorderState QMediaRecorder::recorderState() const { - return d_func()->control ? QMediaRecorder::Status(d_func()->control->status()) : UnavailableStatus; + return d_func()->control ? QMediaRecorder::RecorderState(d_func()->control->state()) : StoppedState; } /*! + \property QMediaRecorder::error + Returns the current error state. \sa errorString() @@ -509,10 +280,19 @@ QMediaRecorder::Status QMediaRecorder::status() const QMediaRecorder::Error QMediaRecorder::error() const { - return d_func()->error; + Q_D(const QMediaRecorder); + + return d->control ? d->control->error() : QMediaRecorder::ResourceError; } +/*! + \qmlproperty string QtMultimedia::MediaRecorder::errorString + \brief This property holds a string describing the current error state. + \sa error +*/ /*! + \property QMediaRecorder::errorString + Returns a string describing the current error state. \sa error() @@ -520,8 +300,15 @@ QMediaRecorder::Error QMediaRecorder::error() const QString QMediaRecorder::errorString() const { - return d_func()->errorString; + Q_D(const QMediaRecorder); + + return d->control ? d->control->errorString() : d->initErrorMessage; } +/*! + \qmlproperty qint64 QtMultimedia::MediaRecorder::duration + + \brief This property holds the recorded media duration in milliseconds. +*/ /*! \property QMediaRecorder::duration @@ -533,577 +320,671 @@ qint64 QMediaRecorder::duration() const { return d_func()->control ? d_func()->control->duration() : 0; } - /*! - \property QMediaRecorder::muted + \fn void QMediaRecorder::encoderSettingsChanged() - \brief whether a recording audio stream is muted. + Signals when the encoder settings change. */ +/*! + \qmlmethod QtMultimedia::MediaRecorder::record() + \brief Starts recording. -bool QMediaRecorder::isMuted() const -{ - return d_func()->control ? d_func()->control->isMuted() : 0; -} + While the recorder state is changed immediately to + \c MediaRecorder.RecordingState, recording may start asynchronously. -void QMediaRecorder::setMuted(bool muted) -{ - Q_D(QMediaRecorder); - - if (d->control) - d->control->setMuted(muted); -} + If recording fails, the error() signal is emitted with recorder state being + reset back to \c{QMediaRecorder.StoppedState}. + \note On mobile devices, recording will happen in the orientation the + device had when calling record and is locked for the duration of the recording. + To avoid artifacts on the user interface, we recommend to keep the user interface + locked to the same orientation as long as the recording is ongoing using + the contentOrientation property of the Window and unlock it again once the recording + is finished. +*/ /*! - \property QMediaRecorder::volume - - \brief the current recording audio volume. + Start recording. - The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this - range will be clamped. + While the recorder state is changed immediately to + c\{QMediaRecorder::RecordingState}, recording may start asynchronously. - The default volume is \c 1.0. + If recording fails error() signal is emitted with recorder state being + reset back to \c{QMediaRecorder::StoppedState}. - UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale - will produce linear changes in perceived loudness, which is what a user would normally expect - from a volume control. See QAudio::convertVolume() for more details. + \note On mobile devices, recording will happen in the orientation the + device had when calling record and is locked for the duration of the recording. + To avoid artifacts on the user interface, we recommend to keep the user interface + locked to the same orientation as long as the recording is ongoing using + the contentOrientation property of QWindow and unlock it again once the recording + is finished. */ -qreal QMediaRecorder::volume() const +void QMediaRecorder::record() { - return d_func()->control ? d_func()->control->volume() : 1.0; -} + Q_D(QMediaRecorder); + if (!d->control || !d->captureSession) + return; -void QMediaRecorder::setVolume(qreal volume) -{ - Q_D(QMediaRecorder); + if (d->control->state() == QMediaRecorder::PausedState) { + d->control->resume(); + } else { + auto oldMediaFormat = d->encoderSettings.mediaFormat(); - if (d->control) { - volume = qMax(qreal(0.0), volume); - d->control->setVolume(volume); + auto platformSession = d->captureSession->platformSession(); + const bool hasVideo = platformSession && !platformSession->activeVideoSources().empty(); + + d->encoderSettings.resolveFormat(hasVideo ? QMediaFormat::RequiresVideo : QMediaFormat::NoFlags); + d->control->clearActualLocation(); + d->control->clearError(); + + auto settings = d->encoderSettings; + d->control->record(d->encoderSettings); + + if (settings != d->encoderSettings) + emit encoderSettingsChanged(); + + if (oldMediaFormat != d->encoderSettings.mediaFormat()) + emit mediaFormatChanged(); } } - /*! - Returns a list of supported container formats. -*/ -QStringList QMediaRecorder::supportedContainers() const -{ - return d_func()->formatControl ? - d_func()->formatControl->supportedContainers() : QStringList(); -} + \qmlmethod QtMultimedia::MediaRecorder::pause() + \brief Pauses recording. -/*! - Returns a description of a container \a format. -*/ -QString QMediaRecorder::containerDescription(const QString &format) const -{ - return d_func()->formatControl ? - d_func()->formatControl->containerDescription(format) : QString(); -} + The recorder state is changed to QMediaRecorder.PausedState. + Depending on the platform, pausing recording may be not supported. + In this case the recorder state is unchanged. +*/ /*! - Returns the selected container format. + Pauses recording. + + The recorder state is changed to QMediaRecorder::PausedState. + + Depending on the platform, pausing recording may be not supported. + In this case the recorder state is unchanged. */ -QString QMediaRecorder::containerFormat() const +void QMediaRecorder::pause() { - return d_func()->formatControl ? - d_func()->formatControl->containerFormat() : QString(); + Q_D(QMediaRecorder); + if (d->control && d->captureSession) + d->control->pause(); } - /*! - Returns a list of supported audio codecs. + \qmlmethod QtMultimedia::MediaRecorder::stop() + \brief Stops the recording. + + The recorder will stop the recording. Processing pending video and audio data might + however still take some time. The recording is finished, once the state of the media + recorder changes to QMediaRecorder::StoppedState. */ -QStringList QMediaRecorder::supportedAudioCodecs() const -{ - return d_func()->audioControl ? - d_func()->audioControl->supportedAudioCodecs() : QStringList(); -} /*! - Returns a description of an audio \a codec. + The recorder will stop the recording. Processing pending video and audio data might + however still take some time. The recording is finished, once the state of the media + recorder changes to QMediaRecorder::StoppedState. */ -QString QMediaRecorder::audioCodecDescription(const QString &codec) const +void QMediaRecorder::stop() { - return d_func()->audioControl ? - d_func()->audioControl->codecDescription(codec) : QString(); + Q_D(QMediaRecorder); + if (d->control && d->captureSession) + d->control->stop(); } +/*! + \qmlproperty enumeration QtMultimedia::MediaRecorder::recorderState + \brief This property holds the current media recorder state. + + The state property represents the user request and is changed synchronously + during record(), pause() or stop() calls. + RecorderSstate may also change asynchronously when recording fails. + \value MediaRecorder.StoppedState The recorder is not active. + \value MediaRecorder.RecordingState The recording is requested. + \value MediaRecorder.PausedState The recorder is pause. +*/ /*! - Returns a list of supported audio sample rates. + \enum QMediaRecorder::RecorderState - If non null audio \a settings parameter is passed, the returned list is - reduced to sample rates supported with partial settings applied. + \value StoppedState The recorder is not active. + \value RecordingState The recording is requested. + \value PausedState The recorder is paused. +*/ +/*! + \qmlproperty enumeration QtMultimedia::MediaRecorder::error + \brief This property holds the current media recorder error state. - This can be used to query the list of sample rates, supported by specific - audio codec. + \value MediaRecorder.NoError Not in an error state. + \value MediaRecorder.ResourceError Not enough system resources + \value MediaRecorder.FormatError the current format is not supported. + \value MediaRecorder.OutOfSpaceError No space left on device. + \value MediaRecorder.LocationNotWriteable The output location is not writable. +*/ +/*! + \enum QMediaRecorder::Error - If the encoder supports arbitrary sample rates within the supported rates - range, *\a continuous is set to true, otherwise *\a continuous is set to - false. + \value NoError No Errors. + \value ResourceError Device is not ready or not available. + \value FormatError Current format is not supported. + \value OutOfSpaceError No space left on device. + \value LocationNotWritable The output location is not writable. */ -QList<int> QMediaRecorder::supportedAudioSampleRates(const QAudioEncoderSettings &settings, bool *continuous) const -{ - if (continuous) - *continuous = false; +/*! + \property QMediaRecorder::recorderState + \brief The current state of the media recorder. - return d_func()->audioControl ? - d_func()->audioControl->supportedSampleRates(settings, continuous) : QList<int>(); -} + The state property represents the user request and is changed synchronously + during record(), pause() or stop() calls. + Recorder state may also change asynchronously when recording fails. +*/ /*! - Returns a list of resolutions video can be encoded at. + \qmlsignal QtMultimedia::MediaRecorder::recorderStateChanged(RecorderState state) + \brief Signals that a media recorder's \a state has changed. +*/ - If non null video \a settings parameter is passed, the returned list is - reduced to resolution supported with partial settings like video codec or - framerate applied. +/*! + \fn QMediaRecorder::recorderStateChanged(QMediaRecorder::RecorderState state) - If the encoder supports arbitrary resolutions within the supported range, - *\a continuous is set to true, otherwise *\a continuous is set to false. + Signals that a media recorder's \a state has changed. +*/ - \sa QVideoEncoderSettings::resolution() +/*! + \qmlsignal QtMultimedia::MediaRecorder::durationChanged(qint64 duration) + \brief Signals that the \a duration of the recorded media has changed. */ -QList<QSize> QMediaRecorder::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const -{ - if (continuous) - *continuous = false; - return d_func()->videoControl ? - d_func()->videoControl->supportedResolutions(settings, continuous) : QList<QSize>(); -} +/*! + \fn QMediaRecorder::durationChanged(qint64 duration) + Signals that the \a duration of the recorded media has changed. +*/ /*! - Returns a list of frame rates video can be encoded at. + \qmlsignal QtMultimedia::MediaRecorder::actualLocationChanged(const QUrl &location) + \brief Signals that the actual \a location of the recorded media has changed. - If non null video \a settings parameter is passed, the returned list is - reduced to frame rates supported with partial settings like video codec or - resolution applied. + This signal is usually emitted when recording starts. +*/ +/*! + \fn QMediaRecorder::actualLocationChanged(const QUrl &location) - If the encoder supports arbitrary frame rates within the supported range, - *\a continuous is set to true, otherwise *\a continuous is set to false. + Signals that the actual \a location of the recorded media has changed. + This signal is usually emitted when recording starts. +*/ +/*! + \qmlsignal QtMultimedia::MediaRecorder::errorOccurred(Error error, const QString &errorString) + \brief Signals that an \a error has occurred. - \sa QVideoEncoderSettings::frameRate() + The \a errorString contains a description of the error. */ -QList<qreal> QMediaRecorder::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const -{ - if (continuous) - *continuous = false; +/*! + \fn QMediaRecorder::errorOccurred(QMediaRecorder::Error error, const QString &errorString) - return d_func()->videoControl ? - d_func()->videoControl->supportedFrameRates(settings, continuous) : QList<qreal>(); -} + Signals that an \a error has occurred, with \a errorString containing + a description of the error. +*/ /*! - Returns a list of supported video codecs. + \qmlproperty mediaMetaData QtMultimedia::MediaRecorder::metaData + + \brief This property holds meta data associated with the recording. + + When a recording is started, any meta-data assigned will be attached to that + recording. + + \note Ensure that meta-data is assigned correctly by assigning it before + starting the recording. + + \sa mediaMetaData */ -QStringList QMediaRecorder::supportedVideoCodecs() const -{ - return d_func()->videoControl ? - d_func()->videoControl->supportedVideoCodecs() : QStringList(); -} /*! - Returns a description of a video \a codec. + \property QMediaRecorder::metaData - \sa setEncodingSettings() + Returns the metaData associated with the recording. */ -QString QMediaRecorder::videoCodecDescription(const QString &codec) const +QMediaMetaData QMediaRecorder::metaData() const { - return d_func()->videoControl ? - d_func()->videoControl->videoCodecDescription(codec) : QString(); + Q_D(const QMediaRecorder); + + return d->control ? d->control->metaData() : QMediaMetaData{}; } /*! - Returns the audio encoder settings being used. + Sets the meta data to \a metaData. - \sa setEncodingSettings() + \note To ensure that meta-data is set correctly, it should be set before starting the recording. + Once the recording is started, any meta-data set will be attached to the next recording. */ - -QAudioEncoderSettings QMediaRecorder::audioSettings() const +void QMediaRecorder::setMetaData(const QMediaMetaData &metaData) { - return d_func()->audioControl ? - d_func()->audioControl->audioSettings() : QAudioEncoderSettings(); + Q_D(QMediaRecorder); + + if (d->control && d->captureSession) + d->control->setMetaData(metaData); } /*! - Returns the video encoder settings being used. - - \sa setEncodingSettings() + Adds \a metaData to the recorded media. */ - -QVideoEncoderSettings QMediaRecorder::videoSettings() const +void QMediaRecorder::addMetaData(const QMediaMetaData &metaData) { - return d_func()->videoControl ? - d_func()->videoControl->videoSettings() : QVideoEncoderSettings(); + auto data = this->metaData(); + // merge data + for (auto &&[key, value] : metaData.asKeyValueRange()) + data.insert(key, value); + setMetaData(data); } /*! - Sets the audio encoder \a settings. + \property QMediaRecorder::autoStop - If some parameters are not specified, or null settings are passed, the - encoder will choose default encoding parameters, depending on media - source properties. + This property controls whether the media recorder stops automatically when + all media inputs have reported the end of the stream or have been deactivated. - It's only possible to change settings when the encoder is in the - QMediaEncoder::StoppedState state. + The end of the stream is reported by sending an empty media frame, + which you can send explicitly via \l QVideoFrameInput or \l QAudioBufferInput. - \sa audioSettings(), videoSettings(), containerFormat() + Video inputs, specificly, \l QCamera, \l QScreenCapture and \l QWindowCapture, + can be deactivated via the function \c setActive. + + Defaults to \c false. + + \sa QCamera, QScreenCapture, QWindowCapture */ -void QMediaRecorder::setAudioSettings(const QAudioEncoderSettings &settings) +bool QMediaRecorder::autoStop() const +{ + Q_D(const QMediaRecorder); + + return d->autoStop; +} + +void QMediaRecorder::setAutoStop(bool autoStop) { Q_D(QMediaRecorder); - //restart camera if it can't apply new settings in the Active state - d->restartCamera(); + if (d->autoStop == autoStop) + return; - if (d->audioControl) { - d->audioControl->setAudioSettings(settings); - d->applySettingsLater(); - } + d->autoStop = autoStop; + d->control->updateAutoStop(); + emit autoStopChanged(); } /*! - Sets the video encoder \a settings. - - If some parameters are not specified, or null settings are passed, the - encoder will choose default encoding parameters, depending on media - source properties. + \qmlsignal QtMultimedia::MediaRecorder::metaDataChanged() - It's only possible to change settings when the encoder is in the - QMediaEncoder::StoppedState state. + \brief Signals that a media object's meta-data has changed. - \sa audioSettings(), videoSettings(), containerFormat() + If multiple meta-data elements are changed metaDataChanged() is emitted + once. */ +/*! + \fn QMediaRecorder::metaDataChanged() -void QMediaRecorder::setVideoSettings(const QVideoEncoderSettings &settings) -{ - Q_D(QMediaRecorder); + Signals that a media object's meta-data has changed. - d->restartCamera(); + If multiple meta-data elements are changed metaDataChanged() is emitted + once. +*/ - if (d->videoControl) { - d->videoControl->setVideoSettings(settings); - d->applySettingsLater(); - } +/*! + Returns the media capture session. +*/ +QMediaCaptureSession *QMediaRecorder::captureSession() const +{ + Q_D(const QMediaRecorder); + return d->captureSession; } - /*! - Sets the media \a container format. + \qmlproperty enumeration QtMultimedia::MediaRecorder::quality - If the container format is not specified, the - encoder will choose format, depending on media source properties - and encoding settings selected. + Enumerates quality encoding levels. - It's only possible to change settings when the encoder is in the - QMediaEncoder::StoppedState state. + \value MediaRecorder.VeryLowQuality + \value MediaRecorder.LowQuality + \value MediaRecorder.NormalQuality + \value MediaRecorder.HighQuality + \value MediaRecorder.VeryHighQuality +*/ +/*! + \enum QMediaRecorder::Quality - \sa audioSettings(), videoSettings(), containerFormat() + Enumerates quality encoding levels. + + \value VeryLowQuality + \value LowQuality + \value NormalQuality + \value HighQuality + \value VeryHighQuality */ -void QMediaRecorder::setContainerFormat(const QString &container) -{ - Q_D(QMediaRecorder); +/*! + \enum QMediaRecorder::EncodingMode - d->restartCamera(); + Enumerates encoding modes. - if (d->formatControl) { - d->formatControl->setContainerFormat(container); - d->applySettingsLater(); - } -} + \value ConstantQualityEncoding Encoding will aim to have a constant quality, adjusting bitrate to fit. + \value ConstantBitRateEncoding Encoding will use a constant bit rate, adjust quality to fit. + \value AverageBitRateEncoding Encoding will try to keep an average bitrate setting, but will use + more or less as needed. + \value TwoPassEncoding The media will first be processed to determine the characteristics, + and then processed a second time allocating more bits to the areas + that need it. +*/ /*! - Sets the \a audio and \a video encoder settings and \a container format. - If some parameters are not specified, or null settings are passed, the - encoder will choose default encoding parameters, depending on media - source properties. + \qmlproperty MediaFormat QtMultimedia::MediaRecorder::mediaFormat - It's only possible to change settings when the encoder is in the - QMediaEncoder::StoppedState state. + \brief This property holds the current MediaFormat of the recorder. +*/ +/*! + \property QMediaRecorder::mediaFormat - \sa audioSettings(), videoSettings(), containerFormat() + Returns the recording media format. */ +QMediaFormat QMediaRecorder::mediaFormat() const +{ + Q_D(const QMediaRecorder); + return d->encoderSettings.mediaFormat(); +} -void QMediaRecorder::setEncodingSettings(const QAudioEncoderSettings &audio, - const QVideoEncoderSettings &video, - const QString &container) +void QMediaRecorder::setMediaFormat(const QMediaFormat &format) { Q_D(QMediaRecorder); + if (d->encoderSettings.mediaFormat() == format) + return; + d->encoderSettings.setMediaFormat(format); + emit mediaFormatChanged(); +} - d->restartCamera(); - - if (d->audioControl) - d->audioControl->setAudioSettings(audio); +/*! - if (d->videoControl) - d->videoControl->setVideoSettings(video); + \qmlproperty enumeration QtMultimedia::MediaRecorder::encodingMode + \since 6.6 + \brief This property holds the encoding mode. + \sa QMediaRecorder::EncodingMode +*/ - if (d->formatControl) - d->formatControl->setContainerFormat(container); +/*! + Returns the encoding mode. - d->applySettingsLater(); + \sa EncodingMode +*/ +QMediaRecorder::EncodingMode QMediaRecorder::encodingMode() const +{ + Q_D(const QMediaRecorder); + return d->encoderSettings.encodingMode(); } /*! - Start recording. - - While the recorder state is changed immediately to QMediaRecorder::RecordingState, - recording may start asynchronously, with statusChanged(QMediaRecorder::RecordingStatus) - signal emitted when recording starts. + \fn void QMediaRecorder::encodingModeChanged() - If recording fails error() signal is emitted - with recorder state being reset back to QMediaRecorder::StoppedState. + Signals when the encoding mode changes. */ +/*! + Sets the encoding \a mode setting. -void QMediaRecorder::record() + If ConstantQualityEncoding is set, the quality + encoding parameter is used and bit rates are ignored, + otherwise the bitrates are used. + + \sa encodingMode(), EncodingMode +*/ +void QMediaRecorder::setEncodingMode(EncodingMode mode) { Q_D(QMediaRecorder); - - d->actualLocation.clear(); - - if (d->settingsChanged) - d->_q_applySettings(); - - // reset error - d->error = NoError; - d->errorString = QString(); - - if (d->control) - d->control->setState(RecordingState); + if (d->encoderSettings.encodingMode() == mode) + return; + d->encoderSettings.setEncodingMode(mode); + emit encodingModeChanged(); } /*! - Pause recording. - - The recorder state is changed to QMediaRecorder::PausedState. + \property QMediaRecorder::quality - Depending on platform recording pause may be not supported, - in this case the recorder state stays unchanged. + Returns the recording quality. */ - -void QMediaRecorder::pause() +QMediaRecorder::Quality QMediaRecorder::quality() const { - Q_D(QMediaRecorder); - if (d->control) - d->control->setState(PausedState); + Q_D(const QMediaRecorder); + return d->encoderSettings.quality(); } /*! - Stop recording. + \fn void QMediaRecorder::qualityChanged() - The recorder state is changed to QMediaRecorder::StoppedState. + Signals when the recording quality changes. */ - -void QMediaRecorder::stop() +void QMediaRecorder::setQuality(Quality quality) { Q_D(QMediaRecorder); - if (d->control) - d->control->setState(StoppedState); + if (d->encoderSettings.quality() == quality) + return; + d->encoderSettings.setQuality(quality); + emit qualityChanged(); } /*! - \enum QMediaRecorder::State + \qmlproperty Size QtMultimedia::MediaRecorder::videoResolution + \since 6.6 + \brief This property holds the resolution of the encoded video. - \value StoppedState The recorder is not active. - If this is the state after recording then the actual created recording has - finished being written to the final location and is ready on all platforms - except on Android. On Android, due to platform limitations, there is no way - to be certain that the recording has finished writing to the final location. - \value RecordingState The recording is requested. - \value PausedState The recorder is paused. + Set an empty Size to make the recorder choose an optimal resolution based + on what is available from the video source and the limitations of the codec. */ -/*! - \enum QMediaRecorder::Status - \value UnavailableStatus - The recorder is not available or not supported by connected media object. - \value UnloadedStatus - The recorder is avilable but not loaded. - \value LoadingStatus - The recorder is initializing. - \value LoadedStatus - The recorder is initialized and ready to record media. - \value StartingStatus - Recording is requested but not active yet. - \value RecordingStatus - Recording is active. - \value PausedStatus - Recording is paused. - \value FinalizingStatus - Recording is stopped with media being finalized. +/*! + Returns the resolution of the encoded video. */ +QSize QMediaRecorder::videoResolution() const +{ + Q_D(const QMediaRecorder); + return d->encoderSettings.videoResolution(); +} /*! - \enum QMediaRecorder::Error + \fn void QMediaRecorder::videoResolutionChanged() - \value NoError No Errors. - \value ResourceError Device is not ready or not available. - \value FormatError Current format is not supported. - \value OutOfSpaceError No space left on device. + Signals when the video recording resolution changes. */ - /*! - \property QMediaRecorder::state - \brief The current state of the media recorder. + Sets the resolution of the encoded video to \a{size}. - The state property represents the user request and is changed synchronously - during record(), pause() or stop() calls. - Recorder state may also change asynchronously when recording fails. + Pass an empty QSize to make the recorder choose an optimal resolution based + on what is available from the video source and the limitations of the codec. */ +void QMediaRecorder::setVideoResolution(const QSize &size) +{ + Q_D(QMediaRecorder); + if (d->encoderSettings.videoResolution() == size) + return; + d->encoderSettings.setVideoResolution(size); + emit videoResolutionChanged(); +} -/*! - \property QMediaRecorder::status - \brief The current status of the media recorder. +/*! \fn void QMediaRecorder::setVideoResolution(int width, int height) - The status is changed asynchronously and represents the actual status - of media recorder. + Sets the \a width and \a height of the resolution of the encoded video. + + \overload */ /*! - \fn QMediaRecorder::stateChanged(State state) + \qmlproperty real QtMultimedia::MediaRecorder::videoFrameRate + \since 6.6 + \brief This property holds the video frame rate. - Signals that a media recorder's \a state has changed. + A value of 0 indicates the recorder should make an optimal choice based on what is available + from the video source and the limitations of the codec. */ /*! - \fn QMediaRecorder::durationChanged(qint64 duration) - - Signals that the \a duration of the recorded media has changed. + Returns the video frame rate. */ +qreal QMediaRecorder::videoFrameRate() const +{ + Q_D(const QMediaRecorder); + return d->encoderSettings.videoFrameRate(); +} /*! - \fn QMediaRecorder::actualLocationChanged(const QUrl &location) + \fn void QMediaRecorder::videoFrameRateChanged() - Signals that the actual \a location of the recorded media has changed. - This signal is usually emitted when recording starts. + Signals when the recording video frame rate changes. */ - /*! - \fn QMediaRecorder::error(QMediaRecorder::Error error) + Sets the video \a frameRate. - Signals that an \a error has occurred. + A value of 0 indicates the recorder should make an optimal choice based on what is available + from the video source and the limitations of the codec. */ +void QMediaRecorder::setVideoFrameRate(qreal frameRate) +{ + Q_D(QMediaRecorder); + if (d->encoderSettings.videoFrameRate() == frameRate) + return; + d->encoderSettings.setVideoFrameRate(frameRate); + emit videoFrameRateChanged(); +} /*! - \fn QMediaRecorder::availabilityChanged(bool available) - - Signals that the media recorder is now available (if \a available is true), or not. + \qmlproperty int QtMultimedia::MediaRecorder::videoBitRate + \since 6.6 + \brief This property holds the bit rate of the compressed video stream in bits per second. */ /*! - \fn QMediaRecorder::availabilityChanged(QMultimedia::AvailabilityStatus availability) - - Signals that the service availability has changed to \a availability. + Returns the bit rate of the compressed video stream in bits per second. */ +int QMediaRecorder::videoBitRate() const +{ + Q_D(const QMediaRecorder); + return d->encoderSettings.videoBitRate(); +} /*! - \fn QMediaRecorder::mutedChanged(bool muted) + \fn void QMediaRecorder::videoBitRateChanged() - Signals that the \a muted state has changed. If true the recording is being muted. + Signals when the recording video bit rate changes. */ - /*! - \property QMediaRecorder::metaDataAvailable - \brief whether access to a media object's meta-data is available. + Sets the video \a bitRate in bits per second. +*/ +void QMediaRecorder::setVideoBitRate(int bitRate) +{ + Q_D(QMediaRecorder); + if (d->encoderSettings.videoBitRate() == bitRate) + return; + d->encoderSettings.setVideoBitRate(bitRate); + emit videoBitRateChanged(); +} - If this is true there is meta-data available, otherwise there is no meta-data available. +/*! + \qmlproperty int QtMultimedia::MediaRecorder::audioBitRate + \since 6.6 + \brief This property holds the bit rate of the compressed audio stream in bits per second. */ -bool QMediaRecorder::isMetaDataAvailable() const +/*! + Returns the bit rate of the compressed audio stream in bits per second. +*/ +int QMediaRecorder::audioBitRate() const { Q_D(const QMediaRecorder); - - return d->metaDataControl - ? d->metaDataControl->isMetaDataAvailable() - : false; + return d->encoderSettings.audioBitRate(); } /*! - \fn QMediaRecorder::metaDataAvailableChanged(bool available) + \fn void QMediaRecorder::audioBitRateChanged() - Signals that the \a available state of a media object's meta-data has changed. + Signals when the recording audio bit rate changes. */ - /*! - \property QMediaRecorder::metaDataWritable - \brief whether a media object's meta-data is writable. - - If this is true the meta-data is writable, otherwise the meta-data is read-only. + Sets the audio \a bitRate in bits per second. */ - -bool QMediaRecorder::isMetaDataWritable() const +void QMediaRecorder::setAudioBitRate(int bitRate) { - Q_D(const QMediaRecorder); - - return d->metaDataControl - ? d->metaDataControl->isWritable() - : false; + Q_D(QMediaRecorder); + if (d->encoderSettings.audioBitRate() == bitRate) + return; + d->encoderSettings.setAudioBitRate(bitRate); + emit audioBitRateChanged(); } /*! - \fn QMediaRecorder::metaDataWritableChanged(bool writable) - - Signals that the \a writable state of a media object's meta-data has changed. + \qmlproperty int QtMultimedia::MediaRecorder::audioChannelCount + \since 6.6 + \brief This property holds the number of audio channels. */ /*! - Returns the value associated with a meta-data \a key. + Returns the number of audio channels. */ -QVariant QMediaRecorder::metaData(const QString &key) const +int QMediaRecorder::audioChannelCount() const { Q_D(const QMediaRecorder); - - return d->metaDataControl - ? d->metaDataControl->metaData(key) - : QVariant(); + return d->encoderSettings.audioChannelCount(); } /*! - Sets a \a value for a meta-data \a key. + \fn void QMediaRecorder::audioChannelCountChanged() - \note To ensure that meta data is set corretly, it should be set before starting the recording. - Once the recording is stopped, any meta data set will be attached to the next recording. + Signals when the recording audio channel count changes. */ -void QMediaRecorder::setMetaData(const QString &key, const QVariant &value) +/*! + Sets the number of audio \a channels. + + A value of -1 indicates the recorder should make an optimal choice based on + what is available from the audio source and the limitations of the codec. +*/ +void QMediaRecorder::setAudioChannelCount(int channels) { Q_D(QMediaRecorder); - - if (d->metaDataControl) - d->metaDataControl->setMetaData(key, value); + if (d->encoderSettings.audioChannelCount() == channels) + return; + d->encoderSettings.setAudioChannelCount(channels); + emit audioChannelCountChanged(); } /*! - Returns a list of keys there is meta-data available for. + \qmlproperty int QtMultimedia::MediaRecorder::audioSampleRate + \since 6.6 + \brief This property holds the audio sample rate in Hz. +*/ + +/*! + Returns the audio sample rate in Hz. */ -QStringList QMediaRecorder::availableMetaData() const +int QMediaRecorder::audioSampleRate() const { Q_D(const QMediaRecorder); - - return d->metaDataControl - ? d->metaDataControl->availableMetaData() - : QStringList(); + return d->encoderSettings.audioSampleRate(); } - /*! - \fn QMediaRecorder::metaDataChanged() + \fn void QMediaRecorder::audioSampleRateChanged() - Signals that a media object's meta-data has changed. - - If multiple meta-data elements are changed, - metaDataChanged(const QString &key, const QVariant &value) signal is emitted - for each of them with metaDataChanged() changed emitted once. + Signals when the recording audio sample rate changes. */ - /*! - \fn QMediaRecorder::metaDataChanged(const QString &key, const QVariant &value) + Sets the audio \a sampleRate in Hz. - Signal the changes of one meta-data element \a value with the given \a key. + A value of \c -1 indicates the recorder should make an optimal choice based + on what is available from the audio source, and the limitations of the codec. */ +void QMediaRecorder::setAudioSampleRate(int sampleRate) +{ + Q_D(QMediaRecorder); + if (d->encoderSettings.audioSampleRate() == sampleRate) + return; + d->encoderSettings.setAudioSampleRate(sampleRate); + emit audioSampleRateChanged(); +} QT_END_NAMESPACE diff --git a/src/multimedia/recording/qmediarecorder.h b/src/multimedia/recording/qmediarecorder.h index 0fdcf80e4..a73d9f8af 100644 --- a/src/multimedia/recording/qmediarecorder.h +++ b/src/multimedia/recording/qmediarecorder.h @@ -1,50 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMEDIARECORDER_H -#define QMEDIARECORDER_H - -#include <QtMultimedia/qmultimedia.h> -#include <QtMultimedia/qmediaobject.h> -#include <QtMultimedia/qmediaencodersettings.h> -#include <QtMultimedia/qmediabindableinterface.h> +// Copyright (C) 2016 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 QMediaRecorder_H +#define QMediaRecorder_H + +#include <QtCore/qobject.h> +#include <QtCore/qsize.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmediaenumdebug.h> +#include <QtMultimedia/qmediametadata.h> #include <QtCore/qpair.h> @@ -53,171 +17,168 @@ QT_BEGIN_NAMESPACE class QUrl; class QSize; class QAudioFormat; -QT_END_NAMESPACE - -QT_BEGIN_NAMESPACE - -class QMediaRecorderService; -class QAudioEncoderSettings; -class QVideoEncoderSettings; +class QCamera; +class QCameraDevice; +class QMediaFormat; +class QAudioDevice; +class QMediaCaptureSession; +class QPlatformMediaRecorder; class QMediaRecorderPrivate; -class Q_MULTIMEDIA_EXPORT QMediaRecorder : public QObject, public QMediaBindableInterface +class Q_MULTIMEDIA_EXPORT QMediaRecorder : public QObject { Q_OBJECT - Q_INTERFACES(QMediaBindableInterface) - Q_ENUMS(State) - Q_ENUMS(Status) - Q_ENUMS(Error) - Q_PROPERTY(QMediaRecorder::State state READ state NOTIFY stateChanged) - Q_PROPERTY(QMediaRecorder::Status status READ status NOTIFY statusChanged) + Q_PROPERTY(QMediaRecorder::RecorderState recorderState READ recorderState NOTIFY recorderStateChanged) Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged) Q_PROPERTY(QUrl outputLocation READ outputLocation WRITE setOutputLocation) Q_PROPERTY(QUrl actualLocation READ actualLocation NOTIFY actualLocationChanged) - Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) - Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged) - Q_PROPERTY(bool metaDataAvailable READ isMetaDataAvailable NOTIFY metaDataAvailableChanged) - Q_PROPERTY(bool metaDataWritable READ isMetaDataWritable NOTIFY metaDataWritableChanged) + Q_PROPERTY(QMediaMetaData metaData READ metaData WRITE setMetaData NOTIFY metaDataChanged) + Q_PROPERTY(QMediaRecorder::Error error READ error NOTIFY errorChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) + Q_PROPERTY(QMediaFormat mediaFormat READ mediaFormat WRITE setMediaFormat NOTIFY mediaFormatChanged) + Q_PROPERTY(Quality quality READ quality WRITE setQuality NOTIFY qualityChanged) + Q_PROPERTY(QMediaRecorder::EncodingMode encodingMode READ encodingMode WRITE setEncodingMode NOTIFY encodingModeChanged) + Q_PROPERTY(QSize videoResolution READ videoResolution WRITE setVideoResolution NOTIFY videoResolutionChanged) + Q_PROPERTY(qreal videoFrameRate READ videoFrameRate WRITE setVideoFrameRate NOTIFY videoFrameRateChanged) + Q_PROPERTY(int videoBitRate READ videoBitRate WRITE setVideoBitRate NOTIFY videoBitRateChanged) + Q_PROPERTY(int audioBitRate READ audioBitRate WRITE setAudioBitRate NOTIFY audioBitRateChanged) + Q_PROPERTY(int audioChannelCount READ audioChannelCount WRITE setAudioChannelCount NOTIFY audioChannelCountChanged) + Q_PROPERTY(int audioSampleRate READ audioSampleRate WRITE setAudioSampleRate NOTIFY audioSampleRateChanged) + Q_PROPERTY(bool autoStop READ autoStop WRITE setAutoStop NOTIFY autoStopChanged) public: + enum Quality + { + VeryLowQuality, + LowQuality, + NormalQuality, + HighQuality, + VeryHighQuality + }; + Q_ENUM(Quality) - enum State + enum EncodingMode + { + ConstantQualityEncoding, + ConstantBitRateEncoding, + AverageBitRateEncoding, + TwoPassEncoding + }; + Q_ENUM(EncodingMode) + + enum RecorderState { StoppedState, RecordingState, PausedState }; - - enum Status { - UnavailableStatus, - UnloadedStatus, - LoadingStatus, - LoadedStatus, - StartingStatus, - RecordingStatus, - PausedStatus, - FinalizingStatus - }; + Q_ENUM(RecorderState) enum Error { NoError, ResourceError, FormatError, - OutOfSpaceError + OutOfSpaceError, + LocationNotWritable }; + Q_ENUM(Error) - explicit QMediaRecorder(QMediaObject *mediaObject, QObject *parent = nullptr); + QMediaRecorder(QObject *parent = nullptr); ~QMediaRecorder(); - QMediaObject *mediaObject() const override; - bool isAvailable() const; - QMultimedia::AvailabilityStatus availability() const; QUrl outputLocation() const; - bool setOutputLocation(const QUrl &location); + void setOutputLocation(const QUrl &location); + + void setOutputDevice(QIODevice *device); + QIODevice *outputDevice() const; QUrl actualLocation() const; - State state() const; - Status status() const; + RecorderState recorderState() const; Error error() const; QString errorString() const; qint64 duration() const; - bool isMuted() const; - qreal volume() const; + QMediaFormat mediaFormat() const; + void setMediaFormat(const QMediaFormat &format); - QStringList supportedContainers() const; - QString containerDescription(const QString &format) const; + EncodingMode encodingMode() const; + void setEncodingMode(EncodingMode); - QStringList supportedAudioCodecs() const; - QString audioCodecDescription(const QString &codecName) const; + Quality quality() const; + void setQuality(Quality quality); - QList<int> supportedAudioSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(), - bool *continuous = nullptr) const; + QSize videoResolution() const; + void setVideoResolution(const QSize &); + void setVideoResolution(int width, int height) { setVideoResolution(QSize(width, height)); } - QStringList supportedVideoCodecs() const; - QString videoCodecDescription(const QString &codecName) const; + qreal videoFrameRate() const; + void setVideoFrameRate(qreal frameRate); - QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(), - bool *continuous = nullptr) const; + int videoBitRate() const; + void setVideoBitRate(int bitRate); - QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(), - bool *continuous = nullptr) const; + int audioBitRate() const; + void setAudioBitRate(int bitRate); - QAudioEncoderSettings audioSettings() const; - QVideoEncoderSettings videoSettings() const; - QString containerFormat() const; + int audioChannelCount() const; + void setAudioChannelCount(int channels); - void setAudioSettings(const QAudioEncoderSettings &audioSettings); - void setVideoSettings(const QVideoEncoderSettings &videoSettings); - void setContainerFormat(const QString &container); + int audioSampleRate() const; + void setAudioSampleRate(int sampleRate); - void setEncodingSettings(const QAudioEncoderSettings &audioSettings, - const QVideoEncoderSettings &videoSettings = QVideoEncoderSettings(), - const QString &containerMimeType = QString()); + QMediaMetaData metaData() const; + void setMetaData(const QMediaMetaData &metaData); + void addMetaData(const QMediaMetaData &metaData); - bool isMetaDataAvailable() const; - bool isMetaDataWritable() const; + bool autoStop() const; + void setAutoStop(bool autoStop); - QVariant metaData(const QString &key) const; - void setMetaData(const QString &key, const QVariant &value); - QStringList availableMetaData() const; + QMediaCaptureSession *captureSession() const; + QPlatformMediaRecorder *platformRecoder() const; public Q_SLOTS: void record(); void pause(); void stop(); - void setMuted(bool muted); - void setVolume(qreal volume); Q_SIGNALS: - void stateChanged(QMediaRecorder::State state); - void statusChanged(QMediaRecorder::Status status); + void recorderStateChanged(RecorderState state); void durationChanged(qint64 duration); - void mutedChanged(bool muted); - void volumeChanged(qreal volume); void actualLocationChanged(const QUrl &location); + void encoderSettingsChanged(); - void error(QMediaRecorder::Error error); + void errorOccurred(Error error, const QString &errorString); + void errorChanged(); - void metaDataAvailableChanged(bool available); - void metaDataWritableChanged(bool writable); void metaDataChanged(); - void metaDataChanged(const QString &key, const QVariant &value); - void availabilityChanged(bool available); - void availabilityChanged(QMultimedia::AvailabilityStatus availability); + void mediaFormatChanged(); + void encodingModeChanged(); + void qualityChanged(); + void videoResolutionChanged(); + void videoFrameRateChanged(); + void videoBitRateChanged(); + void audioBitRateChanged(); + void audioChannelCountChanged(); + void audioSampleRateChanged(); + void autoStopChanged(); -protected: - QMediaRecorder(QMediaRecorderPrivate &dd, QMediaObject *mediaObject, QObject *parent = nullptr); - bool setMediaObject(QMediaObject *object) override; - - QMediaRecorderPrivate *d_ptr; private: + QMediaRecorderPrivate *d_ptr; + friend class QMediaCaptureSession; + void setCaptureSession(QMediaCaptureSession *session); Q_DISABLE_COPY(QMediaRecorder) Q_DECLARE_PRIVATE(QMediaRecorder) - Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QMediaRecorder::State)) - Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &)) - Q_PRIVATE_SLOT(d_func(), void _q_serviceDestroyed()) - Q_PRIVATE_SLOT(d_func(), void _q_notify()) - Q_PRIVATE_SLOT(d_func(), void _q_updateActualLocation(const QUrl &)) - Q_PRIVATE_SLOT(d_func(), void _q_updateNotifyInterval(int)) - Q_PRIVATE_SLOT(d_func(), void _q_applySettings()) - Q_PRIVATE_SLOT(d_func(), void _q_availabilityChanged(QMultimedia::AvailabilityStatus)) }; QT_END_NAMESPACE -Q_DECLARE_METATYPE(QMediaRecorder::State) -Q_DECLARE_METATYPE(QMediaRecorder::Status) -Q_DECLARE_METATYPE(QMediaRecorder::Error) - -Q_MEDIA_ENUM_DEBUG(QMediaRecorder, State) -Q_MEDIA_ENUM_DEBUG(QMediaRecorder, Status) +Q_MEDIA_ENUM_DEBUG(QMediaRecorder, RecorderState) Q_MEDIA_ENUM_DEBUG(QMediaRecorder, Error) -#endif // QMEDIARECORDER_H +#endif // QMediaRecorder_H diff --git a/src/multimedia/recording/qmediarecorder_p.h b/src/multimedia/recording/qmediarecorder_p.h index f634d016e..896f6c368 100644 --- a/src/multimedia/recording/qmediarecorder_p.h +++ b/src/multimedia/recording/qmediarecorder_p.h @@ -1,44 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMEDIARECORDER_P_H -#define QMEDIARECORDER_P_H +// Copyright (C) 2016 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 QMediaRecorder_P_H +#define QMediaRecorder_P_H // // W A R N I N G @@ -52,60 +16,39 @@ // #include "qmediarecorder.h" -#include "qmediaobject_p.h" +#include "qcamera.h" #include <QtCore/qurl.h> +#include <QtCore/qpointer.h> +#include "private/qplatformmediarecorder_p.h" QT_BEGIN_NAMESPACE -class QMediaRecorderControl; -class QMediaContainerControl; -class QAudioEncoderSettingsControl; -class QVideoEncoderSettingsControl; -class QMetaDataWriterControl; -class QMediaAvailabilityControl; +class QPlatformMediaRecorder; class QTimer; -class QMediaRecorderPrivate +class Q_MULTIMEDIA_EXPORT QMediaRecorderPrivate { - Q_DECLARE_NON_CONST_PUBLIC(QMediaRecorder) + Q_DECLARE_PUBLIC(QMediaRecorder) public: QMediaRecorderPrivate(); - virtual ~QMediaRecorderPrivate() {} - - void applySettingsLater(); - void restartCamera(); - - QMediaObject *mediaObject; - QMediaRecorderControl *control; - QMediaContainerControl *formatControl; - QAudioEncoderSettingsControl *audioControl; - QVideoEncoderSettingsControl *videoControl; - QMetaDataWriterControl *metaDataControl; - QMediaAvailabilityControl *availabilityControl; + static QString msgFailedStartRecording(); - bool settingsChanged; + QMediaCaptureSession *captureSession = nullptr; + QPlatformMediaRecorder *control = nullptr; + QString initErrorMessage; + bool autoStop = false; - QTimer* notifyTimer; + bool settingsChanged = false; - QMediaRecorder::State state; - QMediaRecorder::Error error; - QString errorString; - QUrl actualLocation; + QMediaEncoderSettings encoderSettings; - void _q_stateChanged(QMediaRecorder::State state); - void _q_error(int error, const QString &errorString); - void _q_serviceDestroyed(); - void _q_updateActualLocation(const QUrl &); - void _q_notify(); - void _q_updateNotifyInterval(int ms); - void _q_applySettings(); - void _q_availabilityChanged(QMultimedia::AvailabilityStatus availability); - - QMediaRecorder *q_ptr; + QMediaRecorder *q_ptr = nullptr; }; +#undef Q_DECLARE_NON_CONST_PUBLIC + QT_END_NAMESPACE #endif diff --git a/src/multimedia/recording/qscreencapture-limitations.qdocinc b/src/multimedia/recording/qscreencapture-limitations.qdocinc new file mode 100644 index 000000000..240a1a389 --- /dev/null +++ b/src/multimedia/recording/qscreencapture-limitations.qdocinc @@ -0,0 +1,25 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + //! [content] + \section1 Screen Capture Limitations + On Qt 6.5.2 and above, the following limitations apply to using \1ScreenCapture: + \list + \li It is only supported with the FFmpeg backend. + \li It is unsupported on Linux with Wayland compositor, due to Wayland + protocol restrictions and limitations. + \li It is not supported on mobile operating systems, except on Android. + There, you might run into performance issues as the class is currently + implemented via QScreen::grabWindow, which is not optimal for the use case. + \li On embedded with EGLFS, it has limited functionality. For Qt Quick + applications, the class is currently implemented via + QQuickWindow::grabWindow, which can cause performance issues. + \li In most cases, we set a screen capture frame rate that equals the screen + refresh rate, except on Windows, where the rate might be flexible. + Such a frame rate (75/120 FPS) might cause performance issues on weak + CPUs if the captured screen is of 4K resolution. On EGLFS, the capture + frame rate is currently locked to 30 FPS. + \endlist + //! [content] +*/ diff --git a/src/multimedia/recording/qscreencapture.cpp b/src/multimedia/recording/qscreencapture.cpp new file mode 100644 index 000000000..c178af1c1 --- /dev/null +++ b/src/multimedia/recording/qscreencapture.cpp @@ -0,0 +1,261 @@ +// Copyright (C) 2022 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 "qscreencapture.h" +#include "qmediacapturesession.h" +#include <private/qplatformmediaintegration_p.h> +#include <private/qplatformsurfacecapture_p.h> +#include <private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +static QScreenCapture::Error toScreenCaptureError(QPlatformSurfaceCapture::Error error) +{ + return static_cast<QScreenCapture::Error>(error); +} + +class QScreenCapturePrivate : public QObjectPrivate +{ +public: + QMediaCaptureSession *captureSession = nullptr; + std::unique_ptr<QPlatformSurfaceCapture> platformScreenCapture; +}; + +/*! + \class QScreenCapture + \inmodule QtMultimedia + \ingroup multimedia + \ingroup multimedia_video + \since 6.5 + + \brief This class is used for capturing a screen. + + 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 + + \include qscreencapture-limitations.qdocinc {content} {Q} + + \sa QWindowCapture, QMediaCaptureSession +*/ +/*! + \qmltype ScreenCapture + \instantiates QScreenCapture + \brief This type is used for capturing a screen. + + \inqmlmodule QtMultimedia + \ingroup multimedia_qml + \ingroup multimedia_video_qml + + 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 + back the captured primary screen view in VideoOutput. + +\qml + CaptureSession { + id: captureSession + screenCapture: ScreenCapture { + id: screenCapture + active: true + } + videoOutput: VideoOutput { + id: videoOutput + } + } +\endqml + + \include qscreencapture-limitations.qdocinc {content} {} + + \sa WindowCapture, CaptureSession +*/ + +QScreenCapture::QScreenCapture(QObject *parent) + : QObject(*new QScreenCapturePrivate, parent) +{ + Q_D(QScreenCapture); + + auto platformCapture = QPlatformMediaIntegration::instance()->createScreenCapture(this); + if (platformCapture) { + connect(platformCapture, &QPlatformSurfaceCapture::activeChanged, this, + &QScreenCapture::activeChanged); + connect(platformCapture, &QPlatformSurfaceCapture::errorChanged, this, + &QScreenCapture::errorChanged); + connect(platformCapture, &QPlatformSurfaceCapture::errorOccurred, this, + [this](QPlatformSurfaceCapture::Error error, QString errorString) { + emit errorOccurred(toScreenCaptureError(error), errorString); + }); + + connect(platformCapture, + qOverload<QPlatformSurfaceCapture::ScreenSource>( + &QPlatformSurfaceCapture::sourceChanged), + this, &QScreenCapture::screenChanged); + + d->platformScreenCapture.reset(platformCapture); + } +} + +QScreenCapture::~QScreenCapture() +{ + Q_D(QScreenCapture); + + // Reset platformScreenCapture in the destructor to avoid having broken ref in the object. + d->platformScreenCapture.reset(); + + if (d->captureSession) + d->captureSession->setScreenCapture(nullptr); +} + +/*! + \enum QScreenCapture::Error + + Enumerates error codes that can be signaled by the QScreenCapture class. + errorString() provides detailed information about the error cause. + + \value NoError No error + \value InternalError Internal screen capturing driver error + \value CapturingNotSupported Capturing is not supported + \value CaptureFailed Capturing screen failed + \value NotFound Selected screen not found +*/ + +/*! + Returns the capture session this QScreenCapture is connected to. + + Use QMediaCaptureSession::setScreenCapture() to connect the camera to + a session. +*/ +QMediaCaptureSession *QScreenCapture::captureSession() const +{ + Q_D(const QScreenCapture); + + return d->captureSession; +} + +/*! + \qmlproperty bool QtMultimedia::ScreenCapture::active + Describes whether the capturing is currently active. +*/ + +/*! + \property QScreenCapture::active + \brief whether the capturing is currently active. +*/ +void QScreenCapture::setActive(bool active) +{ + Q_D(QScreenCapture); + + if (d->platformScreenCapture) + d->platformScreenCapture->setActive(active); +} + +bool QScreenCapture::isActive() const +{ + Q_D(const QScreenCapture); + + return d->platformScreenCapture && d->platformScreenCapture->isActive(); +} + +/*! + \qmlproperty Screen QtMultimedia::ScreenCapture::screen + Describes the screen for capturing. +*/ + +/*! + \property QScreenCapture::screen + \brief the screen for capturing. +*/ + +void QScreenCapture::setScreen(QScreen *screen) +{ + Q_D(QScreenCapture); + + if (d->platformScreenCapture) + d->platformScreenCapture->setSource(QPlatformSurfaceCapture::ScreenSource(screen)); +} + +QScreen *QScreenCapture::screen() const +{ + Q_D(const QScreenCapture); + + return d->platformScreenCapture + ? d->platformScreenCapture->source<QPlatformSurfaceCapture::ScreenSource>() + : nullptr; +} + +/*! + \qmlproperty enumeration QtMultimedia::ScreenCapture::error + Returns a code of the last error. +*/ + +/*! + \property QScreenCapture::error + \brief the code of the last error. +*/ +QScreenCapture::Error QScreenCapture::error() const +{ + Q_D(const QScreenCapture); + + return d->platformScreenCapture ? toScreenCaptureError(d->platformScreenCapture->error()) + : CapturingNotSupported; +} + +/*! + \fn void QScreenCapture::errorOccurred(QScreenCapture::Error error, const QString &errorString) + + Signals when an \a error occurs, along with the \a errorString. +*/ +/*! + \qmlproperty string QtMultimedia::ScreenCapture::errorString + Returns a human readable string describing the cause of error. +*/ + +/*! + \property QScreenCapture::errorString + \brief a human readable string describing the cause of error. +*/ +QString QScreenCapture::errorString() const +{ + Q_D(const QScreenCapture); + + return d->platformScreenCapture ? d->platformScreenCapture->errorString() + : QLatin1StringView("Capturing is not support on this platform"); +} +/*! + \fn void QScreenCapture::start() + + Starts screen capture. +*/ +/*! + \fn void QScreenCapture::stop() + + Stops screen capture. +*/ +/*! + \internal +*/ +void QScreenCapture::setCaptureSession(QMediaCaptureSession *captureSession) +{ + Q_D(QScreenCapture); + + d->captureSession = captureSession; +} + +/*! + \internal +*/ +class QPlatformSurfaceCapture *QScreenCapture::platformScreenCapture() const +{ + Q_D(const QScreenCapture); + + return d->platformScreenCapture.get(); +} + +QT_END_NAMESPACE + +#include "moc_qscreencapture.cpp" diff --git a/src/multimedia/recording/qscreencapture.h b/src/multimedia/recording/qscreencapture.h new file mode 100644 index 000000000..b46925bc0 --- /dev/null +++ b/src/multimedia/recording/qscreencapture.h @@ -0,0 +1,72 @@ +// Copyright (C) 2022 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 QSCREENCAPTURE_H +#define QSCREENCAPTURE_H + +#include <QtCore/qobject.h> +#include <QtCore/qnamespace.h> +#include <QtGui/qscreen.h> +#include <QtGui/qwindow.h> +#include <QtGui/qwindowdefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> + +QT_BEGIN_NAMESPACE + +class QMediaCaptureSession; +class QPlatformSurfaceCapture; +class QScreenCapturePrivate; + +class Q_MULTIMEDIA_EXPORT QScreenCapture : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) + 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) + +public: + enum Error { + NoError = 0, + InternalError = 1, + CapturingNotSupported = 2, + CaptureFailed = 4, + NotFound = 5, + }; + Q_ENUM(Error) + + explicit QScreenCapture(QObject *parent = nullptr); + ~QScreenCapture() override; + + QMediaCaptureSession *captureSession() const; + + void setScreen(QScreen *screen); + QScreen *screen() 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 errorChanged(); + void screenChanged(QScreen *); + void errorOccurred(QScreenCapture::Error error, const QString &errorString); + +private: + void setCaptureSession(QMediaCaptureSession *captureSession); + QPlatformSurfaceCapture *platformScreenCapture() const; + friend class QMediaCaptureSession; + Q_DISABLE_COPY(QScreenCapture) + Q_DECLARE_PRIVATE(QScreenCapture) +}; + +QT_END_NAMESPACE + +#endif // QSCREENCAPTURE_H diff --git a/src/multimedia/recording/qvideoframeinput.cpp b/src/multimedia/recording/qvideoframeinput.cpp new file mode 100644 index 000000000..99500bb65 --- /dev/null +++ b/src/multimedia/recording/qvideoframeinput.cpp @@ -0,0 +1,181 @@ +// Copyright (C) 2024 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 "qvideoframeinput.h" +#include "qmediaframeinput_p.h" +#include "qmediainputencoderinterface_p.h" +#include "qplatformvideoframeinput_p.h" + +QT_BEGIN_NAMESPACE + +class QVideoFrameInputPrivate : public QMediaFrameInputPrivate +{ +public: + QVideoFrameInputPrivate(QVideoFrameInput *q) : q(q) { } + + bool sendVideoFrame(const QVideoFrame &frame) + { + return sendMediaFrame([&]() { emit m_platfromVideoFrameInput->newVideoFrame(frame); }); + } + + void initialize(QVideoFrameFormat format = {}) + { + m_platfromVideoFrameInput = std::make_unique<QPlatformVideoFrameInput>(std::move(format)); + addUpdateSignal(m_platfromVideoFrameInput.get(), &QPlatformVideoFrameInput::encoderUpdated); + } + + void uninitialize() + { + m_platfromVideoFrameInput.reset(); + + if (captureSession()) + captureSession()->setVideoFrameInput(nullptr); + } + + QPlatformVideoFrameInput *platfromVideoFrameInput() const + { + return m_platfromVideoFrameInput.get(); + } + +protected: + void updateCaptureSessionConnections(QMediaCaptureSession *prevSession, + QMediaCaptureSession *newSession) override + { + if (prevSession) + removeUpdateSignal(prevSession, &QMediaCaptureSession::videoOutputChanged); + + if (newSession) + addUpdateSignal(newSession, &QMediaCaptureSession::videoOutputChanged); + } + + bool checkIfCanSendMediaFrame() const override + { + if (auto encoderInterface = m_platfromVideoFrameInput->encoderInterface()) + return encoderInterface->canPushFrame(); + + return captureSession()->videoOutput() || captureSession()->videoSink(); + } + + void emitReadyToSendMediaFrame() override { emit q->readyToSendVideoFrame(); } + +private: + QVideoFrameInput *q = nullptr; + std::unique_ptr<QPlatformVideoFrameInput> m_platfromVideoFrameInput; +}; + +/*! + \class QVideoFrameInput + \inmodule QtMultimedia + \ingroup multimedia + \ingroup multimedia_video + \since 6.8 + + \brief The QVideoFrameInput class is used for providing custom video frames + to \l QMediaRecorder or a video output through \l QMediaCaptureSession. + + \sa QMediaRecorder, QMediaCaptureSession, QVideoSink +*/ + +/*! + Constructs a new QVideoFrameInput object with \a parent. +*/ +QVideoFrameInput::QVideoFrameInput(QObject *parent) : QVideoFrameInput({}, parent) { } + +/*! + Constructs a new QVideoFrameInput object with video frame \a format and \a parent. + + The specified \a format will work as a hint for the initialization of the matching + video encoder upon invoking \l QMediaRecorder::record(). + If the format is not specified or not valid, the video encoder will be initialized + upon sending the first frame. + Sending of video frames with another pixel format and size after initialization + of the matching video encoder might cause a performance penalty during recording. + + We recommend specifying the format if you know in advance what kind of frames you're + going to send. +*/ +QVideoFrameInput::QVideoFrameInput(const QVideoFrameFormat &format, QObject *parent) + : QObject(*new QVideoFrameInputPrivate(this), parent) +{ + Q_D(QVideoFrameInput); + d->initialize(format); +} + +/*! + Destroys the object. + */ +QVideoFrameInput::~QVideoFrameInput() +{ + Q_D(QVideoFrameInput); + d->uninitialize(); +} + +/*! + Sends \l QVideoFrame to \l QMediaRecorder or a video output + through \l QMediaCaptureSession. + + Returns \c true if the specified \a frame has been sent successfully + to the destination. Returns \c false, if the frame hasn't been sent, + which can happen if the instance is not assigned to + \l QMediaCaptureSession, the session doesn't have video outputs or + a media recorder, the media recorder is not started or its queue is full. + The signal \l readyToSendVideoFrame will be sent as soon as + the destination is able to handle a new frame. + + Sending of an empty video frame is treated by \l QMediaRecorder + as an end of the input stream. QMediaRecorder stops the recording + automatically if \l QMediaRecorder::autoStop is \c true and + all the inputs have reported the end of the stream. +*/ +bool QVideoFrameInput::sendVideoFrame(const QVideoFrame &frame) +{ + Q_D(QVideoFrameInput); + return d->sendVideoFrame(frame); +} + +/*! + Returns the video frame format that was specified + upon construction of the video frame input. +*/ +QVideoFrameFormat QVideoFrameInput::format() const +{ + Q_D(const QVideoFrameInput); + return d->platfromVideoFrameInput()->frameFormat(); +} + +/*! + Returns the capture session this video frame input is connected to, or + a \c nullptr if the video frame input is not connected to a capture session. + + Use QMediaCaptureSession::setVideoFrameInput() to connect + the video frame input to a session. +*/ +QMediaCaptureSession *QVideoFrameInput::captureSession() const +{ + Q_D(const QVideoFrameInput); + return d->captureSession(); +} + +void QVideoFrameInput::setCaptureSession(QMediaCaptureSession *captureSession) +{ + Q_D(QVideoFrameInput); + d->setCaptureSession(captureSession); +} + +QPlatformVideoFrameInput *QVideoFrameInput::platformVideoFrameInput() const +{ + Q_D(const QVideoFrameInput); + return d->platfromVideoFrameInput(); +} + +/*! + \fn void QVideoFrameInput::readyToSendVideoFrame() + + Signals that a new frame can be sent to the video frame input. + After receiving the signal, if you have frames to be sent, invoke \l sendVideoFrame + once or in a loop until it returns \c false. + + \sa sendVideoFrame() +*/ + +QT_END_NAMESPACE diff --git a/src/multimedia/recording/qvideoframeinput.h b/src/multimedia/recording/qvideoframeinput.h new file mode 100644 index 000000000..fbe56b7db --- /dev/null +++ b/src/multimedia/recording/qvideoframeinput.h @@ -0,0 +1,48 @@ +// Copyright (C) 2024 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 QVIDEOFRAMEINPUT_H +#define QVIDEOFRAMEINPUT_H + +#include <QtMultimedia/qtmultimediaexports.h> +#include <QtMultimedia/qvideoframe.h> +#include <QtCore/qobject.h> + +QT_BEGIN_NAMESPACE + +class QPlatformVideoFrameInput; +class QVideoFrameInputPrivate; +class QMediaCaptureSession; + +class Q_MULTIMEDIA_EXPORT QVideoFrameInput : public QObject +{ + Q_OBJECT +public: + explicit QVideoFrameInput(QObject *parent = nullptr); + + explicit QVideoFrameInput(const QVideoFrameFormat &format, QObject *parent = nullptr); + + ~QVideoFrameInput() override; + + bool sendVideoFrame(const QVideoFrame &frame); + + QVideoFrameFormat format() const; + + QMediaCaptureSession *captureSession() const; + +Q_SIGNALS: + void readyToSendVideoFrame(); + +private: + void setCaptureSession(QMediaCaptureSession *captureSession); + + QPlatformVideoFrameInput *platformVideoFrameInput() const; + + friend class QMediaCaptureSession; + Q_DISABLE_COPY(QVideoFrameInput) + Q_DECLARE_PRIVATE(QVideoFrameInput) +}; + +QT_END_NAMESPACE + +#endif // QVIDEOFRAMEINPUT_H diff --git a/src/multimedia/recording/qwindowcapture.cpp b/src/multimedia/recording/qwindowcapture.cpp new file mode 100644 index 000000000..69ad60100 --- /dev/null +++ b/src/multimedia/recording/qwindowcapture.cpp @@ -0,0 +1,268 @@ +// 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" +#include "qmediacapturesession.h" +#include "private/qobject_p.h" +#include "private/qplatformsurfacecapture_p.h" + +QT_BEGIN_NAMESPACE + +static QWindowCapture::Error toWindowCaptureError(QPlatformSurfaceCapture::Error error) +{ + return static_cast<QWindowCapture::Error>(error); +} + +class QWindowCapturePrivate : public QObjectPrivate +{ +public: + QMediaCaptureSession *captureSession = nullptr; + std::unique_ptr<QPlatformSurfaceCapture> platformWindowCapture; +}; + +/*! + \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(*new QWindowCapturePrivate, parent) +{ + Q_D(QWindowCapture); + + qRegisterMetaType<QCapturableWindow>(); + + auto platformCapture = QPlatformMediaIntegration::instance()->createWindowCapture(this); + + if (platformCapture) { + connect(platformCapture, &QPlatformSurfaceCapture::activeChanged, this, + &QWindowCapture::activeChanged); + connect(platformCapture, &QPlatformSurfaceCapture::errorChanged, this, + &QWindowCapture::errorChanged); + connect(platformCapture, &QPlatformSurfaceCapture::errorOccurred, this, + [this](QPlatformSurfaceCapture::Error error, QString errorString) { + emit errorOccurred(toWindowCaptureError(error), errorString); + }); + connect(platformCapture, + qOverload<QCapturableWindow>(&QPlatformSurfaceCapture::sourceChanged), this, + &QWindowCapture::windowChanged); + + d->platformWindowCapture.reset(platformCapture); + } +} + +/*! + Destroys the object. + */ +QWindowCapture::~QWindowCapture() +{ + Q_D(QWindowCapture); + + d->platformWindowCapture.reset(); + + if (d->captureSession) + d->captureSession->setWindowCapture(nullptr); +} + +/*! + \qmlmethod list<CapturableWindow> QtMultimedia::WindowCapture::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()->capturableWindowsList(); +} + +QMediaCaptureSession *QWindowCapture::captureSession() const +{ + Q_D(const QWindowCapture); + + return d->captureSession; +} + +/*! + \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 +{ + Q_D(const QWindowCapture); + + return d->platformWindowCapture ? d->platformWindowCapture->source<QCapturableWindow>() + : QCapturableWindow(); +} + +void QWindowCapture::setWindow(QCapturableWindow window) +{ + Q_D(QWindowCapture); + + if (d->platformWindowCapture) + d->platformWindowCapture->setSource(window); +} + +/*! + \qmlproperty bool QtMultimedia::WindowCapture::active + Describes whether the capturing is currently active. +*/ + +/*! + \property QWindowCapture::active + \brief whether the capturing is currently active. + + \sa start(), stop() +*/ +bool QWindowCapture::isActive() const +{ + Q_D(const QWindowCapture); + + return d->platformWindowCapture && d->platformWindowCapture->isActive(); +} + +void QWindowCapture::setActive(bool active) +{ + Q_D(QWindowCapture); + + if (d->platformWindowCapture) + d->platformWindowCapture->setActive(active); +} + +/*! + \qmlmethod QtMultimedia::WindowCapture::start +*/ + +/*! + \fn void QWindowCapture::start() + + Starts capturing the \l window. + + This is equivalent to setting the \l active property to true. +*/ + +/*! + \qmlmethod QtMultimedia::WindowCapture::stop +*/ + +/*! + \fn void QWindowCapture::stop() + + Stops capturing. + + This is equivalent to setting the \l active property to false. +*/ + + +/*! + \qmlproperty enumeration 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 +{ + Q_D(const QWindowCapture); + + return d->platformWindowCapture ? toWindowCaptureError(d->platformWindowCapture->error()) + : CapturingNotSupported; +} + +/*! + \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 +{ + Q_D(const QWindowCapture); + + return d->platformWindowCapture + ? d->platformWindowCapture->errorString() + : QLatin1StringView("Capturing is not support on this platform"); +} + +void QWindowCapture::setCaptureSession(QMediaCaptureSession *captureSession) +{ + Q_D(QWindowCapture); + + d->captureSession = captureSession; +} + +QPlatformSurfaceCapture *QWindowCapture::platformWindowCapture() const +{ + Q_D(const QWindowCapture); + + return d->platformWindowCapture.get(); +} + +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..4c8b2eac3 --- /dev/null +++ b/src/multimedia/recording/qwindowcapture.h @@ -0,0 +1,71 @@ +// 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 QWINDOWCAPTURE_H +#define QWINDOWCAPTURE_H + +#include <QtMultimedia/qtmultimediaexports.h> +#include <QtMultimedia/qcapturablewindow.h> +#include <QtCore/qobject.h> +#include <QtCore/qlist.h> + +QT_BEGIN_NAMESPACE + +class QPlatformSurfaceCapture; + +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 = 0, + InternalError = 1, + CapturingNotSupported = 2, + CaptureFailed = 4, + NotFound = 5, + }; + 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); + QPlatformSurfaceCapture *platformWindowCapture() const; + + friend class QMediaCaptureSession; + Q_DISABLE_COPY(QWindowCapture) + Q_DECLARE_PRIVATE(QWindowCapture) +}; + +QT_END_NAMESPACE + +#endif // QWINDOWCAPTURE_H diff --git a/src/multimedia/recording/recording.pri b/src/multimedia/recording/recording.pri deleted file mode 100644 index 20ed99e04..000000000 --- a/src/multimedia/recording/recording.pri +++ /dev/null @@ -1,14 +0,0 @@ -INCLUDEPATH += recording - -PUBLIC_HEADERS += \ - recording/qaudiorecorder.h \ - recording/qmediaencodersettings.h \ - recording/qmediarecorder.h \ - -PRIVATE_HEADERS += \ - recording/qmediarecorder_p.h \ - -SOURCES += \ - recording/qaudiorecorder.cpp \ - recording/qmediaencodersettings.cpp \ - recording/qmediarecorder.cpp |