Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAnimationVideoSaver Class Reference

#include <KisVideoSaver.h>

+ Inheritance diagram for KisAnimationVideoSaver:

Public Member Functions

KisImportExportErrorCode encode (const QString &savedFilesMask, const KisAnimationRenderingOptions &options)
 encode the main encoding function. This in turn calls runFFMpeg, which is a private function inside this class.
 
KisImageSP image ()
 image
 
 KisAnimationVideoSaver (KisDocument *doc, bool batchMode)
 KisAnimationVideoSaver This is the object that takes an animation document and config and tells ffmpeg to render it via KisFFMpegWrapper.
 
 ~KisAnimationVideoSaver () override
 

Static Public Member Functions

static KisImportExportErrorCode convert (KisDocument *document, const QString &savedFilesMask, const KisAnimationRenderingOptions &options, bool batchMode)
 

Private Attributes

bool m_batchMode
 
KisDocumentm_doc
 
KisImageSP m_image
 

Detailed Description

Definition at line 21 of file KisVideoSaver.h.

Constructor & Destructor Documentation

◆ KisAnimationVideoSaver()

KisAnimationVideoSaver::KisAnimationVideoSaver ( KisDocument * doc,
bool batchMode )

KisAnimationVideoSaver This is the object that takes an animation document and config and tells ffmpeg to render it via KisFFMpegWrapper.

Parameters
docthe document to use for rendering.
ffmpegPaththe path to the ffmpeg executable.
batchModewhether Krita is in batchmode and we can thus not show gui widgets.

Definition at line 33 of file KisVideoSaver.cpp.

34 : m_image(doc->image())
35 , m_doc(doc)
36 , m_batchMode(batchMode)
37{
38}
KisImageSP image

◆ ~KisAnimationVideoSaver()

KisAnimationVideoSaver::~KisAnimationVideoSaver ( )
override

Definition at line 40 of file KisVideoSaver.cpp.

41{
42}

Member Function Documentation

◆ convert()

KisImportExportErrorCode KisAnimationVideoSaver::convert ( KisDocument * document,
const QString & savedFilesMask,
const KisAnimationRenderingOptions & options,
bool batchMode )
static

Definition at line 207 of file KisVideoSaver.cpp.

208{
209 KisAnimationVideoSaver videoSaver(document, batchMode);
210 KisImportExportErrorCode res = videoSaver.encode(savedFilesMask, options);
211 return res;
212}

References encode().

◆ encode()

KisImportExportErrorCode KisAnimationVideoSaver::encode ( const QString & savedFilesMask,
const KisAnimationRenderingOptions & options )

encode the main encoding function. This in turn calls runFFMpeg, which is a private function inside this class.

Parameters
filenamethe filename to which to render the animation.
configurationthe configuration
Returns
whether it is successful or had another failure.

Definition at line 49 of file KisVideoSaver.cpp.

