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
qffmpegmediarecorder.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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#include "qaudiodevice.h"
6#include <private/qmediastoragelocation_p.h>
7#include <private/qplatformcamera_p.h>
8#include <private/qplatformsurfacecapture_p.h>
9#include "qaudiosource.h"
10#include "qffmpegaudioinput_p.h"
11#include "qaudiobuffer.h"
14
15#include <qdebug.h>
16#include <qloggingcategory.h>
17
18static Q_LOGGING_CATEGORY(qLcMediaEncoder, "qt.multimedia.ffmpeg.encoder");
19
21
25
27
29{
30 return true;
31}
32
33void QFFmpegMediaRecorder::handleSessionError(QMediaRecorder::Error code, const QString &description)
34{
35 updateError(code, description);
36 stop();
37}
38
40{
41 if (!m_session || state() != QMediaRecorder::StoppedState)
42 return;
43
44 auto videoSources = m_session->activeVideoSources();
45 const auto hasVideo = !videoSources.empty();
46 const auto hasAudio = m_session->audioInput() != nullptr;
47
48 if (!hasVideo && !hasAudio) {
49 updateError(QMediaRecorder::ResourceError, QMediaRecorder::tr("No video or audio input"));
50 return;
51 }
52
53 if (outputDevice() && !outputLocation().isEmpty())
54 qCWarning(qLcMediaEncoder)
55 << "Both outputDevice and outputLocation has been set to QMediaRecorder";
56
57 if (outputDevice() && !outputDevice()->isWritable())
58 qCWarning(qLcMediaEncoder) << "Output device has been set but not it's not writable";
59
61 auto formatContext = std::make_unique<QFFmpeg::EncodingFormatContext>(settings.fileFormat());
62
63 if (outputDevice() && outputDevice()->isWritable()) {
64 formatContext->openAVIO(outputDevice());
65 } else {
67 qCDebug(qLcMediaEncoder) << "recording new media to" << actualLocation;
68 formatContext->openAVIO(actualLocation);
69 }
70
71 qCDebug(qLcMediaEncoder) << "requested format:" << settings.fileFormat()
72 << settings.audioCodec();
73
74 if (!formatContext->isAVIOOpen()) {
76 QMediaRecorder::tr("Cannot open the output location for writing"));
77 return;
78 }
79
80 m_recordingEngine.reset(new RecordingEngine(settings, std::move(formatContext)));
81 m_recordingEngine->setMetaData(m_metaData);
82 connect(m_recordingEngine.get(), &QFFmpeg::RecordingEngine::durationChanged, this,
83 &QFFmpegMediaRecorder::newDuration);
84 connect(m_recordingEngine.get(), &QFFmpeg::RecordingEngine::finalizationDone, this,
85 &QFFmpegMediaRecorder::finalizationDone);
86 connect(m_recordingEngine.get(), &QFFmpeg::RecordingEngine::sessionError, this,
87 &QFFmpegMediaRecorder::handleSessionError);
88
89 auto handleStreamInitializationError = [this](QMediaRecorder::Error code,
90 const QString &description) {
91 qCWarning(qLcMediaEncoder) << "Stream initialization error:" << description;
92 updateError(code, description);
93 };
94
96 handleStreamInitializationError);
97
101
102 m_recordingEngine->initialize(static_cast<QFFmpegAudioInput *>(m_session->audioInput()),
103 videoSources);
104}
105
107{
108 if (!m_session || state() != QMediaRecorder::RecordingState)
109 return;
110
111 Q_ASSERT(m_recordingEngine);
112 m_recordingEngine->setPaused(true);
113
115}
116
118{
119 if (!m_session || state() != QMediaRecorder::PausedState)
120 return;
121
122 Q_ASSERT(m_recordingEngine);
123 m_recordingEngine->setPaused(false);
124
126}
127
129{
130 if (!m_session || state() == QMediaRecorder::StoppedState)
131 return;
132 auto * input = m_session ? m_session->audioInput() : nullptr;
133 if (input)
134 static_cast<QFFmpegAudioInput *>(input)->setRunning(false);
135 qCDebug(qLcMediaEncoder) << "stop";
136
137 m_recordingEngine.reset();
138}
139
140void QFFmpegMediaRecorder::finalizationDone()
141{
143}
144
146{
147 if (!m_session)
148 return;
149 m_metaData = metaData;
150}
151
153{
154 return m_metaData;
155}
156
158{
159 auto *captureSession = session;
160 if (m_session == captureSession)
161 return;
162
163 if (m_session)
164 stop();
165
166 m_session = captureSession;
167 if (!m_session)
168 return;
169}
170
171void QFFmpegMediaRecorder::RecordingEngineDeleter::operator()(
172 RecordingEngine *recordingEngine) const
173{
174 // ### all of the below should be done asynchronous. finalize() should do it's work in a thread
175 // to avoid blocking the UI in case of slow codecs
176 recordingEngine->finalize();
177}
178
180
181#include "moc_qffmpegmediarecorder_p.cpp"
void setCaptureSession(QFFmpegMediaCaptureSession *session)
void record(QMediaEncoderSettings &settings) override
bool isLocationWritable(const QUrl &sink) const override
virtual ~QFFmpegMediaRecorder()
QMediaMetaData metaData() const override
void setMetaData(const QMediaMetaData &) override
QFFmpegMediaRecorder(QMediaRecorder *parent)
void sessionError(QMediaRecorder::Error code, const QString &description)
void durationChanged(qint64 duration)
void streamInitializationError(QMediaRecorder::Error code, const QString &description)
\inmodule QtMultimedia
\inmodule QtMultimedia
Error
\qmlproperty enumeration QtMultimedia::MediaRecorder::error
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
std::vector< QPlatformVideoSource * > activeVideoSources()
void actualLocationChanged(const QUrl &location)
void updateError(QMediaRecorder::Error error, const QString &errorString)
void stateChanged(QMediaRecorder::RecorderState state)
void durationChanged(qint64 position)
virtual QMediaRecorder::RecorderState state() const
QString findActualLocation(const QMediaEncoderSettings &settings) const
\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
Combined button and popup list for selecting options.
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLenum GLenum GLenum input
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QSettings settings("MySoft", "Star Runner")
[0]