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
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
6#include <common/mfmetadata_p.h>
7#include <mediacapture/qwindowsmediacapture_p.h>
8#include <mediacapture/qwindowsmediadevicesession_p.h>
9
10#include <QtMultimedia/private/qmediarecorder_p.h>
11#include <QtMultimedia/private/qmediastoragelocation_p.h>
12#include <QtCore/qurl.h>
13#include <QtCore/private/qcomptr_p.h>
14
15#include <mferror.h>
16#include <shobjidl.h>
17
19
21 : QObject(parent),
22 QPlatformMediaRecorder(parent)
23{
24}
25
26bool QWindowsMediaEncoder::isLocationWritable(const QUrl &location) const
27{
28 return location.scheme() == u"file" || location.scheme().isEmpty();
29}
30
32{
33 return m_state;
34}
35
37{
38 return m_duration;
39}
40
41void QWindowsMediaEncoder::record(QMediaEncoderSettings &settings)
42{
43 if (!m_captureService || !m_mediaDeviceSession) {
44 qWarning() << Q_FUNC_INFO << "Encoder is not set to a capture session";
45 return;
46 }
47 if (m_state != QMediaRecorder::StoppedState)
48 return;
49
50 m_sessionWasActive = m_mediaDeviceSession->isActive() || m_mediaDeviceSession->isActivating();
51
52 if (!m_sessionWasActive) {
53
54 m_mediaDeviceSession->setActive(true);
55
56 if (!m_mediaDeviceSession->isActivating()) {
57 updateError(QMediaRecorder::ResourceError,
58 QMediaRecorderPrivate::msgFailedStartRecording());
59 return;
60 }
61 }
62
63 const auto audioOnly = settings.videoCodec() == QMediaFormat::VideoCodec::Unspecified;
64 m_fileName = QMediaStorageLocation::generateFileName(outputLocation().toLocalFile(),
65 audioOnly ? QStandardPaths::MusicLocation
66 : QStandardPaths::MoviesLocation,
67 settings.preferredSuffix());
68
69 QMediaRecorder::Error ec = m_mediaDeviceSession->startRecording(settings, m_fileName, audioOnly);
70 if (ec == QMediaRecorder::NoError) {
71 m_state = QMediaRecorder::RecordingState;
72
73 actualLocationChanged(QUrl::fromLocalFile(m_fileName));
74 stateChanged(m_state);
75
76 } else {
77 updateError(ec, QMediaRecorderPrivate::msgFailedStartRecording());
78 }
79}
80
82{
83 if (!m_mediaDeviceSession || m_state != QMediaRecorder::RecordingState)
84 return;
85
86 if (m_mediaDeviceSession->pauseRecording()) {
87 m_state = QMediaRecorder::PausedState;
88 stateChanged(m_state);
89 } else {
90 updateError(QMediaRecorder::FormatError, tr("Failed to pause recording"));
91 }
92}
93
95{
96 if (!m_mediaDeviceSession || m_state != QMediaRecorder::PausedState)
97 return;
98
99 if (m_mediaDeviceSession->resumeRecording()) {
100 m_state = QMediaRecorder::RecordingState;
101 stateChanged(m_state);
102 } else {
103 updateError(QMediaRecorder::FormatError, tr("Failed to resume recording"));
104 }
105}
106
108{
109 if (m_mediaDeviceSession && m_state != QMediaRecorder::StoppedState) {
110 m_mediaDeviceSession->stopRecording();
111 if (!m_sessionWasActive)
112 m_mediaDeviceSession->setActive(false);
113 }
114}
115
116
117
118void QWindowsMediaEncoder::setCaptureSession(QPlatformMediaCaptureSession *session)
119{
120 QWindowsMediaCaptureService *captureSession = static_cast<QWindowsMediaCaptureService *>(session);
121 if (m_captureService == captureSession)
122 return;
123
124 if (m_captureService)
125 stop();
126
127 m_captureService = captureSession;
128 if (!m_captureService) {
129 m_mediaDeviceSession = nullptr;
130 return;
131 }
132
133 m_mediaDeviceSession = m_captureService->session();
134 Q_ASSERT(m_mediaDeviceSession);
135
136 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::recordingStarted, this, &QWindowsMediaEncoder::onRecordingStarted);
137 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::recordingStopped, this, &QWindowsMediaEncoder::onRecordingStopped);
138 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::streamingError, this, &QWindowsMediaEncoder::onStreamingError);
139 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::recordingError, this, &QWindowsMediaEncoder::onRecordingError);
140 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::durationChanged, this, &QWindowsMediaEncoder::onDurationChanged);
141 connect(m_captureService, &QWindowsMediaCaptureService::cameraChanged, this, &QWindowsMediaEncoder::onCameraChanged);
142 onCameraChanged();
143}
144
145void QWindowsMediaEncoder::setMetaData(const QMediaMetaData &metaData)
146{
147 m_metaData = metaData;
148}
149
151{
152 return m_metaData;
153}
154
155void QWindowsMediaEncoder::saveMetadata()
156{
157 if (!m_metaData.isEmpty()) {
158
159 const QString nativeFileName = QDir::toNativeSeparators(m_fileName);
160
161 ComPtr<IPropertyStore> store;
162
163 if (SUCCEEDED(SHGetPropertyStoreFromParsingName(reinterpret_cast<LPCWSTR>(nativeFileName.utf16()),
164 nullptr, GPS_READWRITE, IID_PPV_ARGS(&store)))) {
165
166 MFMetaData::toNative(m_metaData, store.Get());
167
168 store->Commit();
169 }
170 }
171}
172
173void QWindowsMediaEncoder::onDurationChanged(qint64 duration)
174{
175 m_duration = duration;
176 durationChanged(m_duration);
177}
178
179void QWindowsMediaEncoder::onStreamingError(HRESULT errorCode)
180{
181 if (errorCode == MF_E_VIDEO_RECORDING_DEVICE_INVALIDATED)
182 updateError(QMediaRecorder::ResourceError, tr("Camera is no longer present"));
183 else if (errorCode == MF_E_AUDIO_RECORDING_DEVICE_INVALIDATED)
184 updateError(QMediaRecorder::ResourceError, tr("Audio input is no longer present"));
185 else
186 updateError(QMediaRecorder::ResourceError, tr("Streaming error"));
187
188 if (m_state != QMediaRecorder::StoppedState) {
189 m_mediaDeviceSession->stopRecording();
190 if (!m_sessionWasActive)
191 m_mediaDeviceSession->setActive(false);
192 }
193}
194
195void QWindowsMediaEncoder::onRecordingError(HRESULT errorCode)
196{
197 Q_UNUSED(errorCode);
198 updateError(QMediaRecorder::ResourceError, tr("Recording error"));
199
200 auto lastState = m_state;
201 m_state = QMediaRecorder::StoppedState;
202 if (m_state != lastState)
203 stateChanged(m_state);
204}
205
206void QWindowsMediaEncoder::onCameraChanged()
207{
208}
209
210void QWindowsMediaEncoder::onRecordingStarted()
211{
212}
213
214void QWindowsMediaEncoder::onRecordingStopped()
215{
216 saveMetadata();
217
218 auto lastState = m_state;
219 m_state = QMediaRecorder::StoppedState;
220 if (m_state != lastState)
221 stateChanged(m_state);
222}
223
224QT_END_NAMESPACE
225
226#include "moc_qwindowsmediaencoder_p.cpp"
\inmodule QtMultimedia
QObject * parent
Definition qobject.h:74
QWindowsMediaDeviceSession * session() const
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
Combined button and popup list for selecting options.