diff options
Diffstat (limited to 'src/multimedia/recording/qmediacapturesession.cpp')
-rw-r--r-- | src/multimedia/recording/qmediacapturesession.cpp | 359 |
1 files changed, 251 insertions, 108 deletions
diff --git a/src/multimedia/recording/qmediacapturesession.cpp b/src/multimedia/recording/qmediacapturesession.cpp index 10324313e..f175cd98e 100644 --- a/src/multimedia/recording/qmediacapturesession.cpp +++ b/src/multimedia/recording/qmediacapturesession.cpp @@ -1,50 +1,15 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// 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 <qpointer.h> +#include "qscreencapture.h" +#include "qwindowcapture.h" #include "qplatformmediaintegration_p.h" #include "qplatformmediacapture_p.h" @@ -53,33 +18,19 @@ QT_BEGIN_NAMESPACE -class QMediaCaptureSessionPrivate +void QMediaCaptureSessionPrivate::setVideoSink(QVideoSink *sink) { -public: - QMediaCaptureSession *q = nullptr; - QPlatformMediaCaptureSession *captureSession; - QAudioInput *audioInput = nullptr; - QAudioOutput *audioOutput = nullptr; - QCamera *camera = nullptr; - QImageCapture *imageCapture = nullptr; - QMediaRecorder *recorder = nullptr; - QVideoSink *videoSink = nullptr; - QPointer<QObject> videoOutput; - - void setVideoSink(QVideoSink *sink) - { - if (sink == videoSink) - return; - if (videoSink) - videoSink->setSource(nullptr); - videoSink = sink; - if (sink) - sink->setSource(q); + if (sink == videoSink) + return; + if (videoSink) + videoSink->setSource(nullptr); + videoSink = sink; + if (sink) + sink->setSource(q); + if (captureSession) captureSession->setVideoPreview(sink); - emit q->videoOutputChanged(); - } - -}; + emit q->videoOutputChanged(); +} /*! \class QMediaCaptureSession @@ -87,17 +38,21 @@ public: \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 camera and a microphone to QMediaCaptureSession using setCamera() and setAudioInput(). - A preview of the captured media can be seen by setting a QVideoSink of QVideoWidget using setVideoOutput() - and heard by routing the audio to an output device using setAudioOutput(). + You can connect a video input to QMediaCaptureSession using setCamera(), setScreenCapture() or setWindowCapture(). + A preview of the captured media can be seen by setting a QVideoWidget or QGraphicsVideoItem using setVideoOutput(). + + You can connect a microphone to QMediaCaptureSession using setAudioInput(). + The captured sound can be heard by routing the audio to an output device using setAudioOutput(). You can capture still images from a camera by setting a QImageCapture object on the capture session, and record audio/video using a QMediaRecorder. - \sa QCamera, QAudioDevice, QMediaRecorder, QImageCapture, QMediaRecorder + \sa QCamera, QAudioDevice, QMediaRecorder, QImageCapture, QScreenCapture, QWindowCapture, QMediaRecorder, QGraphicsVideoItem */ /*! @@ -116,6 +71,12 @@ public: 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. @@ -144,7 +105,7 @@ public: } \endqml - \sa Camera, MediaDevice, MediaRecorder, ImageCapture, AudioInput, VideoOutput + \sa Camera, MediaDevices, MediaRecorder, ImageCapture, ScreenCapture, WindowCapture, AudioInput, VideoOutput */ /*! @@ -155,8 +116,13 @@ QMediaCaptureSession::QMediaCaptureSession(QObject *parent) d_ptr(new QMediaCaptureSessionPrivate) { d_ptr->q = this; - d_ptr->captureSession = QPlatformMediaIntegration::instance()->createCaptureSession(); - Q_ASSERT(d_ptr->captureSession); + auto maybeCaptureSession = QPlatformMediaIntegration::instance()->createCaptureSession(); + if (maybeCaptureSession) { + d_ptr->captureSession = maybeCaptureSession.value(); + d_ptr->captureSession->setCaptureSession(this); + } else { + qWarning() << "Failed to initialize QMediaCaptureSession" << maybeCaptureSession.error(); + } } /*! @@ -164,12 +130,13 @@ QMediaCaptureSession::QMediaCaptureSession(QObject *parent) */ QMediaCaptureSession::~QMediaCaptureSession() { - if (d_ptr->camera) - d_ptr->camera->setCaptureSession(nullptr); - if (d_ptr->recorder) - d_ptr->recorder->setCaptureSession(nullptr); - if (d_ptr->imageCapture) - d_ptr->imageCapture->setCaptureSession(nullptr); + setCamera(nullptr); + setRecorder(nullptr); + setImageCapture(nullptr); + setScreenCapture(nullptr); + setWindowCapture(nullptr); + setAudioInput(nullptr); + setAudioOutput(nullptr); d_ptr->setVideoSink(nullptr); delete d_ptr->captureSession; delete d_ptr; @@ -177,11 +144,12 @@ QMediaCaptureSession::~QMediaCaptureSession() /*! \qmlproperty AudioInput QtMultimedia::CaptureSession::audioInput - This property holds the audio input that is being used to capture audio.. - \sa setAudioInput() + 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 @@ -190,16 +158,30 @@ QAudioInput *QMediaCaptureSession::audioInput() const } /*! - Sets the audio input device to \a device. If setting it to an empty + 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 *device) +void QMediaCaptureSession::setAudioInput(QAudioInput *input) { - if (d_ptr->audioInput == device) + QAudioInput *oldInput = d_ptr->audioInput; + if (oldInput == input) return; - d_ptr->audioInput = device; - d_ptr->captureSession->setAudioInput(device ? device->handle() : nullptr); + + // To avoid double emit of audioInputChanged + // from recursive setAudioInput(nullptr) call. + d_ptr->audioInput = nullptr; + + if (d_ptr->captureSession) + d_ptr->captureSession->setAudioInput(nullptr); + if (oldInput) + oldInput->setDisconnectFunction({}); + if (input) { + input->setDisconnectFunction([this](){ setAudioInput(nullptr); }); + if (d_ptr->captureSession) + d_ptr->captureSession->setAudioInput(input->handle()); + } + d_ptr->audioInput = input; emit audioInputChanged(); } @@ -218,7 +200,7 @@ void QMediaCaptureSession::setAudioInput(QAudioInput *device) \brief The camera used to capture video. Record video or take images by adding a camera to the capture session - using this property, + using this property. */ QCamera *QMediaCaptureSession::camera() const { @@ -227,16 +209,123 @@ QCamera *QMediaCaptureSession::camera() const void QMediaCaptureSession::setCamera(QCamera *camera) { - if (d_ptr->camera == camera) + // TODO: come up with an unification of the captures setup + QCamera *oldCamera = d_ptr->camera; + if (oldCamera == camera) return; - if (d_ptr->camera) - d_ptr->camera->setCaptureSession(nullptr); - d_ptr->camera = camera; - if (d_ptr->camera) - d_ptr->camera->setCaptureSession(this); + if (d_ptr->captureSession) + d_ptr->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_ptr->captureSession) + d_ptr->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() +{ + return d_ptr ? d_ptr->screenCapture : nullptr; +} + +void QMediaCaptureSession::setScreenCapture(QScreenCapture *screenCapture) +{ + // TODO: come up with an unification of the captures setup + QScreenCapture *oldScreenCapture = d_ptr->screenCapture; + if (oldScreenCapture == screenCapture) + return; + d_ptr->screenCapture = screenCapture; + if (d_ptr->captureSession) + d_ptr->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_ptr->captureSession) + d_ptr->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() { + return d_ptr ? d_ptr->windowCapture : nullptr; +} + +void QMediaCaptureSession::setWindowCapture(QWindowCapture *windowCapture) +{ + // TODO: come up with an unification of the captures setup + QWindowCapture *oldCapture = d_ptr->windowCapture; + if (oldCapture == windowCapture) + return; + d_ptr->windowCapture = windowCapture; + if (d_ptr->captureSession) + d_ptr->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_ptr->captureSession) + d_ptr->captureSession->setWindowCapture(windowCapture->platformWindowCapture()); + windowCapture->setCaptureSession(this); + } + emit windowCaptureChanged(); +} + /*! \qmlproperty ImageCapture QtMultimedia::CaptureSession::imageCapture @@ -260,14 +349,25 @@ QImageCapture *QMediaCaptureSession::imageCapture() void QMediaCaptureSession::setImageCapture(QImageCapture *imageCapture) { - if (d_ptr->imageCapture == imageCapture) + // TODO: come up with an unification of the captures setup + QImageCapture *oldImageCapture = d_ptr->imageCapture; + if (oldImageCapture == imageCapture) return; - if (d_ptr->imageCapture) - d_ptr->imageCapture->setCaptureSession(nullptr); - d_ptr->imageCapture = imageCapture; - if (d_ptr->imageCapture) - d_ptr->imageCapture->setCaptureSession(this); + if (d_ptr->captureSession) + d_ptr->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_ptr->captureSession) + d_ptr->captureSession->setImageCapture(imageCapture->platformImageCapture()); + imageCapture->setCaptureSession(this); + } emit imageCaptureChanged(); } /*! @@ -294,14 +394,24 @@ QMediaRecorder *QMediaCaptureSession::recorder() void QMediaCaptureSession::setRecorder(QMediaRecorder *recorder) { - if (d_ptr->recorder == recorder) + QMediaRecorder *oldRecorder = d_ptr->recorder; + if (oldRecorder == recorder) return; - if (d_ptr->recorder) - d_ptr->recorder->setCaptureSession(nullptr); - d_ptr->recorder = recorder; - if (d_ptr->recorder) - d_ptr->recorder->setCaptureSession(this); + if (d_ptr->captureSession) + d_ptr->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_ptr->captureSession) + d_ptr->captureSession->setMediaRecorder(recorder->platformRecoder()); + recorder->setCaptureSession(this); + } emit recorderChanged(); } /*! @@ -315,6 +425,11 @@ void QMediaCaptureSession::setRecorder(QMediaRecorder *recorder) The previously set preview is detached. */ +/*! + \property QMediaCaptureSession::videoOutput + + Returns the video output for the session. +*/ QObject *QMediaCaptureSession::videoOutput() const { Q_D(const QMediaCaptureSession); @@ -356,6 +471,10 @@ void QMediaCaptureSession::setVideoSink(QVideoSink *sink) d->videoOutput = nullptr; d->setVideoSink(sink); } + +/*! + Returns the QVideoSink for the session. +*/ QVideoSink *QMediaCaptureSession::videoSink() const { Q_D(const QMediaCaptureSession); @@ -363,19 +482,43 @@ QVideoSink *QMediaCaptureSession::videoSink() const } /*! 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); - if (d->audioOutput == output) + QAudioOutput *oldOutput = d_ptr->audioOutput; + if (oldOutput == output) return; - d->audioOutput = output; - d->captureSession->setAudioOutput(output ? output->handle() : nullptr); + + // We don't want to end up with signal emitted + // twice (from recursive call setAudioInput(nullptr) + // from oldOutput->setDisconnectFunction(): + d_ptr->audioOutput = nullptr; + + if (d_ptr->captureSession) + d_ptr->captureSession->setAudioOutput(nullptr); + if (oldOutput) + oldOutput->setDisconnectFunction({}); + if (output) { + output->setDisconnectFunction([this](){ setAudioOutput(nullptr); }); + if (d_ptr->captureSession) + d_ptr->captureSession->setAudioOutput(output->handle()); + } + d_ptr->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 { |