1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qmediarecorder.h"
41#include "qmediarecorder_p.h"
42
43#include <qmediarecordercontrol.h>
44#include "qmediaobject_p.h"
45#include <qmediaservice.h>
46#include <qmediaserviceprovider_p.h>
47#include <qmetadatawritercontrol.h>
48#include <qaudioencodersettingscontrol.h>
49#include <qvideoencodersettingscontrol.h>
50#include <qmediacontainercontrol.h>
51#include <qmediaavailabilitycontrol.h>
52#include <qcamera.h>
53#include <qcameracontrol.h>
54
55#include <QtCore/qdebug.h>
56#include <QtCore/qurl.h>
57#include <QtCore/qstringlist.h>
58#include <QtCore/qmetaobject.h>
59
60#include <qaudioformat.h>
61
62QT_BEGIN_NAMESPACE
63
64/*!
65 \class QMediaRecorder
66 \inmodule QtMultimedia
67 \ingroup multimedia
68 \ingroup multimedia_recording
69
70 \brief The QMediaRecorder class is used for the recording of media content.
71
72 The QMediaRecorder class is a high level media recording class. It's not
73 intended to be used alone but for accessing the media recording functions
74 of other media objects, like QRadioTuner, or QCamera.
75
76 \snippet multimedia-snippets/media.cpp Media recorder
77
78 \sa QAudioRecorder
79*/
80
81static void qRegisterMediaRecorderMetaTypes()
82{
83 qRegisterMetaType<QMediaRecorder::State>(typeName: "QMediaRecorder::State");
84 qRegisterMetaType<QMediaRecorder::Status>(typeName: "QMediaRecorder::Status");
85 qRegisterMetaType<QMediaRecorder::Error>(typeName: "QMediaRecorder::Error");
86}
87
88Q_CONSTRUCTOR_FUNCTION(qRegisterMediaRecorderMetaTypes)
89
90
91QMediaRecorderPrivate::QMediaRecorderPrivate():
92 mediaObject(nullptr),
93 control(nullptr),
94 formatControl(nullptr),
95 audioControl(nullptr),
96 videoControl(nullptr),
97 metaDataControl(nullptr),
98 availabilityControl(nullptr),
99 settingsChanged(false),
100 notifyTimer(nullptr),
101 state(QMediaRecorder::StoppedState),
102 error(QMediaRecorder::NoError)
103{
104}
105
106#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
107
108void QMediaRecorderPrivate::_q_stateChanged(QMediaRecorder::State ps)
109{
110 Q_Q(QMediaRecorder);
111
112 if (ps == QMediaRecorder::RecordingState)
113 notifyTimer->start();
114 else
115 notifyTimer->stop();
116
117// qDebug() << "Recorder state changed:" << ENUM_NAME(QMediaRecorder,"State",ps);
118 if (state != ps) {
119 emit q->stateChanged(state: ps);
120 }
121
122 state = ps;
123}
124
125
126void QMediaRecorderPrivate::_q_error(int error, const QString &errorString)
127{
128 Q_Q(QMediaRecorder);
129
130 this->error = QMediaRecorder::Error(error);
131 this->errorString = errorString;
132
133 emit q->error(error: this->error);
134}
135
136void QMediaRecorderPrivate::_q_serviceDestroyed()
137{
138 mediaObject = nullptr;
139 control = nullptr;
140 formatControl = nullptr;
141 audioControl = nullptr;
142 videoControl = nullptr;
143 metaDataControl = nullptr;
144 availabilityControl = nullptr;
145 settingsChanged = true;
146}
147
148void QMediaRecorderPrivate::_q_updateActualLocation(const QUrl &location)
149{
150 if (actualLocation != location) {
151 actualLocation = location;
152 emit q_func()->actualLocationChanged(location: actualLocation);
153 }
154}
155
156void QMediaRecorderPrivate::_q_notify()
157{
158 emit q_func()->durationChanged(duration: q_func()->duration());
159}
160
161void QMediaRecorderPrivate::_q_updateNotifyInterval(int ms)
162{
163 notifyTimer->setInterval(ms);
164}
165
166void QMediaRecorderPrivate::applySettingsLater()
167{
168 if (control && !settingsChanged) {
169 settingsChanged = true;
170 QMetaObject::invokeMethod(obj: q_func(), member: "_q_applySettings", type: Qt::QueuedConnection);
171 }
172}
173
174void QMediaRecorderPrivate::_q_applySettings()
175{
176 if (control && settingsChanged) {
177 settingsChanged = false;
178 control->applySettings();
179 }
180}
181
182void QMediaRecorderPrivate::_q_availabilityChanged(QMultimedia::AvailabilityStatus availability)
183{
184 Q_Q(QMediaRecorder);
185 Q_UNUSED(error)
186 Q_UNUSED(availability)
187
188 // Really this should not always emit, but
189 // we can't really tell from here (isAvailable
190 // may not have changed, or the mediaobject's overridden
191 // availability() may not have changed).
192 q->availabilityChanged(availability: q->availability());
193 q->availabilityChanged(available: q->isAvailable());
194}
195
196void QMediaRecorderPrivate::restartCamera()
197{
198 //restart camera if it can't apply new settings in the Active state
199 QCamera *camera = qobject_cast<QCamera*>(object: mediaObject);
200 if (camera && camera->captureMode() == QCamera::CaptureVideo) {
201 QMetaObject::invokeMethod(obj: camera,
202 member: "_q_preparePropertyChange",
203 type: Qt::DirectConnection,
204 Q_ARG(int, QCameraControl::VideoEncodingSettings));
205 }
206}
207
208
209/*!
210 Constructs a media recorder which records the media produced by \a mediaObject.
211
212 The \a parent is passed to QMediaObject.
213*/
214
215QMediaRecorder::QMediaRecorder(QMediaObject *mediaObject, QObject *parent):
216 QObject(parent),
217 d_ptr(new QMediaRecorderPrivate)
218{
219 Q_D(QMediaRecorder);
220 d->q_ptr = this;
221
222 d->notifyTimer = new QTimer(this);
223 connect(asender: d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify()));
224
225 setMediaObject(mediaObject);
226}
227
228/*!
229 \internal
230*/
231QMediaRecorder::QMediaRecorder(QMediaRecorderPrivate &dd, QMediaObject *mediaObject, QObject *parent):
232 QObject(parent),
233 d_ptr(&dd)
234{
235 Q_D(QMediaRecorder);
236 d->q_ptr = this;
237
238 d->notifyTimer = new QTimer(this);
239 connect(asender: d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify()));
240
241 setMediaObject(mediaObject);
242}
243
244/*!
245 Destroys a media recorder object.
246*/
247
248QMediaRecorder::~QMediaRecorder()
249{
250 delete d_ptr;
251}
252
253/*!
254 Returns the QMediaObject instance that this QMediaRecorder is bound too,
255 or 0 otherwise.
256*/
257QMediaObject *QMediaRecorder::mediaObject() const
258{
259 return d_func()->mediaObject;
260}
261
262/*!
263 \internal
264*/
265bool QMediaRecorder::setMediaObject(QMediaObject *object)
266{
267 Q_D(QMediaRecorder);
268
269 if (object == d->mediaObject)
270 return true;
271
272 if (d->mediaObject) {
273 if (d->control) {
274 disconnect(sender: d->control, SIGNAL(stateChanged(QMediaRecorder::State)),
275 receiver: this, SLOT(_q_stateChanged(QMediaRecorder::State)));
276
277 disconnect(sender: d->control, SIGNAL(statusChanged(QMediaRecorder::Status)),
278 receiver: this, SIGNAL(statusChanged(QMediaRecorder::Status)));
279
280 disconnect(sender: d->control, SIGNAL(mutedChanged(bool)),
281 receiver: this, SIGNAL(mutedChanged(bool)));
282
283 disconnect(sender: d->control, SIGNAL(volumeChanged(qreal)),
284 receiver: this, SIGNAL(volumeChanged(qreal)));
285
286 disconnect(sender: d->control, SIGNAL(durationChanged(qint64)),
287 receiver: this, SIGNAL(durationChanged(qint64)));
288
289 disconnect(sender: d->control, SIGNAL(actualLocationChanged(QUrl)),
290 receiver: this, SLOT(_q_updateActualLocation(QUrl)));
291
292 disconnect(sender: d->control, SIGNAL(error(int,QString)),
293 receiver: this, SLOT(_q_error(int,QString)));
294 }
295
296 disconnect(sender: d->mediaObject, SIGNAL(notifyIntervalChanged(int)), receiver: this, SLOT(_q_updateNotifyInterval(int)));
297
298 QMediaService *service = d->mediaObject->service();
299
300 if (service) {
301 disconnect(sender: service, SIGNAL(destroyed()), receiver: this, SLOT(_q_serviceDestroyed()));
302
303 if (d->control)
304 service->releaseControl(control: d->control);
305 if (d->formatControl)
306 service->releaseControl(control: d->formatControl);
307 if (d->audioControl)
308 service->releaseControl(control: d->audioControl);
309 if (d->videoControl)
310 service->releaseControl(control: d->videoControl);
311 if (d->metaDataControl) {
312 disconnect(sender: d->metaDataControl, SIGNAL(metaDataChanged()),
313 receiver: this, SIGNAL(metaDataChanged()));
314 disconnect(sender: d->metaDataControl, SIGNAL(metaDataChanged(QString,QVariant)),
315 receiver: this, SIGNAL(metaDataChanged(QString,QVariant)));
316 disconnect(sender: d->metaDataControl, SIGNAL(metaDataAvailableChanged(bool)),
317 receiver: this, SIGNAL(metaDataAvailableChanged(bool)));
318 disconnect(sender: d->metaDataControl, SIGNAL(writableChanged(bool)),
319 receiver: this, SIGNAL(metaDataWritableChanged(bool)));
320
321 service->releaseControl(control: d->metaDataControl);
322 }
323 if (d->availabilityControl) {
324 disconnect(sender: d->availabilityControl, SIGNAL(availabilityChanged(QMultimedia::AvailabilityStatus)),
325 receiver: this, SLOT(_q_availabilityChanged(QMultimedia::AvailabilityStatus)));
326 service->releaseControl(control: d->availabilityControl);
327 }
328 }
329 }
330
331 d->control = nullptr;
332 d->formatControl = nullptr;
333 d->audioControl = nullptr;
334 d->videoControl = nullptr;
335 d->metaDataControl = nullptr;
336 d->availabilityControl = nullptr;
337
338 d->mediaObject = object;
339
340 if (d->mediaObject) {
341 QMediaService *service = d->mediaObject->service();
342
343 d->notifyTimer->setInterval(d->mediaObject->notifyInterval());
344 connect(asender: d->mediaObject, SIGNAL(notifyIntervalChanged(int)), SLOT(_q_updateNotifyInterval(int)));
345
346 if (service) {
347 d->control = qobject_cast<QMediaRecorderControl*>(object: service->requestControl(QMediaRecorderControl_iid));
348
349 if (d->control) {
350 d->formatControl = qobject_cast<QMediaContainerControl *>(object: service->requestControl(QMediaContainerControl_iid));
351 d->audioControl = qobject_cast<QAudioEncoderSettingsControl *>(object: service->requestControl(QAudioEncoderSettingsControl_iid));
352 d->videoControl = qobject_cast<QVideoEncoderSettingsControl *>(object: service->requestControl(QVideoEncoderSettingsControl_iid));
353
354 QMediaControl *control = service->requestControl(QMetaDataWriterControl_iid);
355 if (control) {
356 d->metaDataControl = qobject_cast<QMetaDataWriterControl *>(object: control);
357 if (!d->metaDataControl) {
358 service->releaseControl(control);
359 } else {
360 connect(asender: d->metaDataControl,
361 SIGNAL(metaDataChanged()),
362 SIGNAL(metaDataChanged()));
363 connect(sender: d->metaDataControl, SIGNAL(metaDataChanged(QString,QVariant)),
364 receiver: this, SIGNAL(metaDataChanged(QString,QVariant)));
365 connect(asender: d->metaDataControl,
366 SIGNAL(metaDataAvailableChanged(bool)),
367 SIGNAL(metaDataAvailableChanged(bool)));
368 connect(asender: d->metaDataControl,
369 SIGNAL(writableChanged(bool)),
370 SIGNAL(metaDataWritableChanged(bool)));
371 }
372 }
373
374 d->availabilityControl = service->requestControl<QMediaAvailabilityControl*>();
375 if (d->availabilityControl) {
376 connect(sender: d->availabilityControl, SIGNAL(availabilityChanged(QMultimedia::AvailabilityStatus)),
377 receiver: this, SLOT(_q_availabilityChanged(QMultimedia::AvailabilityStatus)));
378 }
379
380 connect(sender: d->control, SIGNAL(stateChanged(QMediaRecorder::State)),
381 receiver: this, SLOT(_q_stateChanged(QMediaRecorder::State)));
382
383 connect(sender: d->control, SIGNAL(statusChanged(QMediaRecorder::Status)),
384 receiver: this, SIGNAL(statusChanged(QMediaRecorder::Status)));
385
386 connect(sender: d->control, SIGNAL(mutedChanged(bool)),
387 receiver: this, SIGNAL(mutedChanged(bool)));
388
389 connect(sender: d->control, SIGNAL(volumeChanged(qreal)),
390 receiver: this, SIGNAL(volumeChanged(qreal)));
391
392 connect(sender: d->control, SIGNAL(durationChanged(qint64)),
393 receiver: this, SIGNAL(durationChanged(qint64)));
394
395 connect(sender: d->control, SIGNAL(actualLocationChanged(QUrl)),
396 receiver: this, SLOT(_q_updateActualLocation(QUrl)));
397
398 connect(sender: d->control, SIGNAL(error(int,QString)),
399 receiver: this, SLOT(_q_error(int,QString)));
400
401 connect(sender: service, SIGNAL(destroyed()), receiver: this, SLOT(_q_serviceDestroyed()));
402
403
404 d->applySettingsLater();
405
406 return true;
407 }
408 }
409
410 d->mediaObject = nullptr;
411 return false;
412 }
413
414 return true;
415}
416
417/*!
418 \property QMediaRecorder::outputLocation
419 \brief the destination location of media content.
420
421 Setting the location can fail, for example when the service supports only
422 local file system locations but a network URL was passed. If the service
423 does not support media recording this setting the output location will
424 always fail.
425
426 The \a location can be relative or empty;
427 in this case the recorder uses the system specific place and file naming scheme.
428 After recording has stated, QMediaRecorder::outputLocation() returns the actual output location.
429*/
430
431/*!
432 \property QMediaRecorder::actualLocation
433 \brief the actual location of the last media content.
434
435 The actual location is usually available after recording starts,
436 and reset when new location is set or new recording starts.
437*/
438
439/*!
440 Returns true if media recorder service ready to use.
441
442 \sa availabilityChanged()
443*/
444bool QMediaRecorder::isAvailable() const
445{
446 return availability() == QMultimedia::Available;
447}
448
449/*!
450 Returns the availability of this functionality.
451
452 \sa availabilityChanged()
453*/
454QMultimedia::AvailabilityStatus QMediaRecorder::availability() const
455{
456 if (d_func()->control == nullptr)
457 return QMultimedia::ServiceMissing;
458
459 if (d_func()->availabilityControl)
460 return d_func()->availabilityControl->availability();
461
462 return QMultimedia::Available;
463}
464
465QUrl QMediaRecorder::outputLocation() const
466{
467 return d_func()->control ? d_func()->control->outputLocation() : QUrl();
468}
469
470bool QMediaRecorder::setOutputLocation(const QUrl &location)
471{
472 Q_D(QMediaRecorder);
473 d->actualLocation.clear();
474 return d->control ? d->control->setOutputLocation(location) : false;
475}
476
477QUrl QMediaRecorder::actualLocation() const
478{
479 return d_func()->actualLocation;
480}
481
482/*!
483 Returns the current media recorder state.
484
485 \sa QMediaRecorder::State
486*/
487
488QMediaRecorder::State QMediaRecorder::state() const
489{
490 return d_func()->control ? QMediaRecorder::State(d_func()->control->state()) : StoppedState;
491}
492
493/*!
494 Returns the current media recorder status.
495
496 \sa QMediaRecorder::Status
497*/
498
499QMediaRecorder::Status QMediaRecorder::status() const
500{
501 return d_func()->control ? QMediaRecorder::Status(d_func()->control->status()) : UnavailableStatus;
502}
503
504/*!
505 Returns the current error state.
506
507 \sa errorString()
508*/
509
510QMediaRecorder::Error QMediaRecorder::error() const
511{
512 return d_func()->error;
513}
514
515/*!
516 Returns a string describing the current error state.
517
518 \sa error()
519*/
520
521QString QMediaRecorder::errorString() const
522{
523 return d_func()->errorString;
524}
525
526/*!
527 \property QMediaRecorder::duration
528
529 \brief the recorded media duration in milliseconds.
530*/
531
532qint64 QMediaRecorder::duration() const
533{
534 return d_func()->control ? d_func()->control->duration() : 0;
535}
536
537/*!
538 \property QMediaRecorder::muted
539
540 \brief whether a recording audio stream is muted.
541*/
542
543bool QMediaRecorder::isMuted() const
544{
545 return d_func()->control ? d_func()->control->isMuted() : 0;
546}
547
548void QMediaRecorder::setMuted(bool muted)
549{
550 Q_D(QMediaRecorder);
551
552 if (d->control)
553 d->control->setMuted(muted);
554}
555
556/*!
557 \property QMediaRecorder::volume
558
559 \brief the current recording audio volume.
560
561 The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
562 range will be clamped.
563
564 The default volume is \c 1.0.
565
566 UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
567 will produce linear changes in perceived loudness, which is what a user would normally expect
568 from a volume control. See QAudio::convertVolume() for more details.
569*/
570
571qreal QMediaRecorder::volume() const
572{
573 return d_func()->control ? d_func()->control->volume() : 1.0;
574}
575
576
577void QMediaRecorder::setVolume(qreal volume)
578{
579 Q_D(QMediaRecorder);
580
581 if (d->control) {
582 volume = qMax(a: qreal(0.0), b: volume);
583 d->control->setVolume(volume);
584 }
585}
586
587/*!
588 Returns a list of supported container formats.
589*/
590QStringList QMediaRecorder::supportedContainers() const
591{
592 return d_func()->formatControl ?
593 d_func()->formatControl->supportedContainers() : QStringList();
594}
595
596/*!
597 Returns a description of a container \a format.
598*/
599QString QMediaRecorder::containerDescription(const QString &format) const
600{
601 return d_func()->formatControl ?
602 d_func()->formatControl->containerDescription(formatMimeType: format) : QString();
603}
604
605/*!
606 Returns the selected container format.
607*/
608
609QString QMediaRecorder::containerFormat() const
610{
611 return d_func()->formatControl ?
612 d_func()->formatControl->containerFormat() : QString();
613}
614
615/*!
616 Returns a list of supported audio codecs.
617*/
618QStringList QMediaRecorder::supportedAudioCodecs() const
619{
620 return d_func()->audioControl ?
621 d_func()->audioControl->supportedAudioCodecs() : QStringList();
622}
623
624/*!
625 Returns a description of an audio \a codec.
626*/
627QString QMediaRecorder::audioCodecDescription(const QString &codec) const
628{
629 return d_func()->audioControl ?
630 d_func()->audioControl->codecDescription(codecName: codec) : QString();
631}
632
633/*!
634 Returns a list of supported audio sample rates.
635
636 If non null audio \a settings parameter is passed, the returned list is
637 reduced to sample rates supported with partial settings applied.
638
639 This can be used to query the list of sample rates, supported by specific
640 audio codec.
641
642 If the encoder supports arbitrary sample rates within the supported rates
643 range, *\a continuous is set to true, otherwise *\a continuous is set to
644 false.
645*/
646
647QList<int> QMediaRecorder::supportedAudioSampleRates(const QAudioEncoderSettings &settings, bool *continuous) const
648{
649 if (continuous)
650 *continuous = false;
651
652 return d_func()->audioControl ?
653 d_func()->audioControl->supportedSampleRates(settings, continuous) : QList<int>();
654}
655
656/*!
657 Returns a list of resolutions video can be encoded at.
658
659 If non null video \a settings parameter is passed, the returned list is
660 reduced to resolution supported with partial settings like video codec or
661 framerate applied.
662
663 If the encoder supports arbitrary resolutions within the supported range,
664 *\a continuous is set to true, otherwise *\a continuous is set to false.
665
666 \sa QVideoEncoderSettings::resolution()
667*/
668QList<QSize> QMediaRecorder::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const
669{
670 if (continuous)
671 *continuous = false;
672
673 return d_func()->videoControl ?
674 d_func()->videoControl->supportedResolutions(settings, continuous) : QList<QSize>();
675}
676
677/*!
678 Returns a list of frame rates video can be encoded at.
679
680 If non null video \a settings parameter is passed, the returned list is
681 reduced to frame rates supported with partial settings like video codec or
682 resolution applied.
683
684 If the encoder supports arbitrary frame rates within the supported range,
685 *\a continuous is set to true, otherwise *\a continuous is set to false.
686
687 \sa QVideoEncoderSettings::frameRate()
688*/
689QList<qreal> QMediaRecorder::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const
690{
691 if (continuous)
692 *continuous = false;
693
694 return d_func()->videoControl ?
695 d_func()->videoControl->supportedFrameRates(settings, continuous) : QList<qreal>();
696}
697
698/*!
699 Returns a list of supported video codecs.
700*/
701QStringList QMediaRecorder::supportedVideoCodecs() const
702{
703 return d_func()->videoControl ?
704 d_func()->videoControl->supportedVideoCodecs() : QStringList();
705}
706
707/*!
708 Returns a description of a video \a codec.
709
710 \sa setEncodingSettings()
711*/
712QString QMediaRecorder::videoCodecDescription(const QString &codec) const
713{
714 return d_func()->videoControl ?
715 d_func()->videoControl->videoCodecDescription(codec) : QString();
716}
717
718/*!
719 Returns the audio encoder settings being used.
720
721 \sa setEncodingSettings()
722*/
723
724QAudioEncoderSettings QMediaRecorder::audioSettings() const
725{
726 return d_func()->audioControl ?
727 d_func()->audioControl->audioSettings() : QAudioEncoderSettings();
728}
729
730/*!
731 Returns the video encoder settings being used.
732
733 \sa setEncodingSettings()
734*/
735
736QVideoEncoderSettings QMediaRecorder::videoSettings() const
737{
738 return d_func()->videoControl ?
739 d_func()->videoControl->videoSettings() : QVideoEncoderSettings();
740}
741
742/*!
743 Sets the audio encoder \a settings.
744
745 If some parameters are not specified, or null settings are passed, the
746 encoder will choose default encoding parameters, depending on media
747 source properties.
748
749 It's only possible to change settings when the encoder is in the
750 QMediaEncoder::StoppedState state.
751
752 \sa audioSettings(), videoSettings(), containerFormat()
753*/
754
755void QMediaRecorder::setAudioSettings(const QAudioEncoderSettings &settings)
756{
757 Q_D(QMediaRecorder);
758
759 //restart camera if it can't apply new settings in the Active state
760 d->restartCamera();
761
762 if (d->audioControl) {
763 d->audioControl->setAudioSettings(settings);
764 d->applySettingsLater();
765 }
766}
767
768/*!
769 Sets the video encoder \a settings.
770
771 If some parameters are not specified, or null settings are passed, the
772 encoder will choose default encoding parameters, depending on media
773 source properties.
774
775 It's only possible to change settings when the encoder is in the
776 QMediaEncoder::StoppedState state.
777
778 \sa audioSettings(), videoSettings(), containerFormat()
779*/
780
781void QMediaRecorder::setVideoSettings(const QVideoEncoderSettings &settings)
782{
783 Q_D(QMediaRecorder);
784
785 d->restartCamera();
786
787 if (d->videoControl) {
788 d->videoControl->setVideoSettings(settings);
789 d->applySettingsLater();
790 }
791}
792
793/*!
794 Sets the media \a container format.
795
796 If the container format is not specified, the
797 encoder will choose format, depending on media source properties
798 and encoding settings selected.
799
800 It's only possible to change settings when the encoder is in the
801 QMediaEncoder::StoppedState state.
802
803 \sa audioSettings(), videoSettings(), containerFormat()
804*/
805
806void QMediaRecorder::setContainerFormat(const QString &container)
807{
808 Q_D(QMediaRecorder);
809
810 d->restartCamera();
811
812 if (d->formatControl) {
813 d->formatControl->setContainerFormat(container);
814 d->applySettingsLater();
815 }
816}
817
818/*!
819 Sets the \a audio and \a video encoder settings and \a container format.
820
821 If some parameters are not specified, or null settings are passed, the
822 encoder will choose default encoding parameters, depending on media
823 source properties.
824
825 It's only possible to change settings when the encoder is in the
826 QMediaEncoder::StoppedState state.
827
828 \sa audioSettings(), videoSettings(), containerFormat()
829*/
830
831void QMediaRecorder::setEncodingSettings(const QAudioEncoderSettings &audio,
832 const QVideoEncoderSettings &video,
833 const QString &container)
834{
835 Q_D(QMediaRecorder);
836
837 d->restartCamera();
838
839 if (d->audioControl)
840 d->audioControl->setAudioSettings(audio);
841
842 if (d->videoControl)
843 d->videoControl->setVideoSettings(video);
844
845 if (d->formatControl)
846 d->formatControl->setContainerFormat(container);
847
848 d->applySettingsLater();
849}
850
851/*!
852 Start recording.
853
854 While the recorder state is changed immediately to QMediaRecorder::RecordingState,
855 recording may start asynchronously, with statusChanged(QMediaRecorder::RecordingStatus)
856 signal emitted when recording starts.
857
858 If recording fails error() signal is emitted
859 with recorder state being reset back to QMediaRecorder::StoppedState.
860*/
861
862void QMediaRecorder::record()
863{
864 Q_D(QMediaRecorder);
865
866 d->actualLocation.clear();
867
868 if (d->settingsChanged)
869 d->_q_applySettings();
870
871 // reset error
872 d->error = NoError;
873 d->errorString = QString();
874
875 if (d->control)
876 d->control->setState(RecordingState);
877}
878
879/*!
880 Pause recording.
881
882 The recorder state is changed to QMediaRecorder::PausedState.
883
884 Depending on platform recording pause may be not supported,
885 in this case the recorder state stays unchanged.
886*/
887
888void QMediaRecorder::pause()
889{
890 Q_D(QMediaRecorder);
891 if (d->control)
892 d->control->setState(PausedState);
893}
894
895/*!
896 Stop recording.
897
898 The recorder state is changed to QMediaRecorder::StoppedState.
899*/
900
901void QMediaRecorder::stop()
902{
903 Q_D(QMediaRecorder);
904 if (d->control)
905 d->control->setState(StoppedState);
906}
907
908/*!
909 \enum QMediaRecorder::State
910
911 \value StoppedState The recorder is not active.
912 If this is the state after recording then the actual created recording has
913 finished being written to the final location and is ready on all platforms
914 except on Android. On Android, due to platform limitations, there is no way
915 to be certain that the recording has finished writing to the final location.
916 \value RecordingState The recording is requested.
917 \value PausedState The recorder is paused.
918*/
919
920/*!
921 \enum QMediaRecorder::Status
922
923 \value UnavailableStatus
924 The recorder is not available or not supported by connected media object.
925 \value UnloadedStatus
926 The recorder is avilable but not loaded.
927 \value LoadingStatus
928 The recorder is initializing.
929 \value LoadedStatus
930 The recorder is initialized and ready to record media.
931 \value StartingStatus
932 Recording is requested but not active yet.
933 \value RecordingStatus
934 Recording is active.
935 \value PausedStatus
936 Recording is paused.
937 \value FinalizingStatus
938 Recording is stopped with media being finalized.
939*/
940
941/*!
942 \enum QMediaRecorder::Error
943
944 \value NoError No Errors.
945 \value ResourceError Device is not ready or not available.
946 \value FormatError Current format is not supported.
947 \value OutOfSpaceError No space left on device.
948*/
949
950/*!
951 \property QMediaRecorder::state
952 \brief The current state of the media recorder.
953
954 The state property represents the user request and is changed synchronously
955 during record(), pause() or stop() calls.
956 Recorder state may also change asynchronously when recording fails.
957*/
958
959/*!
960 \property QMediaRecorder::status
961 \brief The current status of the media recorder.
962
963 The status is changed asynchronously and represents the actual status
964 of media recorder.
965*/
966
967/*!
968 \fn QMediaRecorder::stateChanged(State state)
969
970 Signals that a media recorder's \a state has changed.
971*/
972
973/*!
974 \fn QMediaRecorder::durationChanged(qint64 duration)
975
976 Signals that the \a duration of the recorded media has changed.
977*/
978
979/*!
980 \fn QMediaRecorder::actualLocationChanged(const QUrl &location)
981
982 Signals that the actual \a location of the recorded media has changed.
983 This signal is usually emitted when recording starts.
984*/
985
986/*!
987 \fn QMediaRecorder::error(QMediaRecorder::Error error)
988
989 Signals that an \a error has occurred.
990*/
991
992/*!
993 \fn QMediaRecorder::availabilityChanged(bool available)
994
995 Signals that the media recorder is now available (if \a available is true), or not.
996*/
997
998/*!
999 \fn QMediaRecorder::availabilityChanged(QMultimedia::AvailabilityStatus availability)
1000
1001 Signals that the service availability has changed to \a availability.
1002*/
1003
1004/*!
1005 \fn QMediaRecorder::mutedChanged(bool muted)
1006
1007 Signals that the \a muted state has changed. If true the recording is being muted.
1008*/
1009
1010/*!
1011 \property QMediaRecorder::metaDataAvailable
1012 \brief whether access to a media object's meta-data is available.
1013
1014 If this is true there is meta-data available, otherwise there is no meta-data available.
1015*/
1016
1017bool QMediaRecorder::isMetaDataAvailable() const
1018{
1019 Q_D(const QMediaRecorder);
1020
1021 return d->metaDataControl
1022 ? d->metaDataControl->isMetaDataAvailable()
1023 : false;
1024}
1025
1026/*!
1027 \fn QMediaRecorder::metaDataAvailableChanged(bool available)
1028
1029 Signals that the \a available state of a media object's meta-data has changed.
1030*/
1031
1032/*!
1033 \property QMediaRecorder::metaDataWritable
1034 \brief whether a media object's meta-data is writable.
1035
1036 If this is true the meta-data is writable, otherwise the meta-data is read-only.
1037*/
1038
1039bool QMediaRecorder::isMetaDataWritable() const
1040{
1041 Q_D(const QMediaRecorder);
1042
1043 return d->metaDataControl
1044 ? d->metaDataControl->isWritable()
1045 : false;
1046}
1047
1048/*!
1049 \fn QMediaRecorder::metaDataWritableChanged(bool writable)
1050
1051 Signals that the \a writable state of a media object's meta-data has changed.
1052*/
1053
1054/*!
1055 Returns the value associated with a meta-data \a key.
1056*/
1057QVariant QMediaRecorder::metaData(const QString &key) const
1058{
1059 Q_D(const QMediaRecorder);
1060
1061 return d->metaDataControl
1062 ? d->metaDataControl->metaData(key)
1063 : QVariant();
1064}
1065
1066/*!
1067 Sets a \a value for a meta-data \a key.
1068
1069 \note To ensure that meta data is set corretly, it should be set before starting the recording.
1070 Once the recording is stopped, any meta data set will be attached to the next recording.
1071*/
1072void QMediaRecorder::setMetaData(const QString &key, const QVariant &value)
1073{
1074 Q_D(QMediaRecorder);
1075
1076 if (d->metaDataControl)
1077 d->metaDataControl->setMetaData(key, value);
1078}
1079
1080/*!
1081 Returns a list of keys there is meta-data available for.
1082*/
1083QStringList QMediaRecorder::availableMetaData() const
1084{
1085 Q_D(const QMediaRecorder);
1086
1087 return d->metaDataControl
1088 ? d->metaDataControl->availableMetaData()
1089 : QStringList();
1090}
1091
1092/*!
1093 \fn QMediaRecorder::metaDataChanged()
1094
1095 Signals that a media object's meta-data has changed.
1096
1097 If multiple meta-data elements are changed,
1098 metaDataChanged(const QString &key, const QVariant &value) signal is emitted
1099 for each of them with metaDataChanged() changed emitted once.
1100*/
1101
1102/*!
1103 \fn QMediaRecorder::metaDataChanged(const QString &key, const QVariant &value)
1104
1105 Signal the changes of one meta-data element \a value with the given \a key.
1106*/
1107
1108QT_END_NAMESPACE
1109
1110#include "moc_qmediarecorder.cpp"
1111

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