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 plugins 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 "qdeclarativecamera_p.h"
41#include "qdeclarativecamerarecorder_p.h"
42
43#include <QtCore/qurl.h>
44
45QT_BEGIN_NAMESPACE
46
47/*!
48 \qmltype CameraRecorder
49 \instantiates QDeclarativeCameraRecorder
50 \inqmlmodule QtMultimedia
51 \brief Controls video recording with the Camera.
52 \ingroup multimedia_qml
53 \ingroup camera_qml
54
55 CameraRecorder allows recording camera streams to files, and adjusting recording
56 settings and metadata for videos.
57
58 It should not be constructed separately, instead the
59 \c videoRecorder property of a \l Camera should be used.
60
61 \qml
62 Camera {
63 videoRecorder.audioEncodingMode: CameraRecorder.ConstantBitrateEncoding;
64 videoRecorder.audioBitRate: 128000
65 videoRecorder.mediaContainer: "mp4"
66 // ...
67 }
68 \endqml
69
70 There are many different settings for each part of the recording process (audio,
71 video, and output formats), as well as control over muting and where to store
72 the output file.
73
74 \sa QAudioEncoderSettings, QVideoEncoderSettings
75*/
76
77QDeclarativeCameraRecorder::QDeclarativeCameraRecorder(QCamera *camera, QObject *parent) :
78 QObject(parent)
79{
80 m_recorder = new QMediaRecorder(camera, this);
81 connect(asender: m_recorder, SIGNAL(stateChanged(QMediaRecorder::State)),
82 SLOT(updateRecorderState(QMediaRecorder::State)));
83 connect(asender: m_recorder, SIGNAL(statusChanged(QMediaRecorder::Status)),
84 SIGNAL(recorderStatusChanged()));
85 connect(asender: m_recorder, SIGNAL(error(QMediaRecorder::Error)),
86 SLOT(updateRecorderError(QMediaRecorder::Error)));
87 connect(asender: m_recorder, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged(bool)));
88 connect(asender: m_recorder, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64)));
89 connect(asender: m_recorder, SIGNAL(actualLocationChanged(QUrl)),
90 SLOT(updateActualLocation(QUrl)));
91 connect(asender: m_recorder, SIGNAL(metaDataChanged(QString,QVariant)),
92 SIGNAL(metaDataChanged(QString,QVariant)));
93}
94
95QDeclarativeCameraRecorder::~QDeclarativeCameraRecorder()
96{
97}
98
99/*!
100 \qmlproperty size QtMultimedia::CameraRecorder::resolution
101
102 This property holds the video frame dimensions to be used for video capture.
103*/
104QSize QDeclarativeCameraRecorder::captureResolution()
105{
106 return m_videoSettings.resolution();
107}
108
109/*!
110 \qmlproperty string QtMultimedia::CameraRecorder::audioCodec
111
112 This property holds the audio codec to be used for recording video.
113 Typically this is \c aac or \c amr-wb.
114
115 \sa {QtMultimedia::CameraImageProcessing::whiteBalanceMode}{whileBalanceMode}
116*/
117QString QDeclarativeCameraRecorder::audioCodec() const
118{
119 return m_audioSettings.codec();
120}
121
122/*!
123 \qmlproperty string QtMultimedia::CameraRecorder::videoCodec
124
125 This property holds the video codec to be used for recording video.
126 Typically this is \c h264.
127*/
128QString QDeclarativeCameraRecorder::videoCodec() const
129{
130 return m_videoSettings.codec();
131}
132
133/*!
134 \qmlproperty string QtMultimedia::CameraRecorder::mediaContainer
135
136 This property holds the media container to be used for recording video.
137 Typically this is \c mp4.
138*/
139QString QDeclarativeCameraRecorder::mediaContainer() const
140{
141 return m_mediaContainer;
142}
143
144void QDeclarativeCameraRecorder::setCaptureResolution(const QSize &resolution)
145{
146 m_videoSettings = m_recorder->videoSettings();
147 if (resolution != captureResolution()) {
148 m_videoSettings.setResolution(resolution);
149 m_recorder->setVideoSettings(m_videoSettings);
150 emit captureResolutionChanged(resolution);
151 }
152}
153
154void QDeclarativeCameraRecorder::setAudioCodec(const QString &codec)
155{
156 m_audioSettings = m_recorder->audioSettings();
157 if (codec != audioCodec()) {
158 m_audioSettings.setCodec(codec);
159 m_recorder->setAudioSettings(m_audioSettings);
160 emit audioCodecChanged(codec);
161 }
162}
163
164void QDeclarativeCameraRecorder::setVideoCodec(const QString &codec)
165{
166 m_videoSettings = m_recorder->videoSettings();
167 if (codec != videoCodec()) {
168 m_videoSettings.setCodec(codec);
169 m_recorder->setVideoSettings(m_videoSettings);
170 emit videoCodecChanged(codec);
171 }
172}
173
174void QDeclarativeCameraRecorder::setMediaContainer(const QString &container)
175{
176 if (container != m_mediaContainer) {
177 m_mediaContainer = container;
178 m_recorder->setContainerFormat(container);
179 emit mediaContainerChanged(container);
180 }
181}
182
183/*!
184 \qmlproperty qreal QtMultimedia::CameraRecorder::frameRate
185
186 This property holds the framerate (in frames per second) to be used for recording video.
187*/
188qreal QDeclarativeCameraRecorder::frameRate() const
189{
190 return m_videoSettings.frameRate();
191}
192
193/*!
194 \qmlproperty int QtMultimedia::CameraRecorder::videoBitRate
195
196 This property holds the bit rate (in bits per second) to be used for recording video.
197*/
198int QDeclarativeCameraRecorder::videoBitRate() const
199{
200 return m_videoSettings.bitRate();
201}
202
203/*!
204 \qmlproperty int QtMultimedia::CameraRecorder::audioBitRate
205
206 This property holds the audio bit rate (in bits per second) to be used for recording video.
207*/
208int QDeclarativeCameraRecorder::audioBitRate() const
209{
210 return m_audioSettings.bitRate();
211}
212
213/*!
214 \qmlproperty int QtMultimedia::CameraRecorder::audioChannels
215
216 This property indicates the number of audio channels to be encoded while
217 recording video (1 is mono, 2 is stereo).
218*/
219int QDeclarativeCameraRecorder::audioChannels() const
220{
221 return m_audioSettings.channelCount();
222}
223
224/*!
225 \qmlproperty int QtMultimedia::CameraRecorder::audioSampleRate
226
227 This property holds the sample rate to be used to encode audio while recording video.
228*/
229int QDeclarativeCameraRecorder::audioSampleRate() const
230{
231 return m_audioSettings.sampleRate();
232}
233
234/*!
235 \qmlproperty enumeration QtMultimedia::CameraRecorder::videoEncodingMode
236
237 This property holds the type of encoding method to be used for recording video.
238
239 The following are the different encoding methods used:
240
241 \table
242 \header \li Value \li Description
243 \row \li ConstantQualityEncoding
244 \li Encoding will aim to have a constant quality, adjusting bitrate to fit.
245 This is the default. The bitrate setting will be ignored.
246 \row \li ConstantBitRateEncoding
247 \li Encoding will use a constant bit rate, adjust quality to fit. This is
248 appropriate if you are trying to optimize for space.
249 \row \li AverageBitRateEncoding
250 \li Encoding will try to keep an average bitrate setting, but will use
251 more or less as needed.
252 \endtable
253
254*/
255QDeclarativeCameraRecorder::EncodingMode QDeclarativeCameraRecorder::videoEncodingMode() const
256{
257 return EncodingMode(m_videoSettings.encodingMode());
258}
259
260/*!
261 \qmlproperty enumeration QtMultimedia::CameraRecorder::audioEncodingMode
262
263 The type of encoding method to use when recording audio.
264
265 \table
266 \header \li Value \li Description
267 \row \li ConstantQualityEncoding
268 \li Encoding will aim to have a constant quality, adjusting bitrate to fit.
269 This is the default. The bitrate setting will be ignored.
270 \row \li ConstantBitRateEncoding
271 \li Encoding will use a constant bit rate, adjust quality to fit. This is
272 appropriate if you are trying to optimize for space.
273 \row \li AverageBitRateEncoding
274 \li Encoding will try to keep an average bitrate setting, but will use
275 more or less as needed.
276 \endtable
277*/
278QDeclarativeCameraRecorder::EncodingMode QDeclarativeCameraRecorder::audioEncodingMode() const
279{
280 return EncodingMode(m_audioSettings.encodingMode());
281}
282
283void QDeclarativeCameraRecorder::setFrameRate(qreal frameRate)
284{
285 m_videoSettings = m_recorder->videoSettings();
286 if (!qFuzzyCompare(p1: m_videoSettings.frameRate(),p2: frameRate)) {
287 m_videoSettings.setFrameRate(frameRate);
288 m_recorder->setVideoSettings(m_videoSettings);
289 emit frameRateChanged(arg: frameRate);
290 }
291}
292
293void QDeclarativeCameraRecorder::setVideoBitRate(int rate)
294{
295 m_videoSettings = m_recorder->videoSettings();
296 if (m_videoSettings.bitRate() != rate) {
297 m_videoSettings.setBitRate(rate);
298 m_recorder->setVideoSettings(m_videoSettings);
299 emit videoBitRateChanged(arg: rate);
300 }
301}
302
303void QDeclarativeCameraRecorder::setAudioBitRate(int rate)
304{
305 m_audioSettings = m_recorder->audioSettings();
306 if (m_audioSettings.bitRate() != rate) {
307 m_audioSettings.setBitRate(rate);
308 m_recorder->setAudioSettings(m_audioSettings);
309 emit audioBitRateChanged(arg: rate);
310 }
311}
312
313void QDeclarativeCameraRecorder::setAudioChannels(int channels)
314{
315 m_audioSettings = m_recorder->audioSettings();
316 if (m_audioSettings.channelCount() != channels) {
317 m_audioSettings.setChannelCount(channels);
318 m_recorder->setAudioSettings(m_audioSettings);
319 emit audioChannelsChanged(arg: channels);
320 }
321}
322
323void QDeclarativeCameraRecorder::setAudioSampleRate(int rate)
324{
325 m_audioSettings = m_recorder->audioSettings();
326 if (m_audioSettings.sampleRate() != rate) {
327 m_audioSettings.setSampleRate(rate);
328 m_recorder->setAudioSettings(m_audioSettings);
329 emit audioSampleRateChanged(arg: rate);
330 }
331}
332
333void QDeclarativeCameraRecorder::setAudioEncodingMode(QDeclarativeCameraRecorder::EncodingMode encodingMode)
334{
335 m_audioSettings = m_recorder->audioSettings();
336 if (m_audioSettings.encodingMode() != QMultimedia::EncodingMode(encodingMode)) {
337 m_audioSettings.setEncodingMode(QMultimedia::EncodingMode(encodingMode));
338 m_recorder->setAudioSettings(m_audioSettings);
339 emit audioEncodingModeChanged(encodingMode);
340 }
341}
342
343void QDeclarativeCameraRecorder::setVideoEncodingMode(QDeclarativeCameraRecorder::EncodingMode encodingMode)
344{
345 m_videoSettings = m_recorder->videoSettings();
346 if (m_videoSettings.encodingMode() != QMultimedia::EncodingMode(encodingMode)) {
347 m_videoSettings.setEncodingMode(QMultimedia::EncodingMode(encodingMode));
348 m_recorder->setVideoSettings(m_videoSettings);
349 emit videoEncodingModeChanged(encodingMode);
350 }
351}
352
353/*!
354 \qmlproperty enumeration QtMultimedia::CameraRecorder::errorCode
355
356 This property holds the last error code.
357
358 \table
359 \header \li Value \li Description
360 \row \li NoError
361 \li No Errors
362
363 \row \li ResourceError
364 \li Device is not ready or not available.
365
366 \row \li FormatError
367 \li Current format is not supported.
368
369 \row \li OutOfSpaceError
370 \li No space left on device.
371
372 \endtable
373*/
374QDeclarativeCameraRecorder::Error QDeclarativeCameraRecorder::errorCode() const
375{
376 return QDeclarativeCameraRecorder::Error(m_recorder->error());
377}
378
379/*!
380 \qmlproperty string QtMultimedia::CameraRecorder::errorString
381
382 This property holds the description of the last error.
383*/
384QString QDeclarativeCameraRecorder::errorString() const
385{
386 return m_recorder->errorString();
387}
388
389/*!
390 \qmlproperty enumeration QtMultimedia::CameraRecorder::recorderState
391
392 This property holds the current state of the camera recorder object.
393
394 The state can be one of these two:
395
396 \table
397 \header \li Value \li Description
398 \row \li StoppedState
399 \li The camera is not recording video.
400
401 \row \li RecordingState
402 \li The camera is recording video.
403 \endtable
404*/
405QDeclarativeCameraRecorder::RecorderState QDeclarativeCameraRecorder::recorderState() const
406{
407 //paused state is not supported for camera
408 QMediaRecorder::State state = m_recorder->state();
409
410 if (state == QMediaRecorder::PausedState)
411 state = QMediaRecorder::StoppedState;
412
413 return RecorderState(state);
414}
415
416
417/*!
418 \qmlproperty enumeration QtMultimedia::CameraRecorder::recorderStatus
419
420 This property holds the current status of media recording.
421
422 \table
423 \header \li Value \li Description
424 \row \li UnavailableStatus
425 \li Recording is not supported by the camera.
426 \row \li UnloadedStatus
427 \li The recorder is available but not loaded.
428 \row \li LoadingStatus
429 \li The recorder is initializing.
430 \row \li LoadedStatus
431 \li The recorder is initialized and ready to record media.
432 \row \li StartingStatus
433 \li Recording is requested but not active yet.
434 \row \li RecordingStatus
435 \li Recording is active.
436 \row \li PausedStatus
437 \li Recording is paused.
438 \row \li FinalizingStatus
439 \li Recording is stopped with media being finalized.
440 \endtable
441*/
442
443QDeclarativeCameraRecorder::RecorderStatus QDeclarativeCameraRecorder::recorderStatus() const
444{
445 return RecorderStatus(m_recorder->status());
446}
447
448/*!
449 \qmlmethod QtMultimedia::CameraRecorder::record()
450
451 Starts recording.
452*/
453void QDeclarativeCameraRecorder::record()
454{
455 setRecorderState(RecordingState);
456}
457
458/*!
459 \qmlmethod QtMultimedia::CameraRecorder::stop()
460
461 Stops recording.
462*/
463void QDeclarativeCameraRecorder::stop()
464{
465 setRecorderState(StoppedState);
466}
467
468void QDeclarativeCameraRecorder::setRecorderState(QDeclarativeCameraRecorder::RecorderState state)
469{
470 if (!m_recorder)
471 return;
472
473 switch (state) {
474 case QDeclarativeCameraRecorder::RecordingState:
475 m_recorder->record();
476 break;
477 case QDeclarativeCameraRecorder::StoppedState:
478 m_recorder->stop();
479 break;
480 }
481}
482/*!
483 \property QDeclarativeCameraRecorder::outputLocation
484
485 This property holds the destination location of the media content. If it is empty,
486 the recorder uses the system-specific place and file naming scheme.
487*/
488/*!
489 \qmlproperty string QtMultimedia::CameraRecorder::outputLocation
490
491 This property holds the destination location of the media content. If the location is empty,
492 the recorder uses the system-specific place and file naming scheme.
493*/
494
495QString QDeclarativeCameraRecorder::outputLocation() const
496{
497 return m_recorder->outputLocation().toString();
498}
499/*!
500 \property QDeclarativeCameraRecorder::actualLocation
501
502 This property holds the absolute location to the last saved media content.
503 The location is usually available after recording starts, and reset when
504 new location is set or new recording starts.
505*/
506/*!
507 \qmlproperty string QtMultimedia::CameraRecorder::actualLocation
508
509 This property holds the actual location of the last saved media content. The actual location is
510 usually available after the recording starts, and reset when new location is set or the new recording starts.
511*/
512
513QString QDeclarativeCameraRecorder::actualLocation() const
514{
515 return m_recorder->actualLocation().toString();
516}
517
518void QDeclarativeCameraRecorder::setOutputLocation(const QString &location)
519{
520 if (outputLocation() != location) {
521 m_recorder->setOutputLocation(location);
522 emit outputLocationChanged(location: outputLocation());
523 }
524}
525/*!
526 \property QDeclarativeCameraRecorder::duration
527
528 This property holds the duration (in miliseconds) of the last recording.
529*/
530/*!
531 \qmlproperty int QtMultimedia::CameraRecorder::duration
532
533 This property holds the duration (in miliseconds) of the last recording.
534*/
535qint64 QDeclarativeCameraRecorder::duration() const
536{
537 return m_recorder->duration();
538}
539/*!
540 \property QDeclarativeCameraRecorder::muted
541
542 This property indicates whether the audio input is muted during
543 recording.
544*/
545/*!
546 \qmlproperty bool QtMultimedia::CameraRecorder::muted
547
548 This property indicates whether the audio input is muted during recording.
549*/
550bool QDeclarativeCameraRecorder::isMuted() const
551{
552 return m_recorder->isMuted();
553}
554
555void QDeclarativeCameraRecorder::setMuted(bool muted)
556{
557 m_recorder->setMuted(muted);
558}
559
560/*!
561 \qmlmethod QtMultimedia::CameraRecorder::setMetadata(key, value)
562
563 Sets metadata for the next video to be recorder, with
564 the given \a key being associated with \a value.
565*/
566void QDeclarativeCameraRecorder::setMetadata(const QString &key, const QVariant &value)
567{
568 m_recorder->setMetaData(key, value);
569}
570
571void QDeclarativeCameraRecorder::updateRecorderState(QMediaRecorder::State state)
572{
573 if (state == QMediaRecorder::PausedState)
574 state = QMediaRecorder::StoppedState;
575
576 emit recorderStateChanged(state: RecorderState(state));
577}
578
579void QDeclarativeCameraRecorder::updateRecorderError(QMediaRecorder::Error errorCode)
580{
581 qWarning() << "QMediaRecorder error:" << errorString();
582 emit error(errorCode: Error(errorCode), errorString: errorString());
583}
584
585void QDeclarativeCameraRecorder::updateActualLocation(const QUrl &url)
586{
587 emit actualLocationChanged(location: url.toString());
588}
589
590QT_END_NAMESPACE
591
592#include "moc_qdeclarativecamerarecorder_p.cpp"
593

source code of qtmultimedia/src/imports/multimedia/qdeclarativecamerarecorder.cpp