Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwindowsmediadevicesession.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 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
5
7#include "private/qwindowsmultimediautils_p.h"
8#include "private/qplatformvideosink_p.h"
9#include <qvideosink.h>
10#include <QtCore/qdebug.h>
11#include <qaudioinput.h>
12#include <qaudiooutput.h>
13
15
17 : QObject(parent)
18{
19 m_mediaDeviceReader = new QWindowsMediaDeviceReader(this);
21 this, &QWindowsMediaDeviceSession::handleStreamingStarted);
23 this, &QWindowsMediaDeviceSession::handleStreamingStopped);
25 this, &QWindowsMediaDeviceSession::handleStreamingError);
27 this, &QWindowsMediaDeviceSession::handleVideoFrameChanged);
36}
37
39{
40 delete m_mediaDeviceReader;
41}
42
44{
45 return m_active;
46}
47
49{
50 return m_activating;
51}
52
54{
55 if ((active && (m_active || m_activating)) || (!active && !m_active && !m_activating))
56 return;
57
58 if (active) {
59 auto camId = QString::fromUtf8(m_activeCameraDevice.id());
60 auto micId = m_audioInput ? QString::fromUtf8(m_audioInput->device().id()) : QString();
61 if (!camId.isEmpty() || !micId.isEmpty()) {
62 if (m_mediaDeviceReader->activate(camId, m_cameraFormat, micId)) {
63 m_activating = true;
64 } else {
65 emit streamingError(MF_E_NOT_AVAILABLE);
66 }
67 } else {
68 qWarning() << Q_FUNC_INFO << "Camera ID and Microphone ID both undefined.";
69 }
70 } else {
71 m_mediaDeviceReader->deactivate();
72 m_active = false;
73 m_activating = false;
74 emit activeChanged(m_active);
76 }
77}
78
79void QWindowsMediaDeviceSession::reactivate()
80{
81 if (m_active || m_activating) {
83 setActive(false);
84 setActive(true);
86 }
87}
88
90{
91 m_activeCameraDevice = camera;
92 reactivate();
93}
94
96{
97 return m_activeCameraDevice;
98}
99
101{
102 m_cameraFormat = cameraFormat;
103}
104
106{
107 m_surface = surface;
108}
109
110void QWindowsMediaDeviceSession::handleStreamingStarted()
111{
112 if (m_activating) {
113 m_active = true;
114 m_activating = false;
115 emit activeChanged(m_active);
117 }
118}
119
120void QWindowsMediaDeviceSession::handleStreamingStopped()
121{
122 m_active = false;
123 emit activeChanged(m_active);
125}
126
127void QWindowsMediaDeviceSession::handleStreamingError(int errorCode)
128{
129 if (m_surface)
131 emit streamingError(errorCode);
132}
133
134void QWindowsMediaDeviceSession::handleVideoFrameChanged(const QVideoFrame &frame)
135{
136 if (m_surface)
139}
140
142{
143 m_mediaDeviceReader->setInputMuted(muted);
144}
145
147{
148 m_mediaDeviceReader->setInputVolume(volume);
149}
150
155
157{
158 m_mediaDeviceReader->setOutputMuted(muted);
159}
160
162{
163 m_mediaDeviceReader->setOutputVolume(volume);
164}
165
167{
168 if (m_active || m_activating)
169 m_mediaDeviceReader->setAudioOutput(QString::fromUtf8(m_audioOutput->device().id()));
170}
171
173{
174 if (m_audioInput == input)
175 return;
176 if (m_audioInput)
177 m_audioInput->disconnect(this);
178 m_audioInput = input;
179
181
182 if (!m_audioInput)
183 return;
187}
188
190{
191 if (m_audioOutput == output)
192 return;
193 if (m_audioOutput)
194 m_audioOutput->disconnect(this);
195 m_audioOutput = output;
196 if (!m_audioOutput) {
197 m_mediaDeviceReader->setAudioOutput({});
198 return;
199 }
200
201 m_mediaDeviceReader->setAudioOutput(QString::fromUtf8(m_audioOutput->device().id()));
202
206}
207
209{
210 GUID container = audioOnly ? QWindowsMultimediaUtils::containerForAudioFileFormat(settings.mediaFormat().fileFormat())
212 GUID videoFormat = QWindowsMultimediaUtils::videoFormatForCodec(settings.videoCodec());
213 GUID audioFormat = QWindowsMultimediaUtils::audioFormatForCodec(settings.audioCodec());
214
215 QSize res = settings.videoResolution();
216 UINT32 width, height;
217 if (res.width() > 0 && res.height() > 0) {
218 width = UINT32(res.width());
219 height = UINT32(res.height());
220 } else {
221 width = m_mediaDeviceReader->frameWidth();
222 height = m_mediaDeviceReader->frameHeight();
223 settings.setVideoResolution(QSize(int(width), int(height)));
224 }
225
226 qreal frameRate = settings.videoFrameRate();
227 if (frameRate <= 0) {
228 frameRate = m_mediaDeviceReader->frameRate();
229 settings.setVideoFrameRate(frameRate);
230 }
231
232 auto quality = settings.quality();
233
234 UINT32 videoBitRate = 0;
235 if (settings.videoBitRate() > 0) {
236 videoBitRate = UINT32(settings.videoBitRate());
237 } else {
238 videoBitRate = estimateVideoBitRate(videoFormat, width, height, frameRate, quality);
239 settings.setVideoBitRate(int(videoBitRate));
240 }
241
242 UINT32 audioBitRate = 0;
243 if (settings.audioBitRate() > 0) {
244 audioBitRate = UINT32(settings.audioBitRate());
245 } else {
246 audioBitRate = estimateAudioBitRate(audioFormat, quality);
247 settings.setAudioBitRate(int(audioBitRate));
248 }
249
250 return m_mediaDeviceReader->startRecording(fileName, container, audioOnly ? GUID_NULL : videoFormat,
251 videoBitRate, width, height, frameRate,
252 audioFormat, audioBitRate);
253}
254
256{
257 m_mediaDeviceReader->stopRecording();
258}
259
261{
262 return m_mediaDeviceReader->pauseRecording();
263}
264
266{
267 return m_mediaDeviceReader->resumeRecording();
268}
269
270// empirical estimate of the required video bitrate (for H.264)
271quint32 QWindowsMediaDeviceSession::estimateVideoBitRate(const GUID &videoFormat, quint32 width, quint32 height,
273{
274 Q_UNUSED(videoFormat);
275
277 switch (quality) {
279 bitsPerPixel = 0.08;
280 break;
282 bitsPerPixel = 0.2;
283 break;
285 bitsPerPixel = 0.3;
286 break;
288 bitsPerPixel = 0.5;
289 break;
291 bitsPerPixel = 0.8;
292 break;
293 default:
294 bitsPerPixel = 0.3;
295 }
296
297 // Required bitrate is not linear on the number of pixels; small resolutions
298 // require more BPP, thus the minimum values, to try to compensate it.
299 quint32 pixelsPerSec = quint32(qMax(width, 320u) * qMax(height, 240u) * qMax(frameRate, 6.0));
300 return pixelsPerSec * bitsPerPixel;
301}
302
303quint32 QWindowsMediaDeviceSession::estimateAudioBitRate(const GUID &audioFormat, QMediaRecorder::Quality quality)
304{
305 if (audioFormat == MFAudioFormat_AAC) {
306 // Bitrates supported by the AAC encoder are 96K, 128K, 160K, 192K.
307 switch (quality) {
309 return 96000;
311 return 96000;
313 return 128000;
315 return 160000;
317 return 192000;
318 default:
319 return 128000;
320 }
321 } else if (audioFormat == MFAudioFormat_MP3) {
322 // Bitrates supported by the MP3 encoder are
323 // 32K, 40K, 48K, 56K, 64K, 80K, 96K, 112K, 128K, 160K, 192K, 224K, 256K, 320K.
324 switch (quality) {
326 return 48000;
328 return 96000;
330 return 128000;
332 return 224000;
334 return 320000;
335 default:
336 return 128000;
337 }
338 } else if (audioFormat == MFAudioFormat_WMAudioV8) {
339 // Bitrates supported by the Windows Media Audio 8 encoder
340 switch (quality) {
342 return 32000;
344 return 96000;
346 return 192000;
348 return 256016;
350 return 320032;
351 default:
352 return 192000;
353 }
354 } else if (audioFormat == MFAudioFormat_WMAudioV9) {
355 // Bitrates supported by the Windows Media Audio 9 encoder
356 switch (quality) {
358 return 32000;
360 return 96000;
362 return 192000;
364 return 256016;
366 return 384000;
367 default:
368 return 192000;
369 }
370 }
371 return 0; // Use default for format
372}
373
375
376#include "moc_qwindowsmediadevicesession_p.cpp"
QByteArray id
\qmlproperty string QtMultimedia::audioDevice::id
\qmltype AudioInput \instantiates QAudioInput
Definition qaudioinput.h:19
void mutedChanged(bool muted)
void volumeChanged(float volume)
QAudioDevice device
\qmlproperty AudioDevice QtMultimedia::AudioInput::device
Definition qaudioinput.h:21
void deviceChanged()
\qmltype AudioOutput \instantiates QAudioOutput
void deviceChanged()
void mutedChanged(bool muted)
QAudioDevice device
\qmlproperty AudioDevice QtMultimedia::AudioOutput::device
void volumeChanged(float volume)
The QCameraDevice class provides general information about camera devices.
QByteArray id
\qmlproperty string QtMultimedia::cameraDevice::id
The QCameraFormat class describes a video format supported by a camera device. \inmodule QtMultimedia...
Quality
\qmlproperty enumeration QtMultimedia::MediaRecorder::quality
Error
\qmlproperty enumeration QtMultimedia::MediaRecorder::error
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
virtual void setVideoFrame(const QVideoFrame &frame)
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
The QVideoFrame class represents a frame of video data.
Definition qvideoframe.h:27
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22
QPlatformVideoSink * platformVideoSink() const
void durationChanged(qint64 duration)
bool activate(const QString &cameraId, const QCameraFormat &cameraFormat, const QString &microphoneId)
void videoFrameChanged(const QVideoFrame &frame)
bool setAudioOutput(const QString &audioOutputId)
QMediaRecorder::Error startRecording(const QString &fileName, const GUID &container, const GUID &videoFormat, UINT32 videoBitRate, UINT32 width, UINT32 height, qreal frameRate, const GUID &audioFormat, UINT32 audioBitRate)
void streamingError(int errorCode)
void recordingError(int errorCode)
void videoFrameChanged(const QVideoFrame &frame)
void setActiveCamera(const QCameraDevice &camera)
QMediaRecorder::Error startRecording(QMediaEncoderSettings &settings, const QString &fileName, bool audioOnly)
void recordingError(int errorCode)
void setAudioOutput(QAudioOutput *output)
QWindowsMediaDeviceSession(QObject *parent=nullptr)
void durationChanged(qint64 duration)
void setCameraFormat(const QCameraFormat &cameraFormat)
void streamingError(int errorCode)
QCamera * camera
Definition camera.cpp:19
Combined button and popup list for selecting options.
Q_MULTIMEDIA_EXPORT GUID containerForAudioFileFormat(QMediaFormat::FileFormat format)
Q_MULTIMEDIA_EXPORT GUID audioFormatForCodec(QMediaFormat::AudioCodec codec)
Q_MULTIMEDIA_EXPORT GUID videoFormatForCodec(QMediaFormat::VideoCodec codec)
Q_MULTIMEDIA_EXPORT GUID containerForVideoFileFormat(QMediaFormat::FileFormat format)
#define Q_FUNC_INFO
#define qWarning
Definition qlogging.h:166
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLsizei GLsizei height
GLint GLsizei width
GLuint res
GLenum GLenum GLenum input
constexpr QPixelLayout::BPP bitsPerPixel()
#define emit
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
double qreal
Definition qtypes.h:187
QT_BEGIN_NAMESPACE typedef uchar * output
QSettings settings("MySoft", "Star Runner")
[0]
QFrame frame
[0]