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
qwindowsmediaencoder.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
8#include "mfmetadata_p.h"
9#include <QtCore/QUrl>
10#include <QtCore/QMimeType>
11#include <mferror.h>
12#include <shobjidl.h>
13#include <private/qmediastoragelocation_p.h>
14#include <private/qmediarecorder_p.h>
15
17
23
25{
26 return location.scheme() == QLatin1String("file") || location.scheme().isEmpty();
27}
28
33
35{
36 return m_duration;
37}
38
40{
41 if (!m_captureService || !m_mediaDeviceSession) {
42 qWarning() << Q_FUNC_INFO << "Encoder is not set to a capture session";
43 return;
44 }
45 if (m_state != QMediaRecorder::StoppedState)
46 return;
47
48 m_sessionWasActive = m_mediaDeviceSession->isActive() || m_mediaDeviceSession->isActivating();
49
50 if (!m_sessionWasActive) {
51
52 m_mediaDeviceSession->setActive(true);
53
54 if (!m_mediaDeviceSession->isActivating()) {
57 return;
58 }
59 }
60
61 const auto audioOnly = settings.videoCodec() == QMediaFormat::VideoCodec::Unspecified;
65 settings.mimeType().preferredSuffix());
66
67 QMediaRecorder::Error ec = m_mediaDeviceSession->startRecording(settings, m_fileName, audioOnly);
68 if (ec == QMediaRecorder::NoError) {
70
72 stateChanged(m_state);
73
74 } else {
76 }
77}
78
80{
81 if (!m_mediaDeviceSession || m_state != QMediaRecorder::RecordingState)
82 return;
83
84 if (m_mediaDeviceSession->pauseRecording()) {
86 stateChanged(m_state);
87 } else {
88 updateError(QMediaRecorder::FormatError, tr("Failed to pause recording"));
89 }
90}
91
93{
94 if (!m_mediaDeviceSession || m_state != QMediaRecorder::PausedState)
95 return;
96
97 if (m_mediaDeviceSession->resumeRecording()) {
99 stateChanged(m_state);
100 } else {
101 updateError(QMediaRecorder::FormatError, tr("Failed to resume recording"));
102 }
103}
104
106{
107 if (m_mediaDeviceSession && m_state != QMediaRecorder::StoppedState) {
108 m_mediaDeviceSession->stopRecording();
109 if (!m_sessionWasActive)
110 m_mediaDeviceSession->setActive(false);
111 }
112}
113
114
115
117{
118 QWindowsMediaCaptureService *captureSession = static_cast<QWindowsMediaCaptureService *>(session);
119 if (m_captureService == captureSession)
120 return;
121
122 if (m_captureService)
123 stop();
124
125 m_captureService = captureSession;
126 if (!m_captureService) {
127 m_mediaDeviceSession = nullptr;
128 return;
129 }
130
131 m_mediaDeviceSession = m_captureService->session();
132 Q_ASSERT(m_mediaDeviceSession);
133
134 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::recordingStarted, this, &QWindowsMediaEncoder::onRecordingStarted);
135 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::recordingStopped, this, &QWindowsMediaEncoder::onRecordingStopped);
136 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::streamingError, this, &QWindowsMediaEncoder::onStreamingError);
137 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::recordingError, this, &QWindowsMediaEncoder::onRecordingError);
138 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::durationChanged, this, &QWindowsMediaEncoder::onDurationChanged);
139 connect(m_captureService, &QWindowsMediaCaptureService::cameraChanged, this, &QWindowsMediaEncoder::onCameraChanged);
140 onCameraChanged();
141}
142
144{
145 m_metaData = metaData;
146}
147
149{
150 return m_metaData;
151}
152
153void QWindowsMediaEncoder::saveMetadata()
154{
155 if (!m_metaData.isEmpty()) {
156
157 const QString nativeFileName = QDir::toNativeSeparators(m_fileName);
158
159 IPropertyStore *store = nullptr;
160
161 if (SUCCEEDED(SHGetPropertyStoreFromParsingName(reinterpret_cast<LPCWSTR>(nativeFileName.utf16()),
162 nullptr, GPS_READWRITE, IID_PPV_ARGS(&store)))) {
163
164 MFMetaData::toNative(m_metaData, store);
165
166 store->Commit();
167 store->Release();
168 }
169 }
170}
171
172void QWindowsMediaEncoder::onDurationChanged(qint64 duration)
173{
174 m_duration = duration;
175 durationChanged(m_duration);
176}
177
178void QWindowsMediaEncoder::onStreamingError(int errorCode)
179{
180 if (errorCode == MF_E_VIDEO_RECORDING_DEVICE_INVALIDATED)
181 updateError(QMediaRecorder::ResourceError, tr("Camera is no longer present"));
182 else if (errorCode == MF_E_AUDIO_RECORDING_DEVICE_INVALIDATED)
183 updateError(QMediaRecorder::ResourceError, tr("Audio input is no longer present"));
184 else
185 updateError(QMediaRecorder::ResourceError, tr("Streaming error"));
186
187 if (m_state != QMediaRecorder::StoppedState) {
188 m_mediaDeviceSession->stopRecording();
189 if (!m_sessionWasActive)
190 m_mediaDeviceSession->setActive(false);
191 }
192}
193
194void QWindowsMediaEncoder::onRecordingError(int errorCode)
195{
196 Q_UNUSED(errorCode);
197 updateError(QMediaRecorder::ResourceError, tr("Recording error"));
198
199 auto lastState = m_state;
201 if (m_state != lastState)
202 stateChanged(m_state);
203}
204
205void QWindowsMediaEncoder::onCameraChanged()
206{
207}
208
209void QWindowsMediaEncoder::onRecordingStarted()
210{
211}
212
213void QWindowsMediaEncoder::onRecordingStopped()
214{
215 saveMetadata();
216
217 auto lastState = m_state;
219 if (m_state != lastState)
220 stateChanged(m_state);
221}
222
224
225#include "moc_qwindowsmediaencoder_p.cpp"
static void toNative(const QMediaMetaData &metaData, IPropertyStore *content)
static QString toNativeSeparators(const QString &pathName)
Definition qdir.cpp:929
constexpr bool isEmpty() const noexcept
\inmodule QtMultimedia
Q_INVOKABLE bool isEmpty() const
\qmlmethod bool QtMultimedia::mediaMetaData::isEmpty() Returns true if the meta data contains no item...
static QString msgFailedStartRecording()
\inmodule QtMultimedia
RecorderState
\qmlproperty enumeration QtMultimedia::MediaRecorder::recorderState
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
void actualLocationChanged(const QUrl &location)
void updateError(QMediaRecorder::Error error, const QString &errorString)
void stateChanged(QMediaRecorder::RecorderState state)
void durationChanged(qint64 position)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3368
QWindowsMediaDeviceSession * session() const
QMediaRecorder::Error startRecording(QMediaEncoderSettings &settings, const QString &fileName, bool audioOnly)
void recordingError(int errorCode)
void durationChanged(qint64 duration)
void streamingError(int errorCode)
QWindowsMediaEncoder(QMediaRecorder *parent)
void setMetaData(const QMediaMetaData &metaData) override
QMediaRecorder::RecorderState state() const override
void setCaptureSession(QPlatformMediaCaptureSession *session)
QMediaMetaData metaData() const override
bool isLocationWritable(const QUrl &location) const override
qint64 duration() const override
void record(QMediaEncoderSettings &settings) override
Q_MULTIMEDIA_EXPORT QString generateFileName(const QString &requestedName, QStandardPaths::StandardLocation type, const QString &extension)
Combined button and popup list for selecting options.
#define Q_FUNC_INFO
#define qWarning
Definition qlogging.h:166
GLint location
static QString toLocalFile(const QString &url)
Definition qqmlfile.cpp:708
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define tr(X)
#define Q_UNUSED(x)
long long qint64
Definition qtypes.h:60
QSettings settings("MySoft", "Star Runner")
[0]