1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qmediarecorder_p.h"
5
6#include <private/qplatformmediarecorder_p.h>
7#include <qaudiodevice.h>
8#include <qcamera.h>
9#include <qscreencapture.h>
10#include <qwindowcapture.h>
11#include <qmediacapturesession.h>
12#include <private/qplatformcamera_p.h>
13#include <private/qplatformsurfacecapture_p.h>
14#include <private/qplatformmediaintegration_p.h>
15#include <private/qplatformmediacapture_p.h>
16
17#include <QtCore/qdebug.h>
18#include <QtCore/qurl.h>
19#include <QtCore/qstringlist.h>
20#include <QtCore/qmetaobject.h>
21#include <QtCore/qtimer.h>
22
23#include <qaudioformat.h>
24
25QT_BEGIN_NAMESPACE
26
27/*!
28 \class QMediaRecorder
29 \inmodule QtMultimedia
30 \ingroup multimedia
31 \ingroup multimedia_recording
32 \ingroup multimedia_video
33 \ingroup multimedia_audio
34
35 \brief The QMediaRecorder class is used for encoding and recording a capture session.
36
37 Use the QMediaRecorder class to encode and record media generated in
38 \l QMediaCaptureSession. You can generate:
39 \list
40 \li Audio. Use \l QAudioInput or \l QAudioBufferInput.
41 \li Video. Use \l QCamera, \l QScreenCapture, \l QWindowCapture, or \l QVideoFrameInput.
42 \endlist
43
44 To record media, connect a generator to a corresponding media capture session.
45
46 Performance of video encoding and recording is limited by the hardware,
47 the operating system, the installed graphic drivers, and the input video format.
48 If \c QCamera, \c QScreenCapture, or \c QWindowCapture produces video frames
49 faster than \c QMediaRecorder can encode and record them, the recorder
50 may drop some frames. This is likely to occur if the input frame resolution
51 is high, 4K for example, and hardware-accelerated encoding is unavailable.
52 If you generate input video via \c QVideoFrameInput, the method
53 \c QVideoFrameInput::sendVideoFrame will do nothing and return \c false
54 whenever this limitation is reached and the internal frame queue is full.
55 Rely on the signal \c QVideoFrameInput::readyToSendVideoFrame to know
56 when the recorder is ready to receive new frames again.
57 If you cannot change the rate of video frame generation and dropping frames
58 is undesirable, we recommend implementing your own frame queue on top of
59 \c QVideoFrameInput, considering the memory limitations of the hardware.
60
61 \snippet multimedia-snippets/media.cpp Media recorder
62*/
63/*!
64 \qmltype MediaRecorder
65 \nativetype QMediaRecorder
66 \brief For encoding and recording media generated in a CaptureSession.
67
68 \inqmlmodule QtMultimedia
69 \ingroup multimedia_qml
70 \ingroup multimedia_audio_qml
71 \ingroup multimedia_video_qml
72
73 Use the MediaRecorder element within a CaptureSession to encode and record:
74 \list
75 \li Audio captured from an audio interface (like microphone or line input).
76 \li Video captured from camera, screen, or an application window.
77 \endlist
78
79 Performance of video encoding and recording is limited by the hardware,
80 the operating system, the installed graphic drivers, and the input video format.
81 If \c Camera, \c ScreenCapture, or \c WindowCapture produces video frames
82 faster than \c MediaRecorder can encode and record them, the recorder
83 may drop some frames. This is likely to occur if the input frame resolution
84 is high, 4K for example, and hardware-accelerated encoding is unavailable.
85
86 \since 6.2
87 The code below shows a simple capture session containing a MediaRecorder using the default
88 camera and default audio input.
89
90\qml
91 CaptureSession {
92 id: captureSession
93 camera: Camera {
94 id: camera
95 active: true
96 }
97 audioInput: AudioInput {}
98 recorder: MediaRecorder {
99 id: recorder
100 }
101 }
102\endqml
103
104 The code below shows how the recording can be started and stopped.
105\qml
106 CameraButton {
107 text: "Record"
108 visible: recorder.recorderState !== MediaRecorder.RecordingState
109 onClicked: recorder.record()
110 }
111
112 CameraButton {
113 id: stopButton
114 text: "Stop"
115 visible: recorder.recorderState === MediaRecorder.RecordingState
116 onClicked: recorder.stop()
117 }
118\endqml
119
120 \sa CaptureSession, Camera, ScreenCapture, WindowCapture, AudioInput, ImageCapture
121*/
122QMediaRecorderPrivate::QMediaRecorderPrivate()
123{
124#if QT_CONFIG(mimetype)
125 // Force an early initialization of the mime database
126 // to avoid a delay when recording for the first time.
127 encoderSettings.mimeType();
128#endif
129}
130
131QString QMediaRecorderPrivate::msgFailedStartRecording()
132{
133 return QMediaRecorder::tr(s: "Failed to start recording");
134}
135
136/*!
137 Constructs a media recorder.
138 The media recorder is a child of \a{parent}.
139*/
140
141QMediaRecorder::QMediaRecorder(QObject *parent)
142 : QObject(parent),
143 d_ptr(new QMediaRecorderPrivate)
144{
145 Q_D(QMediaRecorder);
146
147 auto &mediaIntegration = *QPlatformMediaIntegration::instance();
148
149 d->q_ptr = this;
150 auto maybeControl = mediaIntegration.createRecorder(this);
151 if (maybeControl) {
152 // The first format info initialization may take some time,
153 // for users it seems to be more suitable to have a delay on the object construction
154 // rather than on QMediaRecorder::record
155 mediaIntegration.formatInfo();
156
157 d->control = maybeControl.value();
158 } else {
159 d->initErrorMessage = maybeControl.error();
160 qWarning() << "Failed to initialize QMediaRecorder" << maybeControl.error();
161 }
162}
163
164/*!
165 Destroys a media recorder object.
166*/
167
168QMediaRecorder::~QMediaRecorder()
169{
170 if (d_ptr->captureSession)
171 d_ptr->captureSession->setRecorder(nullptr);
172 delete d_ptr->control;
173 delete d_ptr;
174}
175
176/*!
177 \internal
178*/
179QPlatformMediaRecorder *QMediaRecorder::platformRecoder() const
180{
181 return d_ptr->control;
182}
183
184/*!
185 \internal
186*/
187void QMediaRecorder::setCaptureSession(QMediaCaptureSession *session)
188{
189 Q_D(QMediaRecorder);
190 d->captureSession = session;
191}
192/*!
193 \qmlproperty url QtMultimedia::MediaRecorder::outputLocation
194 \brief The destination location of media content.
195
196 Setting the location can fail, for example when the service supports only
197 local file system locations but a network URL was passed. If the operation
198 fails, the \l errorOccurred() signal is emitted.
199
200 The output location can be empty, a directory, or a file. The path to a
201 directory or file can be relative or absolute. The \l record() method
202 generates the actual location according to the specified output location and
203 system-specific settings. Refer to the \l actualLocation property description
204 for details.
205
206 \sa actualLocation, errorOccurred()
207*/
208
209/*!
210 \property QMediaRecorder::outputLocation
211 \brief The destination location of media content.
212
213 Setting the location can fail, for example when the service supports only
214 local file system locations but a network URL was passed. If the operation
215 fails, the \l errorOccurred() signal is emitted.
216
217 The output location is ignored if a writable \l outputDevice
218 has been assigned to the recorder.
219 This behavior may change in the future, so we recommend setting only one output,
220 either \c outputLocation or \c outputDevice.
221
222 The output location can be empty, a directory, or a file. The path to a
223 directory or file can be relative or absolute. The \l record() method
224 generates the actual location according to the specified output location and
225 system-specific settings. Refer to the \l actualLocation property description
226 for details.
227
228 \sa actualLocation, outputDevice()
229*/
230
231/*!
232 \qmlproperty url QtMultimedia::MediaRecorder::actualLocation
233 \brief The actual location of the last media content.
234
235 The actual location is reset when a new \l outputLocation is assigned.
236 When \l record() is invoked, the recorder generates the actual location
237 basing on the following rules.
238 \list
239 \li If \c outputLocation is empty, a directory, or a file
240 without an extension, the recorder generates the appropriate extension
241 based on the selected media format and system MIME types.
242 \li If \c outputLocation is a directory, the recorder generates a new file
243 name within it.
244 \li If \c outputLocation is empty, the recorder generates a new file name in
245 the system-specific directory for audio or video.
246 \li The recorder generates the actual location before
247 emitting \c recorderStateChanged(RecordingState).
248 \endlist
249*/
250
251/*!
252 \property QMediaRecorder::actualLocation
253 \brief The actual location of the last media content.
254
255 The actual location is reset when a new \l outputLocation
256 or a non-null \l outputDevice is assigned.
257 When \l record() is invoked and \c outputDevice is \c null or not writable,
258 the recorder generates the actual location basing on the following rules.
259 \list
260 \li If \c outputLocation is empty, a directory, or a file
261 without an extension, the recorder generates the appropriate extension
262 based on the selected media format and system MIME types.
263 \li If \c outputLocation is a directory, the recorder generates a new file
264 name within it.
265 \li If \c outputLocation is empty, the recorder generates a new file name in
266 the system-specific directory for audio or video.
267 \li The recorder generates the actual location before
268 emitting \c recorderStateChanged(RecordingState).
269 \endlist
270*/
271
272/*!
273 Returns \c true if media recorder service ready to use.
274*/
275bool QMediaRecorder::isAvailable() const
276{
277 return d_func()->control && d_func()->captureSession;
278}
279
280QUrl QMediaRecorder::outputLocation() const
281{
282 return d_func()->control ? d_func()->control->outputLocation() : QUrl();
283}
284
285void QMediaRecorder::setOutputLocation(const QUrl &location)
286{
287 Q_D(QMediaRecorder);
288 if (!d->control) {
289 emit errorOccurred(error: QMediaRecorder::ResourceError, errorString: d->initErrorMessage);
290 return;
291 }
292 d->control->setOutputLocation(location);
293 d->control->clearActualLocation();
294 if (!location.isEmpty() && !d->control->isLocationWritable(location))
295 emit errorOccurred(error: QMediaRecorder::LocationNotWritable,
296 QStringLiteral("Output location not writable"));
297}
298
299/*!
300 Set the output IO device for media content.
301
302 The \a device must have been opened in the \l{QIODevice::WriteOnly}{WriteOnly} or
303 \l{QIODevice::ReadWrite}{ReadWrite} modes before the recording starts.
304
305 The media recorder doesn't take ownership of the specified \a device.
306 If the recording has been started, the device must be kept alive and open until
307 the signal \c recorderStateChanged(StoppedState) is emitted.
308
309 This method resets \l actualLocation immediately unless
310 the specified \a device is \c null.
311
312 If a writable output device is assigned to the recorder, \l outputLocation
313 is ignored, and \l actualLocation is not generated when recording starts.
314 This behavior may change in the future, so we recommend setting only
315 one output, either \c outputLocation or \c outputDevice.
316
317 \c QMediaRecorder::setOutputDevice is only supported with the FFmpeg backend.
318
319 \sa outputDevice(), outputLocation
320*/
321void QMediaRecorder::setOutputDevice(QIODevice *device)
322{
323 Q_D(QMediaRecorder);
324 if (!d->control) {
325 emit errorOccurred(error: QMediaRecorder::ResourceError, errorString: d->initErrorMessage);
326 return;
327 }
328
329 d->control->setOutputDevice(device);
330
331 if (device)
332 d->control->clearActualLocation();
333}
334
335/*!
336 Returns the output IO device for media content.
337
338 \sa setOutputDevice()
339*/
340QIODevice *QMediaRecorder::outputDevice() const
341{
342 Q_D(const QMediaRecorder);
343 return d->control ? d->control->outputDevice() : nullptr;
344}
345
346QUrl QMediaRecorder::actualLocation() const
347{
348 Q_D(const QMediaRecorder);
349 return d->control ? d->control->actualLocation() : QUrl();
350}
351
352/*!
353 Returns the current media recorder state.
354
355 \sa QMediaRecorder::RecorderState
356*/
357
358QMediaRecorder::RecorderState QMediaRecorder::recorderState() const
359{
360 return d_func()->control ? QMediaRecorder::RecorderState(d_func()->control->state()) : StoppedState;
361}
362
363/*!
364 \property QMediaRecorder::error
365
366 Returns the current error state.
367
368 \sa errorString()
369*/
370
371QMediaRecorder::Error QMediaRecorder::error() const
372{
373 Q_D(const QMediaRecorder);
374
375 return d->control ? d->control->error() : QMediaRecorder::ResourceError;
376}
377/*!
378 \qmlproperty string QtMultimedia::MediaRecorder::errorString
379 \brief This property holds a string describing the current error state.
380
381 \sa error
382*/
383/*!
384 \property QMediaRecorder::errorString
385
386 Returns a string describing the current error state.
387
388 \sa error()
389*/
390
391QString QMediaRecorder::errorString() const
392{
393 Q_D(const QMediaRecorder);
394
395 return d->control ? d->control->errorString() : d->initErrorMessage;
396}
397/*!
398 \qmlproperty qint64 QtMultimedia::MediaRecorder::duration
399
400 \brief This property holds the recorded media duration in milliseconds.
401*/
402
403/*!
404 \property QMediaRecorder::duration
405
406 \brief the recorded media duration in milliseconds.
407*/
408
409qint64 QMediaRecorder::duration() const
410{
411 return d_func()->control ? d_func()->control->duration() : 0;
412}
413
414#if QT_DEPRECATED_SINCE(6, 9)
415/*!
416 \fn void QMediaRecorder::encoderSettingsChanged()
417 \deprecated [6.9] Use specific signals instead.
418
419 Signals when the encoder settings change.
420*/
421#endif
422
423/*!
424 \qmlmethod QtMultimedia::MediaRecorder::record()
425 \brief Starts recording.
426
427 While the recorder state is changed immediately to
428 \c MediaRecorder.RecordingState, recording may start asynchronously.
429
430 If recording fails, the error() signal is emitted with recorder state being
431 reset back to \c{QMediaRecorder.StoppedState}.
432
433 This method updates \l actualLocation according to its generation rules.
434
435 \note On mobile devices, recording will happen in the orientation the
436 device had when calling record and is locked for the duration of the recording.
437 To avoid artifacts on the user interface, we recommend to keep the user interface
438 locked to the same orientation as long as the recording is ongoing using
439 the contentOrientation property of the Window and unlock it again once the recording
440 is finished.
441*/
442/*!
443 Starts recording.
444
445 While the recorder state is changed immediately to
446 c\{QMediaRecorder::RecordingState}, recording may start asynchronously.
447
448 If recording fails error() signal is emitted with recorder state being
449 reset back to \c{QMediaRecorder::StoppedState}.
450
451 This method updates \l actualLocation according to its generation rules.
452
453 \note On mobile devices, recording will happen in the orientation the
454 device had when calling record and is locked for the duration of the recording.
455 To avoid artifacts on the user interface, we recommend to keep the user interface
456 locked to the same orientation as long as the recording is ongoing using
457 the contentOrientation property of QWindow and unlock it again once the recording
458 is finished.
459*/
460
461void QMediaRecorder::record()
462{
463 Q_D(QMediaRecorder);
464
465 if (!d->control || !d->captureSession)
466 return;
467
468 if (d->control->state() == QMediaRecorder::PausedState) {
469 d->control->resume();
470 } else {
471 auto oldMediaFormat = d->encoderSettings.mediaFormat();
472
473 auto platformSession = d->captureSession->platformSession();
474 const bool hasVideo = platformSession && !platformSession->activeVideoSources().empty();
475
476 d->encoderSettings.resolveFormat(flags: hasVideo ? QMediaFormat::RequiresVideo : QMediaFormat::NoFlags);
477 d->control->clearActualLocation();
478 d->control->clearError();
479
480 auto settings = d->encoderSettings;
481 d->control->record(settings&: d->encoderSettings);
482
483#if QT_DEPRECATED_SINCE(6, 9)
484QT_WARNING_PUSH
485QT_WARNING_DISABLE_DEPRECATED
486 if (settings != d->encoderSettings)
487 emit encoderSettingsChanged();
488QT_WARNING_POP
489#endif
490
491 if (oldMediaFormat != d->encoderSettings.mediaFormat())
492 emit mediaFormatChanged();
493
494 if (settings.encodingMode() != d->encoderSettings.encodingMode())
495 emit encodingModeChanged();
496
497 if (settings.quality() != d->encoderSettings.quality())
498 emit qualityChanged();
499
500 if (settings.videoResolution() != d->encoderSettings.videoResolution())
501 emit videoResolutionChanged();
502
503 if (!qFuzzyCompare(p1: settings.videoFrameRate(), p2: d->encoderSettings.videoFrameRate()))
504 emit videoFrameRateChanged();
505
506 if (settings.videoBitRate() != d->encoderSettings.videoBitRate())
507 emit videoBitRateChanged();
508
509 if (settings.audioBitRate() != d->encoderSettings.audioBitRate())
510 emit audioBitRateChanged();
511
512 if (settings.audioChannelCount() != d->encoderSettings.audioChannelCount())
513 emit audioChannelCountChanged();
514
515 if (settings.audioSampleRate() != d->encoderSettings.audioSampleRate())
516 emit audioSampleRateChanged();
517 }
518}
519/*!
520 \qmlmethod QtMultimedia::MediaRecorder::pause()
521 \brief Pauses recording.
522
523 The recorder state is changed to QMediaRecorder.PausedState.
524
525 Depending on the platform, pausing recording may be not supported.
526 In this case the recorder state is unchanged.
527*/
528/*!
529 Pauses recording.
530
531 The recorder state is changed to QMediaRecorder::PausedState.
532
533 Depending on the platform, pausing recording may be not supported.
534 In this case the recorder state is unchanged.
535*/
536
537void QMediaRecorder::pause()
538{
539 Q_D(QMediaRecorder);
540 if (d->control && d->captureSession)
541 d->control->pause();
542}
543/*!
544 \qmlmethod QtMultimedia::MediaRecorder::stop()
545 \brief Stops the recording.
546
547 The recorder will stop the recording. Processing pending video and audio data might
548 however still take some time. The recording is finished, once the state of the media
549 recorder changes to QMediaRecorder::StoppedState.
550*/
551
552/*!
553 The recorder will stop the recording. Processing pending video and audio data might
554 however still take some time. The recording is finished, once the state of the media
555 recorder changes to QMediaRecorder::StoppedState.
556*/
557void QMediaRecorder::stop()
558{
559 Q_D(QMediaRecorder);
560 if (d->control && d->captureSession)
561 d->control->stop();
562}
563/*!
564 \qmlproperty enumeration QtMultimedia::MediaRecorder::recorderState
565 \brief This property holds the current media recorder state.
566
567 The state property represents the user request and is changed synchronously
568 during record(), pause() or stop() calls.
569 RecorderSstate may also change asynchronously when recording fails.
570
571 \value MediaRecorder.StoppedState The recorder is not active.
572 \value MediaRecorder.RecordingState The recording is requested.
573 \value MediaRecorder.PausedState The recorder is pause.
574*/
575/*!
576 \enum QMediaRecorder::RecorderState
577
578 \value StoppedState The recorder is not active.
579 \value RecordingState The recording is requested.
580 \value PausedState The recorder is paused.
581*/
582/*!
583 \qmlproperty enumeration QtMultimedia::MediaRecorder::error
584 \brief This property holds the current media recorder error state.
585
586 \value MediaRecorder.NoError Not in an error state.
587 \value MediaRecorder.ResourceError Not enough system resources
588 \value MediaRecorder.FormatError the current format is not supported.
589 \value MediaRecorder.OutOfSpaceError No space left on device.
590 \value MediaRecorder.LocationNotWriteable The output location is not writable.
591*/
592/*!
593 \enum QMediaRecorder::Error
594
595 \value NoError No Errors.
596 \value ResourceError Device is not ready or not available.
597 \value FormatError Current format is not supported.
598 \value OutOfSpaceError No space left on device.
599 \value LocationNotWritable The output location is not writable.
600*/
601
602/*!
603 \property QMediaRecorder::recorderState
604 \brief The current state of the media recorder.
605
606 The state property represents the user request and is changed synchronously
607 during record(), pause() or stop() calls.
608 Recorder state may also change asynchronously when recording fails.
609*/
610
611/*!
612 \qmlsignal QtMultimedia::MediaRecorder::recorderStateChanged(RecorderState state)
613 \brief Signals that a media recorder's \a state has changed.
614*/
615
616/*!
617 \fn QMediaRecorder::recorderStateChanged(QMediaRecorder::RecorderState state)
618
619 Signals that a media recorder's \a state has changed.
620*/
621
622/*!
623 \qmlsignal QtMultimedia::MediaRecorder::durationChanged(qint64 duration)
624 \brief Signals that the \a duration of the recorded media has changed.
625*/
626
627/*!
628 \fn QMediaRecorder::durationChanged(qint64 duration)
629
630 Signals that the \a duration of the recorded media has changed.
631*/
632/*!
633 \qmlsignal QtMultimedia::MediaRecorder::actualLocationChanged(const QUrl &location)
634 \brief Signals that the actual \a location of the recorded media has changed.
635
636 This signal is usually emitted when recording starts.
637*/
638/*!
639 \fn QMediaRecorder::actualLocationChanged(const QUrl &location)
640
641 Signals that the actual \a location of the recorded media has changed.
642 This signal is usually emitted when recording starts.
643*/
644/*!
645 \qmlsignal QtMultimedia::MediaRecorder::errorOccurred(Error error, const QString &errorString)
646 \brief Signals that an \a error has occurred.
647
648 The \a errorString contains a description of the error.
649*/
650/*!
651 \fn QMediaRecorder::errorOccurred(QMediaRecorder::Error error, const QString &errorString)
652
653 Signals that an \a error has occurred, with \a errorString containing
654 a description of the error.
655*/
656
657/*!
658 \qmlproperty mediaMetaData QtMultimedia::MediaRecorder::metaData
659
660 \brief This property holds meta data associated with the recording.
661
662 When a recording is started, any meta-data assigned will be attached to that
663 recording.
664
665 \note Ensure that meta-data is assigned correctly by assigning it before
666 starting the recording.
667
668 \sa mediaMetaData
669*/
670
671/*!
672 \property QMediaRecorder::metaData
673
674 Returns the metaData associated with the recording.
675*/
676QMediaMetaData QMediaRecorder::metaData() const
677{
678 Q_D(const QMediaRecorder);
679
680 return d->control ? d->control->metaData() : QMediaMetaData{};
681}
682
683/*!
684 Sets the meta data to \a metaData.
685
686 \note To ensure that meta-data is set correctly, it should be set before starting the recording.
687 Once the recording is started, any meta-data set will be attached to the next recording.
688*/
689void QMediaRecorder::setMetaData(const QMediaMetaData &metaData)
690{
691 Q_D(QMediaRecorder);
692
693 if (d->control && d->captureSession)
694 d->control->setMetaData(metaData);
695}
696
697/*!
698 Adds \a metaData to the recorded media.
699*/
700void QMediaRecorder::addMetaData(const QMediaMetaData &metaData)
701{
702 auto data = this->metaData();
703 // merge data
704 for (auto &&[key, value] : metaData.asKeyValueRange())
705 data.insert(k: key, value);
706 setMetaData(data);
707}
708
709/*!
710 \property QMediaRecorder::autoStop
711
712 This property controls whether the media recorder stops automatically when
713 all media inputs have reported the end of the stream or have been deactivated.
714
715 The end of the stream is reported by sending an empty media frame,
716 which you can send explicitly via \l QVideoFrameInput or \l QAudioBufferInput.
717
718 Video inputs, specificly, \l QCamera, \l QScreenCapture and \l QWindowCapture,
719 can be deactivated via the function \c setActive.
720
721 Defaults to \c false.
722
723 QMediaRecorder::autoStop is only supported with the FFmpeg backend.
724
725 \sa QCamera, QScreenCapture, QWindowCapture
726*/
727
728bool QMediaRecorder::autoStop() const
729{
730 Q_D(const QMediaRecorder);
731
732 return d->autoStop;
733}
734
735void QMediaRecorder::setAutoStop(bool autoStop)
736{
737 Q_D(QMediaRecorder);
738
739 if (d->autoStop == autoStop)
740 return;
741
742 d->autoStop = autoStop;
743
744 if (d->control)
745 d->control->updateAutoStop();
746
747 emit autoStopChanged();
748}
749
750/*!
751 \qmlsignal QtMultimedia::MediaRecorder::metaDataChanged()
752
753 \brief Signals that a media object's meta-data has changed.
754
755 If multiple meta-data elements are changed metaDataChanged() is emitted
756 once.
757*/
758/*!
759 \fn QMediaRecorder::metaDataChanged()
760
761 Signals that a media object's meta-data has changed.
762
763 If multiple meta-data elements are changed metaDataChanged() is emitted
764 once.
765*/
766
767/*!
768 Returns the media capture session.
769*/
770QMediaCaptureSession *QMediaRecorder::captureSession() const
771{
772 Q_D(const QMediaRecorder);
773 return d->captureSession;
774}
775/*!
776 \qmlproperty enumeration QtMultimedia::MediaRecorder::quality
777
778 Enumerates quality encoding levels.
779
780 \value MediaRecorder.VeryLowQuality
781 \value MediaRecorder.LowQuality
782 \value MediaRecorder.NormalQuality
783 \value MediaRecorder.HighQuality
784 \value MediaRecorder.VeryHighQuality
785*/
786/*!
787 \enum QMediaRecorder::Quality
788
789 Enumerates quality encoding levels.
790
791 \value VeryLowQuality
792 \value LowQuality
793 \value NormalQuality
794 \value HighQuality
795 \value VeryHighQuality
796*/
797
798/*!
799 \enum QMediaRecorder::EncodingMode
800
801 Enumerates encoding modes.
802
803 \value ConstantQualityEncoding Encoding will aim to have a constant quality, adjusting bitrate to fit.
804 \value ConstantBitRateEncoding Encoding will use a constant bit rate, adjust quality to fit.
805 \value AverageBitRateEncoding Encoding will try to keep an average bitrate setting, but will use
806 more or less as needed.
807 \value TwoPassEncoding The media will first be processed to determine the characteristics,
808 and then processed a second time allocating more bits to the areas
809 that need it.
810*/
811
812/*!
813
814 \qmlproperty mediaFormat QtMultimedia::MediaRecorder::mediaFormat
815
816 \brief This property holds the current MediaFormat of the recorder.
817*/
818/*!
819 \property QMediaRecorder::mediaFormat
820
821 \brief This property holds the current \l QMediaFormat of the recorder.
822
823 The value of this property may change when invoking \l record(). If this happens, the
824 mediaFormatChanged() signal will be emitted. This will always happen if the
825 \l QMediaFormat::audioCodec or \l QMediaFormat::fileFormat properties are set to unspecified.
826 If a video source (\l QCamera, \l QScreenCapture, or \l QVideoFrameInput) is connected to the
827 \l QMediaCaptureSession, \l QMediaFormat::videoCodec must also be specified.
828 The \l QMediaFormat::audioCodec and \l QMediaFormat::videoCodec property values may also change
829 if the media backend does not support the selected file format or codec.
830
831 The \l QMediaFormat::fileFormat property value may also change to an \c audio only format if a
832 video format was requested, but \l QMediaCaptureSession does not have a video source connected.
833 For example, if \l QMediaFormat::fileFormat is set to \l QMediaFormat::MPEG4, it may
834 be changed to \l QMediaFormat::Mpeg4Audio.
835
836 Applications can determine if \c mediaFormat will change before recording starts by calling the
837 \l QMediaFormat::isSupported() function. When recording without any video inputs,
838 \l record() will not be changed the \l QMediaFormat if the following is true:
839 \list
840 \li \l QMediaFormat::fileFormat is specified
841 \li \l QMediaFormat::audioCodec is specified
842 \li \l QMediaFormat::videoCodec is \b{unspecified}
843 \li \l QMediaFormat::isSupported() returns \c true
844 \endlist
845 When recording with video input, \c mediaFormat will not be changed if the following is true:
846 \list
847 \li \l QMediaFormat::fileFormat is specified
848 \li \l QMediaFormat::audioCodec is specified
849 \li \l QMediaFormat::videoCodec is specified
850 \li \l QMediaFormat::isSupported() returns \c true
851 \endlist
852
853 \note The \l QMediaRecorder does not take the file name extension from the \l outputLocation
854 property into account when determining the \l QMediaFormat::fileFormat, and will not adjust the
855 extension of the \l outputLocation \l QUrl to match the selected file format if an extension is
856 specified. Applications should therefore make sure to set the
857 \l {QMediaFormat::fileFormat}{QMediaRecorder::mediaFormat::fileFormat} to match the file
858 extension, or not specify a file extension. If no file extension is specified, the
859 \l actualLocation file extension will be updated to match the file format used for recording.
860
861 \sa QMediaFormat::isSupported(), actualLocation
862*/
863QMediaFormat QMediaRecorder::mediaFormat() const
864{
865 Q_D(const QMediaRecorder);
866 return d->encoderSettings.mediaFormat();
867}
868
869void QMediaRecorder::setMediaFormat(const QMediaFormat &format)
870{
871 Q_D(QMediaRecorder);
872 if (d->encoderSettings.mediaFormat() == format)
873 return;
874 d->encoderSettings.setMediaFormat(format);
875 emit mediaFormatChanged();
876}
877
878/*!
879
880 \qmlproperty enumeration QtMultimedia::MediaRecorder::encodingMode
881 \since 6.6
882 \brief This property holds the encoding mode.
883 \sa QMediaRecorder::EncodingMode
884*/
885
886/*!
887 Returns the encoding mode.
888
889 \sa EncodingMode
890*/
891QMediaRecorder::EncodingMode QMediaRecorder::encodingMode() const
892{
893 Q_D(const QMediaRecorder);
894 return d->encoderSettings.encodingMode();
895}
896
897/*!
898 \fn void QMediaRecorder::encodingModeChanged()
899
900 Signals when the encoding mode changes.
901*/
902/*!
903 Sets the encoding \a mode setting.
904
905 If ConstantQualityEncoding is set, the quality
906 encoding parameter is used and bit rates are ignored,
907 otherwise the bitrates are used.
908
909 \sa encodingMode(), EncodingMode
910*/
911void QMediaRecorder::setEncodingMode(EncodingMode mode)
912{
913 Q_D(QMediaRecorder);
914 if (d->encoderSettings.encodingMode() == mode)
915 return;
916 d->encoderSettings.setEncodingMode(mode);
917 emit encodingModeChanged();
918}
919
920/*!
921 \property QMediaRecorder::quality
922
923 Returns the recording quality.
924*/
925QMediaRecorder::Quality QMediaRecorder::quality() const
926{
927 Q_D(const QMediaRecorder);
928 return d->encoderSettings.quality();
929}
930
931/*!
932 \fn void QMediaRecorder::qualityChanged()
933
934 Signals when the recording quality changes.
935*/
936void QMediaRecorder::setQuality(Quality quality)
937{
938 Q_D(QMediaRecorder);
939
940 quality = std::clamp(val: quality, lo: QMediaRecorder::Quality::VeryLowQuality,
941 hi: QMediaRecorder::Quality::VeryHighQuality);
942
943 if (d->encoderSettings.quality() == quality)
944 return;
945
946 d->encoderSettings.setQuality(quality);
947 emit qualityChanged();
948}
949
950/*!
951 \qmlproperty Size QtMultimedia::MediaRecorder::videoResolution
952 \since 6.6
953 \brief This property holds the resolution of the encoded video.
954
955 Set an empty Size to make the recorder choose an optimal resolution based
956 on what is available from the video source and the limitations of the codec.
957*/
958
959
960/*!
961 Returns the resolution of the encoded video.
962*/
963QSize QMediaRecorder::videoResolution() const
964{
965 Q_D(const QMediaRecorder);
966 return d->encoderSettings.videoResolution();
967}
968
969/*!
970 \fn void QMediaRecorder::videoResolutionChanged()
971
972 Signals when the video recording resolution changes.
973*/
974/*!
975 Sets the resolution of the encoded video to \a{size}.
976
977 Pass an empty QSize to make the recorder choose an optimal resolution based
978 on what is available from the video source and the limitations of the codec.
979*/
980void QMediaRecorder::setVideoResolution(const QSize &size)
981{
982 Q_D(QMediaRecorder);
983 if (d->encoderSettings.videoResolution() == size)
984 return;
985 d->encoderSettings.setVideoResolution(size);
986 emit videoResolutionChanged();
987}
988
989/*! \fn void QMediaRecorder::setVideoResolution(int width, int height)
990
991 Sets the \a width and \a height of the resolution of the encoded video.
992
993 \overload
994*/
995
996/*!
997 \qmlproperty real QtMultimedia::MediaRecorder::videoFrameRate
998 \since 6.6
999 \brief This property holds the video frame rate.
1000
1001 A value of 0 indicates the recorder should make an optimal choice based on what is available
1002 from the video source and the limitations of the codec.
1003*/
1004
1005/*!
1006 Returns the video frame rate.
1007*/
1008qreal QMediaRecorder::videoFrameRate() const
1009{
1010 Q_D(const QMediaRecorder);
1011 return d->encoderSettings.videoFrameRate();
1012}
1013
1014/*!
1015 \fn void QMediaRecorder::videoFrameRateChanged()
1016
1017 Signals when the recording video frame rate changes.
1018*/
1019/*!
1020 Sets the video \a frameRate.
1021
1022 A value of 0 indicates the recorder should make an optimal choice based on what is available
1023 from the video source and the limitations of the codec.
1024*/
1025void QMediaRecorder::setVideoFrameRate(qreal frameRate)
1026{
1027 Q_D(QMediaRecorder);
1028 if (d->encoderSettings.videoFrameRate() == frameRate)
1029 return;
1030 d->encoderSettings.setVideoFrameRate(frameRate);
1031 emit videoFrameRateChanged();
1032}
1033
1034/*!
1035 \qmlproperty int QtMultimedia::MediaRecorder::videoBitRate
1036 \since 6.6
1037 \brief This property holds the bit rate of the compressed video stream in bits per second.
1038*/
1039
1040/*!
1041 Returns the bit rate of the compressed video stream in bits per second.
1042*/
1043int QMediaRecorder::videoBitRate() const
1044{
1045 Q_D(const QMediaRecorder);
1046 return d->encoderSettings.videoBitRate();
1047}
1048
1049/*!
1050 \fn void QMediaRecorder::videoBitRateChanged()
1051
1052 Signals when the recording video bit rate changes.
1053*/
1054/*!
1055 Sets the video \a bitRate in bits per second.
1056*/
1057void QMediaRecorder::setVideoBitRate(int bitRate)
1058{
1059 Q_D(QMediaRecorder);
1060 if (d->encoderSettings.videoBitRate() == bitRate)
1061 return;
1062 d->encoderSettings.setVideoBitRate(bitRate);
1063 emit videoBitRateChanged();
1064}
1065
1066/*!
1067 \qmlproperty int QtMultimedia::MediaRecorder::audioBitRate
1068 \since 6.6
1069 \brief This property holds the bit rate of the compressed audio stream in bits per second.
1070*/
1071
1072/*!
1073 Returns the bit rate of the compressed audio stream in bits per second.
1074*/
1075int QMediaRecorder::audioBitRate() const
1076{
1077 Q_D(const QMediaRecorder);
1078 return d->encoderSettings.audioBitRate();
1079}
1080
1081/*!
1082 \fn void QMediaRecorder::audioBitRateChanged()
1083
1084 Signals when the recording audio bit rate changes.
1085*/
1086/*!
1087 Sets the audio \a bitRate in bits per second.
1088*/
1089void QMediaRecorder::setAudioBitRate(int bitRate)
1090{
1091 Q_D(QMediaRecorder);
1092 if (d->encoderSettings.audioBitRate() == bitRate)
1093 return;
1094 d->encoderSettings.setAudioBitRate(bitRate);
1095 emit audioBitRateChanged();
1096}
1097
1098/*!
1099 \qmlproperty int QtMultimedia::MediaRecorder::audioChannelCount
1100 \since 6.6
1101 \brief This property holds the number of audio channels.
1102*/
1103
1104/*!
1105 Returns the number of audio channels.
1106*/
1107int QMediaRecorder::audioChannelCount() const
1108{
1109 Q_D(const QMediaRecorder);
1110 return d->encoderSettings.audioChannelCount();
1111}
1112
1113/*!
1114 \fn void QMediaRecorder::audioChannelCountChanged()
1115
1116 Signals when the recording audio channel count changes.
1117*/
1118/*!
1119 Sets the number of audio \a channels.
1120
1121 A value of -1 indicates the recorder should make an optimal choice based on
1122 what is available from the audio source and the limitations of the codec.
1123*/
1124void QMediaRecorder::setAudioChannelCount(int channels)
1125{
1126 Q_D(QMediaRecorder);
1127 if (d->encoderSettings.audioChannelCount() == channels)
1128 return;
1129 d->encoderSettings.setAudioChannelCount(channels);
1130 emit audioChannelCountChanged();
1131}
1132
1133/*!
1134 \qmlproperty int QtMultimedia::MediaRecorder::audioSampleRate
1135 \since 6.6
1136 \brief This property holds the audio sample rate in Hz.
1137*/
1138
1139/*!
1140 Returns the audio sample rate in Hz.
1141*/
1142int QMediaRecorder::audioSampleRate() const
1143{
1144 Q_D(const QMediaRecorder);
1145 return d->encoderSettings.audioSampleRate();
1146}
1147/*!
1148 \fn void QMediaRecorder::audioSampleRateChanged()
1149
1150 Signals when the recording audio sample rate changes.
1151*/
1152/*!
1153 Sets the audio \a sampleRate in Hz.
1154
1155 A value of \c -1 indicates the recorder should make an optimal choice based
1156 on what is available from the audio source, and the limitations of the codec.
1157*/
1158void QMediaRecorder::setAudioSampleRate(int sampleRate)
1159{
1160 Q_D(QMediaRecorder);
1161 if (d->encoderSettings.audioSampleRate() == sampleRate)
1162 return;
1163 d->encoderSettings.setAudioSampleRate(sampleRate);
1164 emit audioSampleRateChanged();
1165}
1166
1167QT_END_NAMESPACE
1168
1169#include "moc_qmediarecorder.cpp"
1170

source code of qtmultimedia/src/multimedia/recording/qmediarecorder.cpp