Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmediacapturesession.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 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
6#include "qaudiodevice.h"
7#include "qcamera.h"
10#include "qvideosink.h"
11#include "qscreencapture.h"
12#include "qwindowcapture.h"
14
17#include "qaudioinput.h"
19#include "qaudiooutput.h"
20
22
24{
25 Q_Q(QMediaCaptureSession);
26
27 if (sink == videoSink)
28 return;
29 if (videoSink)
30 videoSink->setSource(nullptr);
31 videoSink = sink;
32 if (sink)
33 sink->setSource(q);
34 if (captureSession)
35 captureSession->setVideoPreview(sink);
36 emit q->videoOutputChanged();
37}
38
39/*!
40 \class QMediaCaptureSession
41
42 \brief The QMediaCaptureSession class allows capturing of audio and video content.
43 \inmodule QtMultimedia
44 \ingroup multimedia
45 \ingroup multimedia_video
46 \ingroup multimedia_audio
47
48 The QMediaCaptureSession is the central class that manages capturing of media on the local
49 device.
50
51 You can connect a video input to QMediaCaptureSession using setCamera(),
52 setScreenCapture(), setWindowCapture() or setVideoFrameInput().
53 A preview of the captured media can be seen by setting a QVideoWidget or QGraphicsVideoItem
54 using setVideoOutput().
55
56 You can connect a microphone to QMediaCaptureSession using setAudioInput(), or set your
57 custom audio input using setAudioBufferInput().
58 The captured sound can be heard by routing the audio to an output device using setAudioOutput().
59
60 You can capture still images from a camera by setting a QImageCapture object on the capture
61 session, and record audio/video using a QMediaRecorder.
62
63 \sa QCamera, QAudioDevice, QMediaRecorder, QImageCapture, QScreenCapture, QWindowCapture,
64 QVideoFrameInput, QMediaRecorder, QGraphicsVideoItem
65*/
66
67/*!
68 \qmltype CaptureSession
69 \since 6.2
70 \nativetype QMediaCaptureSession
71 \brief Allows capturing of audio and video content.
72
73 \inqmlmodule QtMultimedia
74 \ingroup multimedia_qml
75 \ingroup multimedia_audio_qml
76 \ingroup multimedia_video_qml
77
78 This is the central type that manages capturing of media on the local device.
79
80 Connect a camera and a microphone to a CaptureSession by assigning Camera
81 and AudioInput objects to the relevant properties.
82
83 Capture a screen by connecting a ScreenCapture object to
84 the screenCapture property.
85
86 Capture a window by connecting a WindowCapture object to
87 the windowCapture property.
88
89 Enable a preview of the captured media by assigning a VideoOutput element to
90 the videoOutput property.
91
92 Route audio to an output device by assigning an AudioOutput object
93 to the audioOutput property.
94
95 Capture still images from a camera by assigning an ImageCapture to the
96 imageCapture property.
97
98 Record audio/video by assigning a MediaRecorder to the recorder property.
99
100\qml
101 CaptureSession {
102 id: captureSession
103 camera: Camera {
104 id: camera
105 }
106 imageCapture: ImageCapture {
107 id: imageCapture
108 }
109
110 recorder: MediaRecorder {
111 id: recorder
112 }
113 videoOutput: preview
114
115 Component.onCompleted: {
116 camera.start()
117 }
118 }
119\endqml
120
121 \sa Camera, MediaDevices, MediaRecorder, ImageCapture, ScreenCapture, WindowCapture, AudioInput, VideoOutput
122 \note To ensure the camera starts capturing video frames on all platforms, explicitly call camera.start(),
123 typically in the Component.onCompleted handler.
124*/
125
126/*!
127 Creates a session for media capture from the \a parent object.
128 */
129QMediaCaptureSession::QMediaCaptureSession(QObject *parent)
130 : QObject{ *new QMediaCaptureSessionPrivate, parent }
131{
132 Q_D(QMediaCaptureSession);
133
134 auto maybeCaptureSession = QPlatformMediaIntegration::instance()->createCaptureSession();
135 if (maybeCaptureSession) {
136 d->captureSession.reset(maybeCaptureSession.value());
137 d->captureSession->setCaptureSession(this);
138 } else {
139 qWarning() << "Failed to initialize QMediaCaptureSession" << maybeCaptureSession.error();
140 }
141}
142
143/*!
144 Destroys the session.
145 */
146QMediaCaptureSession::~QMediaCaptureSession()
147{
148 Q_D(QMediaCaptureSession);
149
150 setCamera(nullptr);
151 setRecorder(nullptr);
152 setImageCapture(nullptr);
153 setScreenCapture(nullptr);
154 setWindowCapture(nullptr);
155 setVideoFrameInput(nullptr);
156 setAudioBufferInput(nullptr);
157 setAudioInput(nullptr);
158 setAudioOutput(nullptr);
159 d->setVideoSink(nullptr);
160 d->captureSession.reset();
161}
162/*!
163 \qmlproperty AudioInput QtMultimedia::CaptureSession::audioInput
164
165 This property holds the audio input that is being used to capture audio.
166*/
167
168/*!
169 \property QMediaCaptureSession::audioInput
170
171 Returns the device that is being used to capture audio.
172*/
173QAudioInput *QMediaCaptureSession::audioInput() const
174{
175 Q_D(const QMediaCaptureSession);
176 return d->audioInput;
177}
178
179/*!
180 Sets the audio input device to \a input. If setting it to an empty
181 QAudioDevice the capture session will use the default input as
182 defined by the operating system.
183*/
184void QMediaCaptureSession::setAudioInput(QAudioInput *input)
185{
186 Q_D(QMediaCaptureSession);
187
188 QAudioInput *oldInput = d->audioInput;
189 if (oldInput == input)
190 return;
191
192 // To avoid double emit of audioInputChanged
193 // from recursive setAudioInput(nullptr) call.
194 d->audioInput = nullptr;
195
196 if (d->captureSession)
197 d->captureSession->setAudioInput(nullptr);
198 if (oldInput)
199 oldInput->setDisconnectFunction({});
200 if (input) {
201 input->setDisconnectFunction([this](){ setAudioInput(nullptr); });
202 if (d->captureSession)
203 d->captureSession->setAudioInput(input->handle());
204 }
205 d->audioInput = input;
206 emit audioInputChanged();
207}
208
209/*!
210 \property QMediaCaptureSession::audioBufferInput
211 \since 6.8
212
213 \brief The object used to send custom audio buffers to \l QMediaRecorder.
214*/
215QAudioBufferInput *QMediaCaptureSession::audioBufferInput() const
216{
217 Q_D(const QMediaCaptureSession);
218
219 return d->audioBufferInput;
220}
221
222void QMediaCaptureSession::setAudioBufferInput(QAudioBufferInput *input)
223{
224 Q_D(QMediaCaptureSession);
225
226 // TODO: come up with an unification of the captures setup
227 QAudioBufferInput *oldInput = d->audioBufferInput;
228 if (oldInput == input)
229 return;
230 d->audioBufferInput = input;
231 if (d->captureSession)
232 d->captureSession->setAudioBufferInput(nullptr);
233 if (oldInput) {
234 if (oldInput->captureSession() && oldInput->captureSession() != this)
235 oldInput->captureSession()->setAudioBufferInput(nullptr);
236 oldInput->setCaptureSession(nullptr);
237 }
238 if (input) {
239 if (input->captureSession())
240 input->captureSession()->setAudioBufferInput(nullptr);
241 if (d->captureSession)
242 d->captureSession->setAudioBufferInput(input->platformAudioBufferInput());
243 input->setCaptureSession(this);
244 }
245 emit audioBufferInputChanged();
246}
247
248/*!
249 \qmlproperty Camera QtMultimedia::CaptureSession::camera
250
251 \brief The camera used to capture video.
252
253 Record video or take images by adding a camera to the capture session using
254 this property.
255*/
256
257/*!
258 \property QMediaCaptureSession::camera
259
260 \brief The camera used to capture video.
261
262 Record video or take images by adding a camera to the capture session
263 using this property.
264*/
265QCamera *QMediaCaptureSession::camera() const
266{
267 Q_D(const QMediaCaptureSession);
268
269 return d->camera;
270}
271
272void QMediaCaptureSession::setCamera(QCamera *camera)
273{
274 Q_D(QMediaCaptureSession);
275
276 // TODO: come up with an unification of the captures setup
277 QCamera *oldCamera = d->camera;
278 if (oldCamera == camera)
279 return;
280
281 if (oldCamera
282 && !QPlatformMediaIntegration::instance()->isCameraSwitchingDuringRecordingSupported()
283 && recorder() && recorder()->recorderState() == QMediaRecorder::RecordingState) {
284 qWarning("This media backend does not support camera switching during recording");
285 return;
286 }
287
288 d->camera = camera;
289 if (d->captureSession)
290 d->captureSession->setCamera(nullptr);
291 if (oldCamera) {
292 if (oldCamera->captureSession() && oldCamera->captureSession() != this)
293 oldCamera->captureSession()->setCamera(nullptr);
294 oldCamera->setCaptureSession(nullptr);
295 }
296 if (camera) {
297 if (camera->captureSession())
298 camera->captureSession()->setCamera(nullptr);
299 if (d->captureSession)
300 d->captureSession->setCamera(camera->platformCamera());
301 camera->setCaptureSession(this);
302 }
303 emit cameraChanged();
304}
305
306/*!
307 \qmlproperty ScreenCapture QtMultimedia::CaptureSession::screenCapture
308 \since 6.5
309
310 \brief The object used to capture a screen.
311
312 Record a screen by adding a screen capture objet
313 to the capture session using this property.
314*/
315
316/*!
317 \property QMediaCaptureSession::screenCapture
318 \since 6.5
319
320 \brief The object used to capture a screen.
321
322 Record a screen by adding a screen capture object
323 to the capture session using this property.
324*/
325QScreenCapture *QMediaCaptureSession::screenCapture()
326{
327 Q_D(QMediaCaptureSession);
328
329 return d->screenCapture;
330}
331
332void QMediaCaptureSession::setScreenCapture(QScreenCapture *screenCapture)
333{
334 Q_D(QMediaCaptureSession);
335
336 // TODO: come up with an unification of the captures setup
337 QScreenCapture *oldScreenCapture = d->screenCapture;
338 if (oldScreenCapture == screenCapture)
339 return;
340 d->screenCapture = screenCapture;
341 if (d->captureSession)
342 d->captureSession->setScreenCapture(nullptr);
343 if (oldScreenCapture) {
344 if (oldScreenCapture->captureSession() && oldScreenCapture->captureSession() != this)
345 oldScreenCapture->captureSession()->setScreenCapture(nullptr);
346 oldScreenCapture->setCaptureSession(nullptr);
347 }
348 if (screenCapture) {
349 if (screenCapture->captureSession())
350 screenCapture->captureSession()->setScreenCapture(nullptr);
351 if (d->captureSession)
352 d->captureSession->setScreenCapture(screenCapture->platformScreenCapture());
353 screenCapture->setCaptureSession(this);
354 }
355 emit screenCaptureChanged();
356}
357
358/*!
359 \qmlproperty WindowCapture QtMultimedia::CaptureSession::windowCapture
360 \since 6.6
361
362 \brief The object used to capture a window.
363
364 Record a window by adding a window capture object
365 to the capture session using this property.
366*/
367
368/*!
369 \property QMediaCaptureSession::windowCapture
370 \since 6.6
371
372 \brief The object used to capture a window.
373
374 Record a window by adding a window capture objet
375 to the capture session using this property.
376*/
377QWindowCapture *QMediaCaptureSession::windowCapture()
378{
379 Q_D(QMediaCaptureSession);
380 return d->windowCapture;
381}
382
383void QMediaCaptureSession::setWindowCapture(QWindowCapture *windowCapture)
384{
385 Q_D(QMediaCaptureSession);
386
387 // TODO: come up with an unification of the captures setup
388 QWindowCapture *oldCapture = d->windowCapture;
389 if (oldCapture == windowCapture)
390 return;
391 d->windowCapture = windowCapture;
392 if (d->captureSession)
393 d->captureSession->setWindowCapture(nullptr);
394 if (oldCapture) {
395 if (oldCapture->captureSession() && oldCapture->captureSession() != this)
396 oldCapture->captureSession()->setWindowCapture(nullptr);
397 oldCapture->setCaptureSession(nullptr);
398 }
399 if (windowCapture) {
400 if (windowCapture->captureSession())
401 windowCapture->captureSession()->setWindowCapture(nullptr);
402 if (d->captureSession)
403 d->captureSession->setWindowCapture(windowCapture->platformWindowCapture());
404 windowCapture->setCaptureSession(this);
405 }
406 emit windowCaptureChanged();
407}
408
409/*!
410 \property QMediaCaptureSession::videoFrameInput
411 \since 6.8
412
413 \brief The object used to send custom video frames to
414 \l QMediaRecorder or a video output.
415*/
416QVideoFrameInput *QMediaCaptureSession::videoFrameInput() const
417{
418 Q_D(const QMediaCaptureSession);
419 return d->videoFrameInput;
420}
421
422void QMediaCaptureSession::setVideoFrameInput(QVideoFrameInput *input)
423{
424 Q_D(QMediaCaptureSession);
425 // TODO: come up with an unification of the captures setup
426 QVideoFrameInput *oldInput = d->videoFrameInput;
427 if (oldInput == input)
428 return;
429 d->videoFrameInput = input;
430 if (d->captureSession)
431 d->captureSession->setVideoFrameInput(nullptr);
432 if (oldInput) {
433 if (oldInput->captureSession() && oldInput->captureSession() != this)
434 oldInput->captureSession()->setVideoFrameInput(nullptr);
435 oldInput->setCaptureSession(nullptr);
436 }
437 if (input) {
438 if (input->captureSession())
439 input->captureSession()->setVideoFrameInput(nullptr);
440 if (d->captureSession)
441 d->captureSession->setVideoFrameInput(input->platformVideoFrameInput());
442 input->setCaptureSession(this);
443 }
444 emit videoFrameInputChanged();
445}
446
447/*!
448 \qmlproperty ImageCapture QtMultimedia::CaptureSession::imageCapture
449
450 \brief The object used to capture still images.
451
452 Add an ImageCapture interface to the capture session to enable
453 capturing of still images from the camera.
454*/
455/*!
456 \property QMediaCaptureSession::imageCapture
457
458 \brief the object used to capture still images.
459
460 Add a QImageCapture object to the capture session to enable
461 capturing of still images from the camera.
462*/
463QImageCapture *QMediaCaptureSession::imageCapture()
464{
465 Q_D(QMediaCaptureSession);
466
467 return d->imageCapture;
468}
469
470void QMediaCaptureSession::setImageCapture(QImageCapture *imageCapture)
471{
472 Q_D(QMediaCaptureSession);
473
474 // TODO: come up with an unification of the captures setup
475 QImageCapture *oldImageCapture = d->imageCapture;
476 if (oldImageCapture == imageCapture)
477 return;
478 d->imageCapture = imageCapture;
479 if (d->captureSession)
480 d->captureSession->setImageCapture(nullptr);
481 if (oldImageCapture) {
482 if (oldImageCapture->captureSession() && oldImageCapture->captureSession() != this)
483 oldImageCapture->captureSession()->setImageCapture(nullptr);
484 oldImageCapture->setCaptureSession(nullptr);
485 }
486 if (imageCapture) {
487 if (imageCapture->captureSession())
488 imageCapture->captureSession()->setImageCapture(nullptr);
489 if (d->captureSession)
490 d->captureSession->setImageCapture(imageCapture->platformImageCapture());
491 imageCapture->setCaptureSession(this);
492 }
493 emit imageCaptureChanged();
494}
495/*!
496 \qmlproperty MediaRecorder QtMultimedia::CaptureSession::recorder
497
498 \brief The recorder object used to capture audio/video.
499
500 Add a MediaRcorder object to the capture session to enable
501 recording of audio and/or video from the capture session.
502*/
503/*!
504 \property QMediaCaptureSession::recorder
505
506 \brief The recorder object used to capture audio/video.
507
508 Add a QMediaRecorder object to the capture session to enable
509 recording of audio and/or video from the capture session.
510*/
511
512QMediaRecorder *QMediaCaptureSession::recorder()
513{
514 Q_D(QMediaCaptureSession);
515 return d->recorder;
516}
517
518void QMediaCaptureSession::setRecorder(QMediaRecorder *recorder)
519{
520 Q_D(QMediaCaptureSession);
521 QMediaRecorder *oldRecorder = d->recorder;
522 if (oldRecorder == recorder)
523 return;
524 d->recorder = recorder;
525 if (d->captureSession)
526 d->captureSession->setMediaRecorder(nullptr);
527 if (oldRecorder) {
528 if (oldRecorder->captureSession() && oldRecorder->captureSession() != this)
529 oldRecorder->captureSession()->setRecorder(nullptr);
530 oldRecorder->setCaptureSession(nullptr);
531 }
532 if (recorder) {
533 if (recorder->captureSession())
534 recorder->captureSession()->setRecorder(nullptr);
535 if (d->captureSession)
536 d->captureSession->setMediaRecorder(recorder->platformRecoder());
537 recorder->setCaptureSession(this);
538 }
539 emit recorderChanged();
540}
541/*!
542 \qmlproperty VideoOutput QtMultimedia::CaptureSession::videoOutput
543
544 \brief The VideoOutput that is the video preview for the capture session.
545
546 A VideoOutput based preview is expected to have an invokable videoSink()
547 method that returns a QVideoSink.
548
549 The previously set preview is detached.
550
551*/
552/*!
553 \property QMediaCaptureSession::videoOutput
554
555 Returns the video output for the session.
556*/
557QObject *QMediaCaptureSession::videoOutput() const
558{
559 Q_D(const QMediaCaptureSession);
560 return d->videoOutput;
561}
562/*!
563 Sets a QObject, (\a output), to a video preview for the capture session.
564
565 A QObject based preview is expected to have an invokable videoSink()
566 method that returns a QVideoSink.
567
568 The previously set preview is detached.
569*/
570void QMediaCaptureSession::setVideoOutput(QObject *output)
571{
572 Q_D(QMediaCaptureSession);
573 if (d->videoOutput == output)
574 return;
575 QVideoSink *sink = qobject_cast<QVideoSink *>(output);
576 if (!sink && output) {
577 auto *mo = output->metaObject();
578 mo->invokeMethod(output, "videoSink", Q_RETURN_ARG(QVideoSink *, sink));
579 }
580 d->videoOutput = output;
581 d->setVideoSink(sink);
582}
583
584/*!
585 Sets a QVideoSink, (\a sink), to a video preview for the capture session.
586
587 A QObject based preview is expected to have an invokable videoSink()
588 method that returns a QVideoSink.
589
590 The previously set preview is detached.
591*/
592void QMediaCaptureSession::setVideoSink(QVideoSink *sink)
593{
594 Q_D(QMediaCaptureSession);
595 d->videoOutput = nullptr;
596 d->setVideoSink(sink);
597}
598
599/*!
600 Returns the QVideoSink for the session.
601*/
602QVideoSink *QMediaCaptureSession::videoSink() const
603{
604 Q_D(const QMediaCaptureSession);
605 return d->videoSink;
606}
607/*!
608 Sets the audio output device to \a{output}.
609
610 Setting an audio output device enables audio routing from an audio input device.
611*/
612void QMediaCaptureSession::setAudioOutput(QAudioOutput *output)
613{
614 Q_D(QMediaCaptureSession);
615
616 QAudioOutput *oldOutput = d->audioOutput;
617 if (oldOutput == output)
618 return;
619
620 // We don't want to end up with signal emitted
621 // twice (from recursive call setAudioInput(nullptr)
622 // from oldOutput->setDisconnectFunction():
623 d->audioOutput = nullptr;
624
625 if (d->captureSession)
626 d->captureSession->setAudioOutput(nullptr);
627 if (oldOutput)
628 oldOutput->setDisconnectFunction({});
629 if (output) {
630 output->setDisconnectFunction([this](){ setAudioOutput(nullptr); });
631 if (d->captureSession)
632 d->captureSession->setAudioOutput(output->handle());
633 }
634 d->audioOutput = output;
635 emit audioOutputChanged();
636}
637/*!
638 \qmlproperty AudioOutput QtMultimedia::CaptureSession::audioOutput
639 \brief The audio output device for the capture session.
640
641 Add an AudioOutput device to the capture session to enable
642 audio routing from an AudioInput device.
643*/
644/*!
645 \property QMediaCaptureSession::audioOutput
646
647 Returns the audio output for the session.
648*/
649QAudioOutput *QMediaCaptureSession::audioOutput() const
650{
651 Q_D(const QMediaCaptureSession);
652 return d->audioOutput;
653}
654
655/*!
656 \internal
657*/
658QPlatformMediaCaptureSession *QMediaCaptureSession::platformSession() const
659{
660 Q_D(const QMediaCaptureSession);
661 return d->captureSession.get();
662}
663/*!
664 \qmlsignal QtMultimedia::CaptureSession::audioInputChanged()
665 This signal is emitted when an audio input has changed.
666 \sa CaptureSession::audioInput
667*/
668
669/*!
670 \qmlsignal QtMultimedia::CaptureSession::cameraChanged()
671 This signal is emitted when the selected camera has changed.
672 \sa CaptureSession::camera
673*/
674
675/*!
676 \qmlsignal QtMultimedia::CaptureSession::imageCaptureChanged()
677 This signal is emitted when the selected interface has changed.
678 \sa CaptureSession::camera
679*/
680
681/*!
682 \qmlsignal QtMultimedia::CaptureSession::recorderChanged()
683 This signal is emitted when the selected recorder has changed.
684 \sa CaptureSession::recorder
685*/
686
687/*!
688 \qmlsignal QtMultimedia::CaptureSession::videoOutputChanged()
689 This signal is emitted when the selected video output has changed.
690 \sa CaptureSession::videoOutput
691*/
692
693/*!
694 \qmlsignal QtMultimedia::CaptureSession::audioOutputChanged()
695 This signal is emitted when the selected audio output has changed.
696 \sa CaptureSession::audioOutput
697*/
698QT_END_NAMESPACE
699
700#include "moc_qmediacapturesession.cpp"
void setVideoSink(QVideoSink *sink)
Combined button and popup list for selecting options.