summaryrefslogtreecommitdiffstats
path: root/src/multimedia/recording/qmediarecorder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia/recording/qmediarecorder.cpp')
-rw-r--r--src/multimedia/recording/qmediarecorder.cpp328
1 files changed, 217 insertions, 111 deletions
diff --git a/src/multimedia/recording/qmediarecorder.cpp b/src/multimedia/recording/qmediarecorder.cpp
index afa189c89..a7f5a31b8 100644
--- a/src/multimedia/recording/qmediarecorder.cpp
+++ b/src/multimedia/recording/qmediarecorder.cpp
@@ -1,49 +1,16 @@
-/****************************************************************************
-**
-** 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) 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 <private/qplatformmediaencoder_p.h>
+#include <private/qplatformmediarecorder_p.h>
#include <qaudiodevice.h>
#include <qcamera.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>
@@ -62,6 +29,8 @@ QT_BEGIN_NAMESPACE
\inmodule QtMultimedia
\ingroup multimedia
\ingroup multimedia_recording
+ \ingroup multimedia_video
+ \ingroup multimedia_audio
\brief The QMediaRecorder class is used for encoding and recording a capture session.
@@ -80,48 +49,44 @@ QT_BEGIN_NAMESPACE
\ingroup multimedia_audio_qml
\ingroup multimedia_video_qml
+ The MediaRecorder element can be used within a CaptureSession to record and encode audio and
+ video captured from a microphone and camera
+
\since 6.2
- The code below shows how this qml is instantiated.
+ The code below shows a simple capture session containing a MediaRecorder using the default
+ camera and default audio input.
+
\qml
CaptureSession {
id: captureSession
camera: Camera {
id: camera
+ active: true
}
- imageCapture: ImageCapture {
- id: imageCapture
- }
-
+ audioInput: AudioInput {}
recorder: MediaRecorder {
id: recorder
}
}
\endqml
- The code below shows how some properties are used.
+ The code below shows how the recording can be started and stopped.
\qml
CameraButton {
text: "Record"
- visible: captureSession.recorder.status !== MediaRecorder.RecordingStatus
- onClicked: captureSession.recorder.record()
+ visible: recorder.recorderState !== MediaRecorder.RecordingState
+ onClicked: recorder.record()
}
CameraButton {
id: stopButton
text: "Stop"
- visible: captureSession.recorder.status === MediaRecorder.RecordingStatus
- onClicked: captureSession.recorder.stop()
- }
-
- CameraButton {
- text: "View"
- onClicked: captureControls.previewSelected()
- //don't show View button during recording
- visible: captureSession.recorder.actualLocation && !stopButton.visible
+ visible: recorder.recorderState === MediaRecorder.RecordingState
+ onClicked: recorder.stop()
}
\endqml
- \sa CaptureSession
+ \sa CaptureSession, Camera, AudioInput, ImageCapture
*/
QMediaRecorderPrivate::QMediaRecorderPrivate()
{
@@ -145,8 +110,22 @@ QMediaRecorder::QMediaRecorder(QObject *parent)
d_ptr(new QMediaRecorderPrivate)
{
Q_D(QMediaRecorder);
+
+ auto &mediaIntegration = *QPlatformMediaIntegration::instance();
+
d->q_ptr = this;
- d->control = QPlatformMediaIntegration::instance()->createEncoder(this);
+ 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();
+ }
}
/*!
@@ -155,11 +134,8 @@ QMediaRecorder::QMediaRecorder(QObject *parent)
QMediaRecorder::~QMediaRecorder()
{
- if (d_ptr->captureSession) {
- if (d_ptr->captureSession->platformSession())
- d_ptr->captureSession->platformSession()->setMediaEncoder(nullptr);
+ if (d_ptr->captureSession)
d_ptr->captureSession->setRecorder(nullptr);
- }
delete d_ptr->control;
delete d_ptr;
}
@@ -167,22 +143,18 @@ QMediaRecorder::~QMediaRecorder()
/*!
\internal
*/
+QPlatformMediaRecorder *QMediaRecorder::platformRecoder() const
+{
+ return d_ptr->control;
+}
+
+/*!
+ \internal
+*/
void QMediaRecorder::setCaptureSession(QMediaCaptureSession *session)
{
Q_D(QMediaRecorder);
- if (d->captureSession == session)
- return;
-
d->captureSession = session;
-
- if (!d->captureSession)
- return;
-
- QPlatformMediaCaptureSession *platformSession = session->platformSession();
- if (!platformSession || !d->control)
- return;
-
- platformSession->setMediaEncoder(d->control);
}
/*!
\qmlproperty QUrl QtMultimedia::MediaRecorder::outputLocation
@@ -227,17 +199,11 @@ void QMediaRecorder::setCaptureSession(QMediaCaptureSession *session)
*/
/*!
- \qmlproperty bool QtMultimedia::MediaRecorder::isAvailable
- \brief This property holds whether the recorder service is ready to use.
-
- Returns \c true if media recorder service ready to use.
-*/
-/*!
Returns \c true if media recorder service ready to use.
*/
bool QMediaRecorder::isAvailable() const
{
- return d_func()->control != nullptr && d_func()->captureSession;
+ return d_func()->control && d_func()->captureSession;
}
QUrl QMediaRecorder::outputLocation() const
@@ -249,7 +215,7 @@ void QMediaRecorder::setOutputLocation(const QUrl &location)
{
Q_D(QMediaRecorder);
if (!d->control) {
- emit errorOccurred(QMediaRecorder::ResourceError, tr("Not available"));
+ emit errorOccurred(QMediaRecorder::ResourceError, d->initErrorMessage);
return;
}
d->control->setOutputLocation(location);
@@ -258,6 +224,35 @@ void QMediaRecorder::setOutputLocation(const QUrl &location)
emit errorOccurred(QMediaRecorder::LocationNotWritable, tr("Output location not writable"));
}
+/*!
+ Set the output IO device for media content.
+
+ The \a device must have been opened in the \l{QIODevice::Write}{Write} 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)
+{
+ Q_D(QMediaRecorder);
+ d->control->setOutputDevice(device);
+}
+
+/*!
+ Returns the output IO device for media content.
+
+ \sa setOutputDevice()
+*/
+QIODevice *QMediaRecorder::outputDevice() const
+{
+ Q_D(const QMediaRecorder);
+ return d->control->outputDevice();
+}
+
QUrl QMediaRecorder::actualLocation() const
{
Q_D(const QMediaRecorder);
@@ -276,6 +271,8 @@ QMediaRecorder::RecorderState QMediaRecorder::recorderState() const
}
/*!
+ \property QMediaRecorder::error
+
Returns the current error state.
\sa errorString()
@@ -294,6 +291,8 @@ QMediaRecorder::Error QMediaRecorder::error() const
\sa error
*/
/*!
+ \property QMediaRecorder::errorString
+
Returns a string describing the current error state.
\sa error()
@@ -303,7 +302,7 @@ QString QMediaRecorder::errorString() const
{
Q_D(const QMediaRecorder);
- return d->control ? d->control->errorString() : tr("QMediaRecorder not supported on this platform");
+ return d->control ? d->control->errorString() : d->initErrorMessage;
}
/*!
\qmlproperty qint64 QtMultimedia::MediaRecorder::duration
@@ -322,6 +321,11 @@ qint64 QMediaRecorder::duration() const
return d_func()->control ? d_func()->control->duration() : 0;
}
/*!
+ \fn void QMediaRecorder::encoderSettingsChanged()
+
+ Signals when the encoder settings change.
+*/
+/*!
\qmlmethod QtMultimedia::MediaRecorder::record()
\brief Starts recording.
@@ -359,17 +363,18 @@ void QMediaRecorder::record()
{
Q_D(QMediaRecorder);
- if (!d->control || ! d->captureSession)
+ if (!d->control || !d->captureSession)
return;
if (d->control->state() == QMediaRecorder::PausedState) {
d->control->resume();
} else {
auto oldMediaFormat = d->encoderSettings.mediaFormat();
- auto camera = d->captureSession->camera();
- auto flags = camera && camera->isActive() ? QMediaFormat::RequiresVideo
- : QMediaFormat::NoFlags;
- d->encoderSettings.resolveFormat(flags);
+
+ 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();
@@ -409,17 +414,18 @@ void QMediaRecorder::pause()
}
/*!
\qmlmethod QtMultimedia::MediaRecorder::stop()
- \brief Stops recording.
+ \brief Stops the recording.
- The recorder state is changed to \c{QMediaRecorder.StoppedState}.
+ 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.
*/
/*!
- Stops recording.
-
- The recorder state is changed to QMediaRecorder::StoppedState.
+ 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.
*/
-
void QMediaRecorder::stop()
{
Q_D(QMediaRecorder);
@@ -434,22 +440,14 @@ void QMediaRecorder::stop()
during record(), pause() or stop() calls.
RecorderSstate may also change asynchronously when recording fails.
- \value recorderState.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 recorderState.RecordingState The recording is requested.
- \value recorderState.PausedState The recorder is pause.
+ \value MediaRecorder.StoppedState The recorder is not active.
+ \value MediaRecorder.RecordingState The recording is requested.
+ \value MediaRecorder.PausedState The recorder is pause.
*/
/*!
\enum QMediaRecorder::RecorderState
\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.
*/
@@ -529,7 +527,7 @@ void QMediaRecorder::stop()
*/
/*!
- \qmlproperty MetaData QtMultimedia::MediaRecorder::metaData
+ \qmlproperty mediaMetaData QtMultimedia::MediaRecorder::metaData
\brief This property holds meta data associated with the recording.
@@ -538,9 +536,13 @@ void QMediaRecorder::stop()
\note Ensure that meta-data is assigned correctly by assigning it before
starting the recording.
+
+ \sa mediaMetaData
*/
/*!
+ \property QMediaRecorder::metaData
+
Returns the metaData associated with the recording.
*/
QMediaMetaData QMediaRecorder::metaData() const
@@ -564,6 +566,9 @@ void QMediaRecorder::setMetaData(const QMediaMetaData &metaData)
d->control->setMetaData(metaData);
}
+/*!
+ Adds \a metaData to the recorded media.
+*/
void QMediaRecorder::addMetaData(const QMediaMetaData &metaData)
{
auto data = this->metaData();
@@ -589,6 +594,9 @@ void QMediaRecorder::addMetaData(const QMediaMetaData &metaData)
once.
*/
+/*!
+ Returns the media capture session.
+*/
QMediaCaptureSession *QMediaRecorder::captureSession() const
{
Q_D(const QMediaRecorder);
@@ -599,11 +607,11 @@ QMediaCaptureSession *QMediaRecorder::captureSession() const
Enumerates quality encoding levels.
- \value MediaaRecorder.VeryLowQuality
- \value MediaaRecorder.LowQuality
- \value MediaaRecorder.NormalQuality
- \value MediaaRecorder.HighQuality
- \value MediaaRecorder.VeryHighQuality
+ \value MediaRecorder.VeryLowQuality
+ \value MediaRecorder.LowQuality
+ \value MediaRecorder.NormalQuality
+ \value MediaRecorder.HighQuality
+ \value MediaRecorder.VeryHighQuality
*/
/*!
\enum QMediaRecorder::Quality
@@ -637,7 +645,11 @@ QMediaCaptureSession *QMediaRecorder::captureSession() const
\brief This property holds the current MediaFormat of the recorder.
*/
+/*!
+ \property QMediaRecorder::mediaFormat
+ Returns the recording media format.
+*/
QMediaFormat QMediaRecorder::mediaFormat() const
{
Q_D(const QMediaRecorder);
@@ -654,6 +666,14 @@ void QMediaRecorder::setMediaFormat(const QMediaFormat &format)
}
/*!
+
+ \qmlproperty enumeration QtMultimedia::MediaRecorder::encodingMode
+ \since 6.6
+ \brief This property holds the encoding mode.
+ \sa QMediaRecorder::EncodingMode
+*/
+
+/*!
Returns the encoding mode.
\sa EncodingMode
@@ -665,6 +685,11 @@ QMediaRecorder::EncodingMode QMediaRecorder::encodingMode() const
}
/*!
+ \fn void QMediaRecorder::encodingModeChanged()
+
+ Signals when the encoding mode changes.
+*/
+/*!
Sets the encoding \a mode setting.
If ConstantQualityEncoding is set, the quality
@@ -682,12 +707,22 @@ void QMediaRecorder::setEncodingMode(EncodingMode mode)
emit encodingModeChanged();
}
+/*!
+ \property QMediaRecorder::quality
+
+ Returns the recording quality.
+*/
QMediaRecorder::Quality QMediaRecorder::quality() const
{
Q_D(const QMediaRecorder);
return d->encoderSettings.quality();
}
+/*!
+ \fn void QMediaRecorder::qualityChanged()
+
+ Signals when the recording quality changes.
+*/
void QMediaRecorder::setQuality(Quality quality)
{
Q_D(QMediaRecorder);
@@ -697,6 +732,15 @@ void QMediaRecorder::setQuality(Quality quality)
emit qualityChanged();
}
+/*!
+ \qmlproperty Size QtMultimedia::MediaRecorder::videoResolution
+ \since 6.6
+ \brief This property holds the resolution of the encoded video.
+
+ 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.
+*/
+
/*!
Returns the resolution of the encoded video.
@@ -708,6 +752,11 @@ QSize QMediaRecorder::videoResolution() const
}
/*!
+ \fn void QMediaRecorder::videoResolutionChanged()
+
+ Signals when the video recording resolution changes.
+*/
+/*!
Sets the resolution of the encoded video to \a{size}.
Pass an empty QSize to make the recorder choose an optimal resolution based
@@ -730,6 +779,15 @@ void QMediaRecorder::setVideoResolution(const QSize &size)
*/
/*!
+ \qmlproperty real QtMultimedia::MediaRecorder::videoFrameRate
+ \since 6.6
+ \brief This property holds the video frame rate.
+
+ 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.
+*/
+
+/*!
Returns the video frame rate.
*/
qreal QMediaRecorder::videoFrameRate() const
@@ -739,6 +797,11 @@ qreal QMediaRecorder::videoFrameRate() const
}
/*!
+ \fn void QMediaRecorder::videoFrameRateChanged()
+
+ Signals when the recording video frame rate changes.
+*/
+/*!
Sets the video \a frameRate.
A value of 0 indicates the recorder should make an optimal choice based on what is available
@@ -754,6 +817,12 @@ void QMediaRecorder::setVideoFrameRate(qreal frameRate)
}
/*!
+ \qmlproperty int QtMultimedia::MediaRecorder::videoBitRate
+ \since 6.6
+ \brief This property holds the bit rate of the compressed video stream in bits per second.
+*/
+
+/*!
Returns the bit rate of the compressed video stream in bits per second.
*/
int QMediaRecorder::videoBitRate() const
@@ -763,6 +832,11 @@ int QMediaRecorder::videoBitRate() const
}
/*!
+ \fn void QMediaRecorder::videoBitRateChanged()
+
+ Signals when the recording video bit rate changes.
+*/
+/*!
Sets the video \a bitRate in bits per second.
*/
void QMediaRecorder::setVideoBitRate(int bitRate)
@@ -775,6 +849,12 @@ void QMediaRecorder::setVideoBitRate(int bitRate)
}
/*!
+ \qmlproperty int QtMultimedia::MediaRecorder::audioBitRate
+ \since 6.6
+ \brief This property holds the bit rate of the compressed audio stream in bits per second.
+*/
+
+/*!
Returns the bit rate of the compressed audio stream in bits per second.
*/
int QMediaRecorder::audioBitRate() const
@@ -784,6 +864,11 @@ int QMediaRecorder::audioBitRate() const
}
/*!
+ \fn void QMediaRecorder::audioBitRateChanged()
+
+ Signals when the recording audio bit rate changes.
+*/
+/*!
Sets the audio \a bitRate in bits per second.
*/
void QMediaRecorder::setAudioBitRate(int bitRate)
@@ -796,6 +881,12 @@ void QMediaRecorder::setAudioBitRate(int bitRate)
}
/*!
+ \qmlproperty int QtMultimedia::MediaRecorder::audioChannelCount
+ \since 6.6
+ \brief This property holds the number of audio channels.
+*/
+
+/*!
Returns the number of audio channels.
*/
int QMediaRecorder::audioChannelCount() const
@@ -805,6 +896,11 @@ int QMediaRecorder::audioChannelCount() const
}
/*!
+ \fn void QMediaRecorder::audioChannelCountChanged()
+
+ Signals when the recording audio channel count changes.
+*/
+/*!
Sets the number of audio \a channels.
A value of -1 indicates the recorder should make an optimal choice based on
@@ -820,6 +916,12 @@ void QMediaRecorder::setAudioChannelCount(int channels)
}
/*!
+ \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.
*/
int QMediaRecorder::audioSampleRate() const
@@ -827,7 +929,11 @@ int QMediaRecorder::audioSampleRate() const
Q_D(const QMediaRecorder);
return d->encoderSettings.audioSampleRate();
}
+/*!
+ \fn void QMediaRecorder::audioSampleRateChanged()
+ Signals when the recording audio sample rate changes.
+*/
/*!
Sets the audio \a sampleRate in Hz.