summaryrefslogtreecommitdiffstats
path: root/src/plugins/multimedia/windows/mediacapture/qwindowsmediaencoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/multimedia/windows/mediacapture/qwindowsmediaencoder.cpp')
-rw-r--r--src/plugins/multimedia/windows/mediacapture/qwindowsmediaencoder.cpp225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/plugins/multimedia/windows/mediacapture/qwindowsmediaencoder.cpp b/src/plugins/multimedia/windows/mediacapture/qwindowsmediaencoder.cpp
new file mode 100644
index 000000000..512110af6
--- /dev/null
+++ b/src/plugins/multimedia/windows/mediacapture/qwindowsmediaencoder.cpp
@@ -0,0 +1,225 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwindowsmediaencoder_p.h"
+
+#include "qwindowsmediadevicesession_p.h"
+#include "qwindowsmediacapture_p.h"
+#include "mfmetadata_p.h"
+#include <QtCore/QUrl>
+#include <QtCore/QMimeType>
+#include <mferror.h>
+#include <shobjidl.h>
+#include <private/qmediastoragelocation_p.h>
+#include <private/qmediarecorder_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QWindowsMediaEncoder::QWindowsMediaEncoder(QMediaRecorder *parent)
+ : QObject(parent),
+ QPlatformMediaRecorder(parent)
+{
+}
+
+bool QWindowsMediaEncoder::isLocationWritable(const QUrl &location) const
+{
+ return location.scheme() == QLatin1String("file") || location.scheme().isEmpty();
+}
+
+QMediaRecorder::RecorderState QWindowsMediaEncoder::state() const
+{
+ return m_state;
+}
+
+qint64 QWindowsMediaEncoder::duration() const
+{
+ return m_duration;
+}
+
+void QWindowsMediaEncoder::record(QMediaEncoderSettings &settings)
+{
+ if (!m_captureService || !m_mediaDeviceSession) {
+ qWarning() << Q_FUNC_INFO << "Encoder is not set to a capture session";
+ return;
+ }
+ if (m_state != QMediaRecorder::StoppedState)
+ return;
+
+ m_sessionWasActive = m_mediaDeviceSession->isActive() || m_mediaDeviceSession->isActivating();
+
+ if (!m_sessionWasActive) {
+
+ m_mediaDeviceSession->setActive(true);
+
+ if (!m_mediaDeviceSession->isActivating()) {
+ updateError(QMediaRecorder::ResourceError,
+ QMediaRecorderPrivate::msgFailedStartRecording());
+ return;
+ }
+ }
+
+ const auto audioOnly = settings.videoCodec() == QMediaFormat::VideoCodec::Unspecified;
+ m_fileName = QMediaStorageLocation::generateFileName(outputLocation().toLocalFile(), audioOnly
+ ? QStandardPaths::MusicLocation
+ : QStandardPaths::MoviesLocation,
+ settings.mimeType().preferredSuffix());
+
+ QMediaRecorder::Error ec = m_mediaDeviceSession->startRecording(settings, m_fileName, audioOnly);
+ if (ec == QMediaRecorder::NoError) {
+ m_state = QMediaRecorder::RecordingState;
+
+ actualLocationChanged(QUrl::fromLocalFile(m_fileName));
+ stateChanged(m_state);
+
+ } else {
+ updateError(ec, QMediaRecorderPrivate::msgFailedStartRecording());
+ }
+}
+
+void QWindowsMediaEncoder::pause()
+{
+ if (!m_mediaDeviceSession || m_state != QMediaRecorder::RecordingState)
+ return;
+
+ if (m_mediaDeviceSession->pauseRecording()) {
+ m_state = QMediaRecorder::PausedState;
+ stateChanged(m_state);
+ } else {
+ updateError(QMediaRecorder::FormatError, tr("Failed to pause recording"));
+ }
+}
+
+void QWindowsMediaEncoder::resume()
+{
+ if (!m_mediaDeviceSession || m_state != QMediaRecorder::PausedState)
+ return;
+
+ if (m_mediaDeviceSession->resumeRecording()) {
+ m_state = QMediaRecorder::RecordingState;
+ stateChanged(m_state);
+ } else {
+ updateError(QMediaRecorder::FormatError, tr("Failed to resume recording"));
+ }
+}
+
+void QWindowsMediaEncoder::stop()
+{
+ if (m_mediaDeviceSession && m_state != QMediaRecorder::StoppedState) {
+ m_mediaDeviceSession->stopRecording();
+ if (!m_sessionWasActive)
+ m_mediaDeviceSession->setActive(false);
+ }
+}
+
+
+
+void QWindowsMediaEncoder::setCaptureSession(QPlatformMediaCaptureSession *session)
+{
+ QWindowsMediaCaptureService *captureSession = static_cast<QWindowsMediaCaptureService *>(session);
+ if (m_captureService == captureSession)
+ return;
+
+ if (m_captureService)
+ stop();
+
+ m_captureService = captureSession;
+ if (!m_captureService) {
+ m_mediaDeviceSession = nullptr;
+ return;
+ }
+
+ m_mediaDeviceSession = m_captureService->session();
+ Q_ASSERT(m_mediaDeviceSession);
+
+ connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::recordingStarted, this, &QWindowsMediaEncoder::onRecordingStarted);
+ connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::recordingStopped, this, &QWindowsMediaEncoder::onRecordingStopped);
+ connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::streamingError, this, &QWindowsMediaEncoder::onStreamingError);
+ connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::recordingError, this, &QWindowsMediaEncoder::onRecordingError);
+ connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::durationChanged, this, &QWindowsMediaEncoder::onDurationChanged);
+ connect(m_captureService, &QWindowsMediaCaptureService::cameraChanged, this, &QWindowsMediaEncoder::onCameraChanged);
+ onCameraChanged();
+}
+
+void QWindowsMediaEncoder::setMetaData(const QMediaMetaData &metaData)
+{
+ m_metaData = metaData;
+}
+
+QMediaMetaData QWindowsMediaEncoder::metaData() const
+{
+ return m_metaData;
+}
+
+void QWindowsMediaEncoder::saveMetadata()
+{
+ if (!m_metaData.isEmpty()) {
+
+ const QString nativeFileName = QDir::toNativeSeparators(m_fileName);
+
+ IPropertyStore *store = nullptr;
+
+ if (SUCCEEDED(SHGetPropertyStoreFromParsingName(reinterpret_cast<LPCWSTR>(nativeFileName.utf16()),
+ nullptr, GPS_READWRITE, IID_PPV_ARGS(&store)))) {
+
+ MFMetaData::toNative(m_metaData, store);
+
+ store->Commit();
+ store->Release();
+ }
+ }
+}
+
+void QWindowsMediaEncoder::onDurationChanged(qint64 duration)
+{
+ m_duration = duration;
+ durationChanged(m_duration);
+}
+
+void QWindowsMediaEncoder::onStreamingError(int errorCode)
+{
+ if (errorCode == MF_E_VIDEO_RECORDING_DEVICE_INVALIDATED)
+ updateError(QMediaRecorder::ResourceError, tr("Camera is no longer present"));
+ else if (errorCode == MF_E_AUDIO_RECORDING_DEVICE_INVALIDATED)
+ updateError(QMediaRecorder::ResourceError, tr("Audio input is no longer present"));
+ else
+ updateError(QMediaRecorder::ResourceError, tr("Streaming error"));
+
+ if (m_state != QMediaRecorder::StoppedState) {
+ m_mediaDeviceSession->stopRecording();
+ if (!m_sessionWasActive)
+ m_mediaDeviceSession->setActive(false);
+ }
+}
+
+void QWindowsMediaEncoder::onRecordingError(int errorCode)
+{
+ Q_UNUSED(errorCode);
+ updateError(QMediaRecorder::ResourceError, tr("Recording error"));
+
+ auto lastState = m_state;
+ m_state = QMediaRecorder::StoppedState;
+ if (m_state != lastState)
+ stateChanged(m_state);
+}
+
+void QWindowsMediaEncoder::onCameraChanged()
+{
+}
+
+void QWindowsMediaEncoder::onRecordingStarted()
+{
+}
+
+void QWindowsMediaEncoder::onRecordingStopped()
+{
+ saveMetadata();
+
+ auto lastState = m_state;
+ m_state = QMediaRecorder::StoppedState;
+ if (m_state != lastState)
+ stateChanged(m_state);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qwindowsmediaencoder_p.cpp"