50{
51 if (!QFileInfo(options.ffmpegPath).exists()) {
52 m_doc->setErrorMessage(i18n("ffmpeg could not be found at %1", options.ffmpegPath));
54 }
55
57
59
60 const int sequenceStart = options.sequenceStart;
61 const KisTimeSpan clipRange = KisTimeSpan::fromTimeToTime(options.firstFrame,
62 options.lastFrame);
63
64 // export dimensions could be off a little bit, so the last force option tweaks the pixels for the export to work
65 const QString exportDimensions =
66 QString("scale=w=")
67 .append(QString::number(options.width))
68 .append(":h=")
69 .append(QString::number(options.height))
70 .append(":flags=")
71 .append(options.scaleFilter);
72 //.append(":force_original_aspect_ratio=decrease"); HOTFIX for even:odd dimension images.
73
74 const QString resultFile = options.resolveAbsoluteVideoFilePath();
75 const QFileInfo resultFileInfo(resultFile);
76 const QDir videoDir(resultFileInfo.absolutePath());
77
78 const QString suffix = resultFileInfo.suffix().toLower();
79 const QString palettePath = videoDir.filePath("KritaTempPalettegen_\%06d.png");
80
81 QStringList additionalOptionsList = options.customFFMpegOptions.split(' ', Qt::SkipEmptyParts);
82
83 QScopedPointer<KisFFMpegWrapper> ffmpegWrapper(new KisFFMpegWrapper(this));
84
85 {
86 QStringList paletteArgs;
87 QStringList simpleFilterArgs;
88 QStringList complexFilterArgs;
89 QStringList args;
90
91 args << "-y" // Auto Confirm...
92 << "-r" << QString::number(options.frameRate) // Frame rate for video...
93 << "-start_number" << QString::number(sequenceStart) << "-start_number_range" << "1"
94 << "-i" << savedFilesMask; // Input frame(s) file mask..
95
96 const int lavfiOptionsIndex = additionalOptionsList.indexOf("-lavfi");
97
98 if ( lavfiOptionsIndex != -1 ) {
99 complexFilterArgs << additionalOptionsList.takeAt(lavfiOptionsIndex + 1);
100
101 additionalOptionsList.removeAt( lavfiOptionsIndex );
102 }
103
104 if ( options.videoMimeType == "image/gif" ) {
105 paletteArgs << "-r" << QString::number(options.frameRate)
106 << "-start_number" << QString::number(sequenceStart) << "-start_number_range" << "1"
107 << "-i" << savedFilesMask;
108
109 const int paletteOptionsIndex = additionalOptionsList.indexOf("-palettegen");
110 QString palettegenString = "palettegen";
111
112 if ( paletteOptionsIndex != -1 ) {
113 palettegenString = additionalOptionsList.takeAt(paletteOptionsIndex + 1);
114
115 additionalOptionsList.removeAt( paletteOptionsIndex );
116 }
117
118 if (m_image->width() != options.width || m_image->height() != options.height) {
119 paletteArgs << "-vf" << (exportDimensions + "," + palettegenString );
120 } else {
121 paletteArgs << "-vf" << palettegenString;
122 }
123
124 paletteArgs << "-y" << palettePath;
125
126 QStringList ffmpegArgs;
127 ffmpegArgs << "-v" << "debug"
128 << paletteArgs;
129
130 KisFFMpegWrapperSettings ffmpegSettings;
131 ffmpegSettings.args = ffmpegArgs;
132 ffmpegSettings.processPath = options.ffmpegPath;
133
134 ffmpegSettings.progressIndeterminate = true;
135 ffmpegSettings.progressMessage = i18nc("Animation export dialog for palette exporting. arg1: file-suffix",
136 "Creating palette for %1 file format.", "[suffix]");
137 ffmpegSettings.logPath = QDir::tempPath() + QDir::separator() + "krita" + QDir::separator() + "ffmpeg.log";
138
139 KisImportExportErrorCode result = ffmpegWrapper->start(ffmpegSettings);
140
141 if (!result.isOk()) {
142 return result;
143 }
144
145 if (lavfiOptionsIndex == -1) {
146 complexFilterArgs << "[0:v][1:v] paletteuse";
147 }
148
149 args << "-i" << palettePath;
150
151 // We need to kill the process so we can reuse it later down the chain. BUG:446320
152 ffmpegWrapper->reset();
153 }
154
156 if (options.includeAudio && audioFiles.count() > 0 && audioFiles.first().exists()) {
157 QFileInfo audioFileInfo = audioFiles.first();
158 const int msecPerFrame = (1000 / animation->framerate());
159 const int msecStart = msecPerFrame * clipRange.start();
160 const int msecDuration = msecPerFrame * clipRange.duration();
161
162 const QTime startTime = QTime::fromMSecsSinceStartOfDay(msecStart);
163 const QTime durationTime = QTime::fromMSecsSinceStartOfDay(msecDuration);
164 const QString ffmpegTimeFormat = QStringLiteral("H:m:s.zzz");
165
166 args << "-ss" << QLocale::c().toString(startTime, ffmpegTimeFormat);
167 args << "-t" << QLocale::c().toString(durationTime, ffmpegTimeFormat);
168 args << "-i" << audioFileInfo.absoluteFilePath();
169 }
170
171 // if we are exporting out at a different image size, we apply scaling filter
172 // export options HAVE to go after input options, so make sure this is after the audio import
173 if (m_image->width() != options.width || m_image->height() != options.height) {
174 simpleFilterArgs << exportDimensions;
175 }
176
177 if ( !complexFilterArgs.isEmpty() ) {
178 args << "-lavfi" << (!simpleFilterArgs.isEmpty() ? simpleFilterArgs.join(",").append("[0:v];"):"") + complexFilterArgs.join(";");
179 } else if ( !simpleFilterArgs.isEmpty() ) {
180 args << "-vf" << simpleFilterArgs.join(",");
181 }
182
183 args << additionalOptionsList;
184
185 dbgFile << "savedFilesMask" << savedFilesMask
186 << "save files offset" << sequenceStart
187 << "start" << QString::number(clipRange.start())
188 << "duration" << clipRange.duration();
189
190
191 KisFFMpegWrapperSettings ffmpegSettings;
192 ffmpegSettings.processPath = options.ffmpegPath;
193 ffmpegSettings.args = args;
194 ffmpegSettings.outputFile = resultFile;
195 ffmpegSettings.totalFrames = clipRange.duration();
196 ffmpegSettings.logPath = QDir::tempPath() + QDir::separator() + "krita" + QDir::separator() + "ffmpeg.log";
197 ffmpegSettings.progressMessage = i18nc("Animation export dialog for tracking ffmpeg progress. arg1: file-suffix, arg2: progress frame number, arg3: totalFrameCount.",
198 "Creating desired %1 file: %2/%3 frames.", "[suffix]", "[progress]", "[framecount]");
199
200 resultOuter = ffmpegWrapper->start(ffmpegSettings);
201 }
202
203
204 return resultOuter;
205}
QString resolveAbsoluteVideoFilePath(const QString &documentPath) const
void setErrorMessage(const QString &errMsg)
QVector< QFileInfo > getAudioTracks() const
KisImageAnimationInterface * animationInterface() const
qint32 width() const
qint32 height() const
int start() const
int duration() const
static KisTimeSpan fromTimeToTime(int start, int end)
#define dbgFile
Definition kis_debug.h:53

