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 d->camera = camera;
281 if (d->captureSession)
282 d->captureSession->setCamera(nullptr);
283 if (oldCamera) {
284 if (oldCamera->captureSession() && oldCamera->captureSession() != this)
285 oldCamera->captureSession()->setCamera(nullptr);
286 oldCamera->setCaptureSession(nullptr);
287 }
288 if (camera) {
289 if (camera->captureSession())
290 camera->captureSession()->setCamera(nullptr);
291 if (d->captureSession)
292 d->captureSession->setCamera(camera->platformCamera());
293 camera->setCaptureSession(this);
294 }
295 emit cameraChanged();
296}
297
298/*!
299 \qmlproperty ScreenCapture QtMultimedia::CaptureSession::screenCapture
300 \since 6.5
301
302 \brief The object used to capture a screen.
303
304 Record a screen by adding a screen capture objet
305 to the capture session using this property.
306*/
307
308/*!
309 \property QMediaCaptureSession::screenCapture
310 \since 6.5
311
312 \brief The object used to capture a screen.
313
314 Record a screen by adding a screen capture object
315 to the capture session using this property.
316*/
317QScreenCapture *QMediaCaptureSession::screenCapture()
318{
319 Q_D(QMediaCaptureSession);
320
321 return d->screenCapture;
322}
323
324void QMediaCaptureSession::setScreenCapture(QScreenCapture *screenCapture)
325{
326 Q_D(QMediaCaptureSession);
327
328 // TODO: come up with an unification of the captures setup
329 QScreenCapture *oldScreenCapture = d->screenCapture;
330 if (oldScreenCapture == screenCapture)
331 return;
332 d->screenCapture = screenCapture;
333 if (d->captureSession)
334 d->captureSession->setScreenCapture(nullptr);
335 if (oldScreenCapture) {
336 if (oldScreenCapture->captureSession() && oldScreenCapture->captureSession() != this)
337 oldScreenCapture->captureSession()->setScreenCapture(nullptr);
338 oldScreenCapture->setCaptureSession(nullptr);
339 }
340 if (screenCapture) {
341 if (screenCapture->captureSession())
342 screenCapture->captureSession()->setScreenCapture(nullptr);
343 if (d->captureSession)
344 d->captureSession->setScreenCapture(screenCapture->platformScreenCapture());
345 screenCapture->setCaptureSession(this);
346 }
347 emit screenCaptureChanged();
348}
349
350/*!
351 \qmlproperty WindowCapture QtMultimedia::CaptureSession::windowCapture
352 \since 6.6
353
354 \brief The object used to capture a window.
355
356 Record a window by adding a window capture object
357 to the capture session using this property.
358*/
359
360/*!
361 \property QMediaCaptureSession::windowCapture
362 \since 6.6
363
364 \brief The object used to capture a window.
365
366 Record a window by adding a window capture objet
367 to the capture session using this property.
368*/
369QWindowCapture *QMediaCaptureSession::windowCapture()
370{
371 Q_D(QMediaCaptureSession);
372 return d->windowCapture;
373}
374
375void QMediaCaptureSession::setWindowCapture(QWindowCapture *windowCapture)
376{
377 Q_D(QMediaCaptureSession);
378
379 // TODO: come up with an unification of the captures setup
380 QWindowCapture *oldCapture = d->windowCapture;
381 if (oldCapture == windowCapture)
382 return;
383 d->windowCapture = windowCapture;
384 if (d->captureSession)
385 d->captureSession->setWindowCapture(nullptr);
386 if (oldCapture) {
387 if (oldCapture->captureSession() && oldCapture->captureSession() != this)
388 oldCapture->captureSession()->setWindowCapture(nullptr);
389 oldCapture->setCaptureSession(nullptr);
390 }
391 if (windowCapture) {
392 if (windowCapture->captureSession())
393 windowCapture->captureSession()->setWindowCapture(nullptr);
394 if (d->captureSession)
395 d->captureSession->setWindowCapture(windowCapture->platformWindowCapture());
396 windowCapture->setCaptureSession(this);
397 }
398 emit windowCaptureChanged();
399}
400
401/*!
402 \property QMediaCaptureSession::videoFrameInput
403 \since 6.8
404
405 \brief The object used to send custom video frames to
406 \l QMediaRecorder or a video output.
407*/
408QVideoFrameInput *QMediaCaptureSession::videoFrameInput() const
409{
410 Q_D(const QMediaCaptureSession);
411 return d->videoFrameInput;
412}
413
414void QMediaCaptureSession::setVideoFrameInput(QVideoFrameInput *input)
415{
416 Q_D(QMediaCaptureSession);
417 // TODO: come up with an unification of the captures setup
418 QVideoFrameInput *oldInput = d->videoFrameInput;
419 if (oldInput == input)
420 return;
421 d->videoFrameInput = input;
422 if (d->captureSession)
423 d->captureSession->setVideoFrameInput(nullptr);
424 if (oldInput) {
425 if (oldInput->captureSession() && oldInput->captureSession() != this)
426 oldInput->captureSession()->setVideoFrameInput(nullptr);
427 oldInput->setCaptureSession(nullptr);
428 }
429 if (input) {
430 if (input->captureSession())
431 input->captureSession()->setVideoFrameInput(nullptr);
432 if (d->captureSession)
433 d->captureSession->setVideoFrameInput(input->platformVideoFrameInput());
434 input->setCaptureSession(this);
435 }
436 emit videoFrameInputChanged();
437}
438
439/*!
440 \qmlproperty ImageCapture QtMultimedia::CaptureSession::imageCapture
441
442 \brief The object used to capture still images.
443
444 Add an ImageCapture interface to the capture session to enable
445 capturing of still images from the camera.
446*/
447/*!
448 \property QMediaCaptureSession::imageCapture
449
450 \brief the object used to capture still images.
451
452 Add a QImageCapture object to the capture session to enable
453 capturing of still images from the camera.
454*/
455QImageCapture *QMediaCaptureSession::imageCapture()
456{
457 Q_D(QMediaCaptureSession);
458
459 return d->imageCapture;
460}
461
462void QMediaCaptureSession::setImageCapture(QImageCapture *imageCapture)
463{
464 Q_D(QMediaCaptureSession);
465
466 // TODO: come up with an unification of the captures setup
467 QImageCapture *oldImageCapture = d->imageCapture;
468 if (oldImageCapture == imageCapture)
469 return;
470 d->imageCapture = imageCapture;
471 if (d->captureSession)
472 d->captureSession->setImageCapture(nullptr);
473 if (oldImageCapture) {
474 if (oldImageCapture->captureSession() && oldImageCapture->captureSession() != this)
475 oldImageCapture->captureSession()->setImageCapture(nullptr);
476 oldImageCapture->setCaptureSession(nullptr);
477 }
478 if (imageCapture) {
479 if (imageCapture->captureSession())
480 imageCapture->captureSession()->setImageCapture(nullptr);
481 if (d->captureSession)
482 d->captureSession->setImageCapture(imageCapture->platformImageCapture());
483 imageCapture->setCaptureSession(this);
484 }
485 emit imageCaptureChanged();
486}
487/*!
488 \qmlproperty MediaRecorder QtMultimedia::CaptureSession::recorder
489
490 \brief The recorder object used to capture audio/video.
491
492 Add a MediaRcorder object to the capture session to enable
493 recording of audio and/or video from the capture session.
494*/
495/*!
496 \property QMediaCaptureSession::recorder
497
498 \brief The recorder object used to capture audio/video.
499
500 Add a QMediaRecorder object to the capture session to enable
501 recording of audio and/or video from the capture session.
502*/
503
504QMediaRecorder *QMediaCaptureSession::recorder()
505{
506 Q_D(QMediaCaptureSession);
507 return d->recorder;
508}
509
510void QMediaCaptureSession::setRecorder(QMediaRecorder *recorder)
511{
512 Q_D(QMediaCaptureSession);
513 QMediaRecorder *oldRecorder = d->recorder;
514 if (oldRecorder == recorder)
515 return;
516 d->recorder = recorder;
517 if (d->captureSession)
518 d->captureSession->setMediaRecorder(nullptr);
519 if (oldRecorder) {
520 if (oldRecorder->captureSession() && oldRecorder->captureSession() != this)
521 oldRecorder->captureSession()->setRecorder(nullptr);
522 oldRecorder->setCaptureSession(nullptr);
523 }
524 if (recorder) {
525 if (recorder->captureSession())
526 recorder->captureSession()->setRecorder(nullptr);
527 if (d->captureSession)
528 d->captureSession->setMediaRecorder(recorder->platformRecoder());
529 recorder->setCaptureSession(this);
530 }
531 emit recorderChanged();
532}
533/*!
534 \qmlproperty VideoOutput QtMultimedia::CaptureSession::videoOutput
535
536 \brief The VideoOutput that is the video preview for the capture session.
537
538 A VideoOutput based preview is expected to have an invokable videoSink()
539 method that returns a QVideoSink.
540
541 The previously set preview is detached.
542
543*/
544/*!
545 \property QMediaCaptureSession::videoOutput
546
547 Returns the video output for the session.
548*/
549QObject *QMediaCaptureSession::videoOutput() const
550{
551 Q_D(const QMediaCaptureSession);
552 return d->videoOutput;
553}
554/*!
555 Sets a QObject, (\a output), to a video preview for the capture session.
556
557 A QObject based preview is expected to have an invokable videoSink()
558 method that returns a QVideoSink.
559
560 The previously set preview is detached.
561*/
562void QMediaCaptureSession::setVideoOutput(QObject *output)
563{
564 Q_D(QMediaCaptureSession);
565 if (d->videoOutput == output)
566 return;
567 QVideoSink *sink = qobject_cast<QVideoSink *>(output);
568 if (!sink && output) {
569 auto *mo = output->metaObject();
570 mo->invokeMethod(output, "videoSink", Q_RETURN_ARG(QVideoSink *, sink));
571 }
572 d->videoOutput = output;
573 d->setVideoSink(sink);
574}
575
576/*!
577 Sets a QVideoSink, (\a sink), to a video preview for the capture session.
578
579 A QObject based preview is expected to have an invokable videoSink()
580 method that returns a QVideoSink.
581
582 The previously set preview is detached.
583*/
584void QMediaCaptureSession::setVideoSink(QVideoSink *sink)
585{
586 Q_D(QMediaCaptureSession);
587 d->videoOutput = nullptr;
588 d->setVideoSink(sink);
589}
590
591/*!
592 Returns the QVideoSink for the session.
593*/
594QVideoSink *QMediaCaptureSession::videoSink() const
595{
596 Q_D(const QMediaCaptureSession);
597 return d->videoSink;
598}
599/*!
600 Sets the audio output device to \a{output}.
601
602 Setting an audio output device enables audio routing from an audio input device.
603*/
604void QMediaCaptureSession::setAudioOutput(QAudioOutput *output)
605{
606 Q_D(QMediaCaptureSession);
607
608 QAudioOutput *oldOutput = d->audioOutput;
609 if (oldOutput == output)
610 return;
611
612 // We don't want to end up with signal emitted
613 // twice (from recursive call setAudioInput(nullptr)
614 // from oldOutput->setDisconnectFunction():
615 d->audioOutput = nullptr;
616
617 if (d->captureSession)
618 d->captureSession->setAudioOutput(nullptr);
619 if (oldOutput)
620 oldOutput->setDisconnectFunction({});
621 if (output) {
622 output->setDisconnectFunction([this](){ setAudioOutput(nullptr); });
623 if (d->captureSession)
624 d->captureSession->setAudioOutput(output->handle());
625 }
626 d->audioOutput = output;
627 emit audioOutputChanged();
628}
629/*!
630 \qmlproperty AudioOutput QtMultimedia::CaptureSession::audioOutput
631 \brief The audio output device for the capture session.
632
633 Add an AudioOutput device to the capture session to enable
634 audio routing from an AudioInput device.
635*/
636/*!
637 \property QMediaCaptureSession::audioOutput
638
639 Returns the audio output for the session.
640*/
641QAudioOutput *QMediaCaptureSession::audioOutput() const
642{
643 Q_D(const QMediaCaptureSession);
644 return d->audioOutput;
645}
646
647/*!
648 \internal
649*/
650QPlatformMediaCaptureSession *QMediaCaptureSession::platformSession() const
651{
652 Q_D(const QMediaCaptureSession);
653 return d->captureSession.get();
654}
655/*!
656 \qmlsignal QtMultimedia::CaptureSession::audioInputChanged()
657 This signal is emitted when an audio input has changed.
658 \sa CaptureSession::audioInput
659*/
660
661/*!
662 \qmlsignal QtMultimedia::CaptureSession::cameraChanged()
663 This signal is emitted when the selected camera has changed.
664 \sa CaptureSession::camera
665*/
666
667/*!
668 \qmlsignal QtMultimedia::CaptureSession::imageCaptureChanged()
669 This signal is emitted when the selected interface has changed.
670 \sa CaptureSession::camera
671*/
672
673/*!
674 \qmlsignal QtMultimedia::CaptureSession::recorderChanged()
675 This signal is emitted when the selected recorder has changed.
676 \sa CaptureSession::recorder
677*/
678
679/*!
680 \qmlsignal QtMultimedia::CaptureSession::videoOutputChanged()
681 This signal is emitted when the selected video output has changed.
682 \sa CaptureSession::videoOutput
683*/
684
685/*!
686 \qmlsignal QtMultimedia::CaptureSession::audioOutputChanged()
687 This signal is emitted when the selected audio output has changed.
688 \sa CaptureSession::audioOutput
689*/
690QT_END_NAMESPACE
691
692#include "moc_qmediacapturesession.cpp"
void setVideoSink(QVideoSink *sink)