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
126template <>
127struct QMediaCaptureSession::ObjectTraits<QCamera>
128{
129 static constexpr auto Member = &QMediaCaptureSessionPrivate::camera;
130 static constexpr auto Setter = &QMediaCaptureSession::setCamera;
131 static constexpr auto PlatformSetter = &QPlatformMediaCaptureSession::setCamera;
132 static constexpr auto PlatformObjectProvider = &QCamera::platformCamera;
133 static constexpr auto ChangeNotifier = &QMediaCaptureSession::cameraChanged;
134};
135
136template <>
137struct QMediaCaptureSession::ObjectTraits<QScreenCapture>
138{
139 static constexpr auto Member = &QMediaCaptureSessionPrivate::screenCapture;
140 static constexpr auto Setter = &QMediaCaptureSession::setScreenCapture;
141 static constexpr auto PlatformSetter = &QPlatformMediaCaptureSession::setScreenCapture;
142 static constexpr auto PlatformObjectProvider = &QScreenCapture::platformScreenCapture;
143 static constexpr auto ChangeNotifier = &QMediaCaptureSession::screenCaptureChanged;
144};
145
146template <>
147struct QMediaCaptureSession::ObjectTraits<QWindowCapture>
148{
149 static constexpr auto Member = &QMediaCaptureSessionPrivate::windowCapture;
150 static constexpr auto Setter = &QMediaCaptureSession::setWindowCapture;
151 static constexpr auto PlatformSetter = &QPlatformMediaCaptureSession::setWindowCapture;
152 static constexpr auto PlatformObjectProvider = &QWindowCapture::platformWindowCapture;
153 static constexpr auto ChangeNotifier = &QMediaCaptureSession::windowCaptureChanged;
154};
155
156template <>
157struct QMediaCaptureSession::ObjectTraits<QVideoFrameInput>
158{
159 static constexpr auto Member = &QMediaCaptureSessionPrivate::videoFrameInput;
160 static constexpr auto Setter = &QMediaCaptureSession::setVideoFrameInput;
161 static constexpr auto PlatformSetter = &QPlatformMediaCaptureSession::setVideoFrameInput;
162 static constexpr auto PlatformObjectProvider = &QVideoFrameInput::platformVideoFrameInput;
163 static constexpr auto ChangeNotifier = &QMediaCaptureSession::videoFrameInputChanged;
164};
165
166template <>
167struct QMediaCaptureSession::ObjectTraits<QAudioBufferInput>
168{
169 static constexpr auto Member = &QMediaCaptureSessionPrivate::audioBufferInput;
170 static constexpr auto Setter = &QMediaCaptureSession::setAudioBufferInput;
171 static constexpr auto PlatformSetter = &QPlatformMediaCaptureSession::setAudioBufferInput;
172 static constexpr auto PlatformObjectProvider = &QAudioBufferInput::platformAudioBufferInput;
173 static constexpr auto ChangeNotifier = &QMediaCaptureSession::audioBufferInputChanged;
174};
175
176template <>
177struct QMediaCaptureSession::ObjectTraits<QImageCapture>
178{
179 static constexpr auto Member = &QMediaCaptureSessionPrivate::imageCapture;
180 static constexpr auto Setter = &QMediaCaptureSession::setImageCapture;
181 static constexpr auto PlatformSetter = &QPlatformMediaCaptureSession::setImageCapture;
182 static constexpr auto PlatformObjectProvider = &QImageCapture::platformImageCapture;
183 static constexpr auto ChangeNotifier = &QMediaCaptureSession::imageCaptureChanged;
184};
185
186template <>
187struct QMediaCaptureSession::ObjectTraits<QMediaRecorder>
188{
189 static constexpr auto Member = &QMediaCaptureSessionPrivate::recorder;
190 static constexpr auto Setter = &QMediaCaptureSession::setRecorder;
191 static constexpr auto PlatformSetter = &QPlatformMediaCaptureSession::setMediaRecorder;
192 static constexpr auto PlatformObjectProvider = &QMediaRecorder::platformRecoder;
193 static constexpr auto ChangeNotifier = &QMediaCaptureSession::recorderChanged;
194};
195
196template <typename Object>
197void QMediaCaptureSession::setObject(Object *object) {
198 Q_D(QMediaCaptureSession);
199
200 using Traits = QMediaCaptureSession::ObjectTraits<Object>;
201
202 Object *oldObject = d->*Traits::Member;
203 if (oldObject == object)
204 return;
205
206 d->*Traits::Member = object;
207
208 if (d->captureSession)
209 std::invoke(Traits::PlatformSetter, d->captureSession, nullptr);
210
211 if (oldObject) {
212 if (oldObject->captureSession() && oldObject->captureSession() != this)
213 std::invoke(Traits::Setter, oldObject->captureSession(), nullptr);
214 oldObject->setCaptureSession(nullptr);
215 }
216
217 if (object) {
218 if (auto *otherSession = object->captureSession())
219 std::invoke(Traits::Setter, otherSession, nullptr);
220 if (d->captureSession)
221 std::invoke(Traits::PlatformSetter, d->captureSession,
222 std::invoke(Traits::PlatformObjectProvider, object));
223 object->setCaptureSession(this);
224 }
225
226 emit (this->*Traits::ChangeNotifier)();
227}
228
229/*!
230 Creates a session for media capture from the \a parent object.
231 */
232QMediaCaptureSession::QMediaCaptureSession(QObject *parent)
233 : QObject{ *new QMediaCaptureSessionPrivate, parent }
234{
235 Q_D(QMediaCaptureSession);
236
237 auto maybeCaptureSession = QPlatformMediaIntegration::instance()->createCaptureSession();
238 if (maybeCaptureSession) {
239 d->captureSession.reset(maybeCaptureSession.value());
240 d->captureSession->setCaptureSession(this);
241 } else {
242 qWarning() << "Failed to initialize QMediaCaptureSession" << maybeCaptureSession.error();
243 }
244}
245
246/*!
247 Destroys the session.
248 */
249QMediaCaptureSession::~QMediaCaptureSession()
250{
251 Q_D(QMediaCaptureSession);
252
253 setCamera(nullptr);
254 setRecorder(nullptr);
255 setImageCapture(nullptr);
256 setScreenCapture(nullptr);
257 setWindowCapture(nullptr);
258 setVideoFrameInput(nullptr);
259 setAudioBufferInput(nullptr);
260 setAudioInput(nullptr);
261 setAudioOutput(nullptr);
262 d->setVideoSink(nullptr);
263 d->captureSession.reset();
264}
265/*!
266 \qmlproperty AudioInput QtMultimedia::CaptureSession::audioInput
267
268 This property holds the audio input that is being used to capture audio.
269*/
270
271/*!
272 \property QMediaCaptureSession::audioInput
273
274 Returns the device that is being used to capture audio.
275*/
276QAudioInput *QMediaCaptureSession::audioInput() const
277{
278 Q_D(const QMediaCaptureSession);
279 return d->audioInput;
280}
281
282/*!
283 Sets the audio input device to \a input. If setting it to an empty
284 QAudioDevice the capture session will use the default input as
285 defined by the operating system.
286*/
287void QMediaCaptureSession::setAudioInput(QAudioInput *input)
288{
289 Q_D(QMediaCaptureSession);
290
291 QAudioInput *oldInput = d->audioInput;
292 if (oldInput == input)
293 return;
294
295 // To avoid double emit of audioInputChanged
296 // from recursive setAudioInput(nullptr) call.
297 d->audioInput = nullptr;
298
299 // TODO: check if it's possible to reuse setObject(input)
300 if (d->captureSession)
301 d->captureSession->setAudioInput(nullptr);
302 if (oldInput)
303 oldInput->setDisconnectFunction({});
304 if (input) {
305 input->setDisconnectFunction([this](){ setAudioInput(nullptr); });
306 if (d->captureSession)
307 d->captureSession->setAudioInput(input->handle());
308 }
309 d->audioInput = input;
310 emit audioInputChanged();
311}
312
313/*!
314 \property QMediaCaptureSession::audioBufferInput
315 \since 6.8
316
317 \brief The object used to send custom audio buffers to \l QMediaRecorder.
318*/
319QAudioBufferInput *QMediaCaptureSession::audioBufferInput() const
320{
321 Q_D(const QMediaCaptureSession);
322
323 return d->audioBufferInput;
324}
325
326void QMediaCaptureSession::setAudioBufferInput(QAudioBufferInput *input)
327{
328 setObject(input);
329}
330
331/*!
332 \qmlproperty Camera QtMultimedia::CaptureSession::camera
333
334 \brief The camera used to capture video.
335
336 Record video or take images by adding a camera to the capture session using
337 this property.
338*/
339
340/*!
341 \property QMediaCaptureSession::camera
342
343 \brief The camera used to capture video.
344
345 Record video or take images by adding a camera to the capture session
346 using this property.
347*/
348QCamera *QMediaCaptureSession::camera() const
349{
350 Q_D(const QMediaCaptureSession);
351 return d->camera;
352}
353
354void QMediaCaptureSession::setCamera(QCamera *camera)
355{
356 Q_D(QMediaCaptureSession);
357
358 if (d->camera
359 && d->camera != camera
360 && !QPlatformMediaIntegration::instance()->isCameraSwitchingDuringRecordingSupported()
361 && recorder() && recorder()->recorderState() == QMediaRecorder::RecordingState) {
362 qWarning("This media backend does not support camera switching during recording");
363 return;
364 }
365
366 setObject(camera);
367}
368
369/*!
370 \qmlproperty ScreenCapture QtMultimedia::CaptureSession::screenCapture
371 \since 6.5
372
373 \brief The object used to capture a screen.
374
375 Record a screen by adding a screen capture objet
376 to the capture session using this property.
377*/
378
379/*!
380 \property QMediaCaptureSession::screenCapture
381 \since 6.5
382
383 \brief The object used to capture a screen.
384
385 Record a screen by adding a screen capture object
386 to the capture session using this property.
387*/
388QScreenCapture *QMediaCaptureSession::screenCapture()
389{
390 Q_D(QMediaCaptureSession);
391 return d->screenCapture;
392}
393
394void QMediaCaptureSession::setScreenCapture(QScreenCapture *screenCapture)
395{
396 setObject(screenCapture);
397}
398
399/*!
400 \qmlproperty WindowCapture QtMultimedia::CaptureSession::windowCapture
401 \since 6.6
402
403 \brief The object used to capture a window.
404
405 Record a window by adding a window capture object
406 to the capture session using this property.
407*/
408
409/*!
410 \property QMediaCaptureSession::windowCapture
411 \since 6.6
412
413 \brief The object used to capture a window.
414
415 Record a window by adding a window capture objet
416 to the capture session using this property.
417*/
418QWindowCapture *QMediaCaptureSession::windowCapture()
419{
420 Q_D(QMediaCaptureSession);
421 return d->windowCapture;
422}
423
424void QMediaCaptureSession::setWindowCapture(QWindowCapture *windowCapture)
425{
426 setObject(windowCapture);
427}
428
429/*!
430 \property QMediaCaptureSession::videoFrameInput
431 \since 6.8
432
433 \brief The object used to send custom video frames to
434 \l QMediaRecorder or a video output.
435*/
436QVideoFrameInput *QMediaCaptureSession::videoFrameInput() const
437{
438 Q_D(const QMediaCaptureSession);
439 return d->videoFrameInput;
440}
441
442void QMediaCaptureSession::setVideoFrameInput(QVideoFrameInput *input)
443{
444 setObject(input);
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 return d->imageCapture;
467}
468
469void QMediaCaptureSession::setImageCapture(QImageCapture *imageCapture)
470{
471 setObject(imageCapture);
472}
473/*!
474 \qmlproperty MediaRecorder QtMultimedia::CaptureSession::recorder
475
476 \brief The recorder object used to capture audio/video.
477
478 Add a MediaRcorder object to the capture session to enable
479 recording of audio and/or video from the capture session.
480*/
481/*!
482 \property QMediaCaptureSession::recorder
483
484 \brief The recorder object used to capture audio/video.
485
486 Add a QMediaRecorder object to the capture session to enable
487 recording of audio and/or video from the capture session.
488*/
489
490QMediaRecorder *QMediaCaptureSession::recorder()
491{
492 Q_D(QMediaCaptureSession);
493 return d->recorder;
494}
495
496void QMediaCaptureSession::setRecorder(QMediaRecorder *recorder)
497{
498 setObject(recorder);
499}
500/*!
501 \qmlproperty VideoOutput QtMultimedia::CaptureSession::videoOutput
502
503 \brief The VideoOutput that is the video preview for the capture session.
504
505 A VideoOutput based preview is expected to have an invokable videoSink()
506 method that returns a QVideoSink.
507
508 The previously set preview is detached.
509
510*/
511/*!
512 \property QMediaCaptureSession::videoOutput
513
514 Returns the video output for the session.
515*/
516QObject *QMediaCaptureSession::videoOutput() const
517{
518 Q_D(const QMediaCaptureSession);
519 return d->videoOutput;
520}
521/*!
522 Sets a QObject, (\a output), to a video preview for the capture session.
523
524 A QObject based preview is expected to have an invokable videoSink()
525 method that returns a QVideoSink.
526
527 The previously set preview is detached.
528*/
529void QMediaCaptureSession::setVideoOutput(QObject *output)
530{
531 Q_D(QMediaCaptureSession);
532 if (d->videoOutput == output)
533 return;
534 QVideoSink *sink = qobject_cast<QVideoSink *>(output);
535 if (!sink && output) {
536 auto *mo = output->metaObject();
537 mo->invokeMethod(output, "videoSink", Q_RETURN_ARG(QVideoSink *, sink));
538 }
539 d->videoOutput = output;
540 d->setVideoSink(sink);
541}
542
543/*!
544 Sets a QVideoSink, (\a sink), to a video preview for the capture session.
545
546 A QObject based preview is expected to have an invokable videoSink()
547 method that returns a QVideoSink.
548
549 The previously set preview is detached.
550*/
551void QMediaCaptureSession::setVideoSink(QVideoSink *sink)
552{
553 Q_D(QMediaCaptureSession);
554 d->videoOutput = nullptr;
555 d->setVideoSink(sink);
556}
557
558/*!
559 Returns the QVideoSink for the session.
560*/
561QVideoSink *QMediaCaptureSession::videoSink() const
562{
563 Q_D(const QMediaCaptureSession);
564 return d->videoSink;
565}
566/*!
567 Sets the audio output device to \a{output}.
568
569 Setting an audio output device enables audio routing from an audio input device.
570*/
571void QMediaCaptureSession::setAudioOutput(QAudioOutput *output)
572{
573 Q_D(QMediaCaptureSession);
574
575 QAudioOutput *oldOutput = d->audioOutput;
576 if (oldOutput == output)
577 return;
578
579 // We don't want to end up with signal emitted
580 // twice (from recursive call setAudioInput(nullptr)
581 // from oldOutput->setDisconnectFunction():
582 d->audioOutput = nullptr;
583
584 if (d->captureSession)
585 d->captureSession->setAudioOutput(nullptr);
586 if (oldOutput)
587 oldOutput->setDisconnectFunction({});
588 if (output) {
589 output->setDisconnectFunction([this](){ setAudioOutput(nullptr); });
590 if (d->captureSession)
591 d->captureSession->setAudioOutput(output->handle());
592 }
593 d->audioOutput = output;
594 emit audioOutputChanged();
595}
596/*!
597 \qmlproperty AudioOutput QtMultimedia::CaptureSession::audioOutput
598 \brief The audio output device for the capture session.
599
600 Add an AudioOutput device to the capture session to enable
601 audio routing from an AudioInput device.
602*/
603/*!
604 \property QMediaCaptureSession::audioOutput
605
606 Returns the audio output for the session.
607*/
608QAudioOutput *QMediaCaptureSession::audioOutput() const
609{
610 Q_D(const QMediaCaptureSession);
611 return d->audioOutput;
612}
613
614/*!
615 \internal
616*/
617QPlatformMediaCaptureSession *QMediaCaptureSession::platformSession() const
618{
619 Q_D(const QMediaCaptureSession);
620 return d->captureSession.get();
621}
622/*!
623 \qmlsignal QtMultimedia::CaptureSession::audioInputChanged()
624 This signal is emitted when an audio input has changed.
625 \sa CaptureSession::audioInput
626*/
627
628/*!
629 \qmlsignal QtMultimedia::CaptureSession::cameraChanged()
630 This signal is emitted when the selected camera has changed.
631 \sa CaptureSession::camera
632*/
633
634/*!
635 \qmlsignal QtMultimedia::CaptureSession::imageCaptureChanged()
636 This signal is emitted when the selected interface has changed.
637 \sa CaptureSession::camera
638*/
639
640/*!
641 \qmlsignal QtMultimedia::CaptureSession::recorderChanged()
642 This signal is emitted when the selected recorder has changed.
643 \sa CaptureSession::recorder
644*/
645
646/*!
647 \qmlsignal QtMultimedia::CaptureSession::videoOutputChanged()
648 This signal is emitted when the selected video output has changed.
649 \sa CaptureSession::videoOutput
650*/
651
652/*!
653 \qmlsignal QtMultimedia::CaptureSession::audioOutputChanged()
654 This signal is emitted when the selected audio output has changed.
655 \sa CaptureSession::audioOutput
656*/
657QT_END_NAMESPACE
658
659#include "moc_qmediacapturesession.cpp"
void setVideoSink(QVideoSink *sink)
Combined button and popup list for selecting options.