References KisImage::animationInterface(), KisFFMpegWrapperSettings::args, KisAnimationRenderingOptions::customFFMpegOptions, dbgFile, KisTimeSpan::duration(), ImportExportCodes::Failure, KisAnimationRenderingOptions::ffmpegPath, KisAnimationRenderingOptions::firstFrame, KisImageAnimationInterface::framerate(), KisAnimationRenderingOptions::frameRate, KisTimeSpan::fromTimeToTime(), KisDocument::getAudioTracks(), KisImage::height(), KisAnimationRenderingOptions::height, KisAnimationRenderingOptions::includeAudio, KisImportExportErrorCode::isOk(), KisAnimationRenderingOptions::lastFrame, KisFFMpegWrapperSettings::logPath, m_doc, m_image, ImportExportCodes::OK, KisFFMpegWrapperSettings::outputFile, KisFFMpegWrapperSettings::processPath, KisFFMpegWrapperSettings::progressIndeterminate, KisFFMpegWrapperSettings::progressMessage, KisAnimationRenderingOptions::resolveAbsoluteVideoFilePath(), KisAnimationRenderingOptions::scaleFilter, KisAnimationRenderingOptions::sequenceStart, KisDocument::setErrorMessage(), KisTimeSpan::start(), KisFFMpegWrapperSettings::totalFrames, KisAnimationRenderingOptions::videoMimeType, KisImage::width(), and KisAnimationRenderingOptions::width.

◆ image()

KisImageSP KisAnimationVideoSaver::image ( )

image

Returns
get the image used by this exporter.

Definition at line 44 of file KisVideoSaver.cpp.

45{
46 return m_image;
47}

References m_image.

Member Data Documentation

◆ m_batchMode

bool KisAnimationVideoSaver::m_batchMode
private

Definition at line 55 of file KisVideoSaver.h.

◆ m_doc

KisDocument* KisAnimationVideoSaver::m_doc
private

Definition at line 54 of file KisVideoSaver.h.

◆ m_image

KisImageSP KisAnimationVideoSaver::m_image
private

Definition at line 53 of file KisVideoSaver.h.


The documentation for this class was generated from the following files: