Krita Source Code Documentation
Loading...
Searching...
No Matches
KisMediaEncoderWrapper.cpp
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: GPL-3.0-or-later
3 */
4#include <QAtomicInt>
5#include <QImage>
6#include <QImageReader>
7#include <QRunnable>
8#include <QThreadPool>
9
10#include <functional>
11
12#include <klocalizedstring.h>
13
15
16#include <kis_assert.h>
17#include <kis_debug.h>
18
19#ifdef Q_OS_ANDROID
21#endif
22
27
29{
30 Q_EMIT sigStarted();
31 QString errorMessage;
32 EncodeResult result = prepareAndEncode(errorMessage);
33 if (result == EncodeResult::Completed) {
34 Q_EMIT sigCompleted();
35 } else if (result == EncodeResult::Cancelled) {
36 Q_EMIT sigCancelled();
37 } else {
38 Q_EMIT sigFailed(errorMessage);
39 }
40}
41
43{
44 QImageReader reader(m_path);
45 if (reader.read(&outImage)) {
46 // Should be non-null on success, but we'll guard against mayhem.
47 if (outImage.isNull() || outImage.size().isEmpty()) {
48 warnFile.nospace() << "Got null image reading frame from file '" << m_path << "'";
49 return false;
50 } else {
51 return true;
52 }
53 } else {
54 warnFile.nospace() << "Error " << reader.error() << " reading frame from file '" << m_path
55 << "': " << reader.errorString();
56 // Again, should be null anyway, but let's be extra sure.
57 outImage = QImage();
58 return false;
59 }
60}
61
67
69{
70 int inputFileCount = m_settings.inputFiles.size();
71 if (inputFileCount == 0) {
72 return false;
73 }
74
75 int lastIndex = inputFileCount - 1;
78 int seconds = m_settings.firstFrameSec;
79 if (seconds > 0) {
80 outFrame = Frame(m_settings.inputFiles[lastIndex], seconds * m_settings.outputFps);
81 return true;
82 }
83 }
84
85 double inputFrameDuration = 1.0 / double(m_settings.inputFps);
86 double outputFrameDuration = 1.0 / double(m_settings.outputFps);
87 while (m_inputFileIndex < inputFileCount) {
88 int fileIndex = m_inputFileIndex;
90
91 int instances = 0;
92 double nextInputTime = double(m_inputFileIndex) * inputFrameDuration;
93 while (m_inputTime < nextInputTime) {
94 ++instances;
95 m_inputTime += outputFrameDuration;
96 }
97
98 if (instances != 0) {
99 m_outputFrameNo += instances;
101
102 // If we're on the last frame, we can append the linger time.
103 if (fileIndex == lastIndex && m_needsLingerAfter) {
104 m_needsLingerAfter = false;
105 instances += qMax(0, m_settings.lastFrameSec) * m_settings.outputFps;
106 }
107
108 outFrame = Frame(m_settings.inputFiles[fileIndex], instances);
109 return true;
110 }
111 }
112
113 if (m_needsLingerAfter) {
114 m_needsLingerAfter = false;
115 int seconds = m_settings.lastFrameSec;
116 if (seconds > 0) {
117 outFrame = Frame(m_settings.inputFiles[lastIndex], seconds * m_settings.outputFps);
118 return true;
119 }
120 }
121
122 return false;
123}
124
126{
127 if (m_cancel) {
129 }
130
131 if (m_settings.inputFiles.isEmpty()) {
132 outErrorMessage = i18n("No frame files found");
134 }
135
137 return encode(outErrorMessage);
138}
139
141 : QObject(parent)
142{
143}
144
149
151{
152 reset();
153
155 if (runnable) {
156 connect(runnable,
158 this,
160 Qt::QueuedConnection);
161 connect(runnable,
163 this,
165 Qt::QueuedConnection);
166 connect(runnable,
168 this,
170 Qt::QueuedConnection);
171 connect(runnable,
173 this,
175 Qt::QueuedConnection);
176 connect(runnable,
178 this,
180 Qt::QueuedConnection);
181 connect(this,
183 runnable,
185 Qt::QueuedConnection);
186
187 m_runnable = runnable;
188 runnable->setAutoDelete(true);
189 QThreadPool::globalInstance()->start(runnable);
190
191 } else {
192 Q_EMIT sigFinishedWithError(i18n("No encoder for the selected format found"));
193 }
194}
195
197{
198 KisMediaEncoderRunnable *runnable = m_runnable.data();
199 if (runnable) {
200 m_runnable.clear();
201 Q_EMIT sigCancelRequested();
202 disconnect(runnable);
203 }
204}
205
207{
208 static QVector<KisMediaEncoderFormat *> *supportedFormats;
209 if (!supportedFormats) {
210 supportedFormats = new QVector<KisMediaEncoderFormat *>();
211#ifdef Q_OS_ANDROID
213#endif
214 }
215 return *supportedFormats;
216}
217
219{
221 if (format->key() == key) {
222 return format;
223 }
224 }
225 return nullptr;
226}
227
229{
231
232#ifdef Q_OS_ANDROID
233 {
235 if (androidRunnable) {
236 return androidRunnable;
237 }
238 }
239#endif
240
241 return nullptr;
242}
static void getSupportedFormats(QVector< KisMediaEncoderFormat * > &outSupportedFormats)
static KisAndroidMediaEncoderRunnable * create(const KisMediaEncoderWrapperSettings &settings, QObject *parent=nullptr)
bool readImage(QImage &outImage) const
KisMediaEncoderRunnable(const KisMediaEncoderWrapperSettings &settings, QObject *parent)
const KisMediaEncoderWrapperSettings settings()
bool nextFrame(Frame &outFrame)
KisMediaEncoderWrapperSettings m_settings
void sigFailed(const QString &errorMessage)
EncodeResult prepareAndEncode(QString &outErrorMessage)
virtual EncodeResult encode(QString &outErrorMessage)=0
void sigProgressUpdated(int frameNo)
static KisMediaEncoderFormat * getFormatByKey(const QString &key)
void sigFinishedWithError(QString message)
QPointer< KisMediaEncoderRunnable > m_runnable
KisMediaEncoderWrapper(QObject *parent=nullptr)
void sigProgressUpdated(int frameNo)
static const QVector< KisMediaEncoderFormat * > & getSupportedFormats()
static KisMediaEncoderRunnable * makeSupportedRunnable(const KisMediaEncoderWrapperSettings &settings)
void startNonBlocking(const KisMediaEncoderWrapperSettings &settings)
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define warnFile
Definition kis_debug.h:95