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