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

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