1 ///////////////////////////////////////////////////////////////////////////////
2 // Simple x264 Launcher
3 // Copyright (C) 2004-2023 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
24 #include "source_vapoursynth.h"
32 static const unsigned int VER_X264_VSPIPE_API
= 3;
33 static const unsigned int VER_X264_VSPIPE_VER
= 46;
35 // ------------------------------------------------------------
37 // ------------------------------------------------------------
39 class VapoursyntSourceInfo
: public AbstractSourceInfo
42 virtual QString
getBinaryPath(const SysinfoModel
*const sysinfo
, const bool& x64
) const
44 return QString("%1/vspipe.exe").arg(x64
? sysinfo
->getVPS64Path() : sysinfo
->getVPS32Path());
48 static const VapoursyntSourceInfo s_vapoursynthEncoderInfo
;
50 const AbstractSourceInfo
&VapoursynthSource::getSourceInfo(void)
52 return s_vapoursynthEncoderInfo
;
55 // ------------------------------------------------------------
56 // Constructor & Destructor
57 // ------------------------------------------------------------
59 VapoursynthSource::VapoursynthSource(JobObject
*jobObject
, const OptionsModel
*options
, const SysinfoModel
*const sysinfo
, const PreferencesModel
*const preferences
, JobStatus
&jobStatus
, volatile bool *abort
, volatile bool *pause
, QSemaphore
*semaphorePause
, const QString
&sourceFile
)
61 AbstractSource(jobObject
, options
, sysinfo
, preferences
, jobStatus
, abort
, pause
, semaphorePause
, sourceFile
)
63 /*Nothing to do here*/
66 VapoursynthSource::~VapoursynthSource(void)
68 /*Nothing to do here*/
71 QString
VapoursynthSource::getName(void) const
73 return tr("VapourSynth (vpy)");
76 // ------------------------------------------------------------
78 // ------------------------------------------------------------
80 bool VapoursynthSource::isSourceAvailable()
82 if (m_sysinfo
->hasVapourSynth())
84 if (m_sysinfo
->getVapourSynth(SysinfoModel::VapourSynth_X86
) && (!m_sysinfo
->getVPS32Path().isEmpty()))
88 if (m_sysinfo
->getVapourSynth(SysinfoModel::VapourSynth_X64
) && (!m_sysinfo
->getVPS64Path().isEmpty()))
94 log(tr("\nVPY INPUT REQUIRES VAPOURSYNTH, BUT IT IS *NOT* AVAILABLE !!!"));
98 void VapoursynthSource::checkVersion_init(QList
<QRegExp
*> &patterns
, QStringList
&cmdLine
)
100 cmdLine
<< "--version";
101 patterns
<< new QRegExp("\\bVapourSynth\\b", Qt::CaseInsensitive
);
102 patterns
<< new QRegExp("\\bCore\\s+r(\\d+)\\b", Qt::CaseInsensitive
);
103 patterns
<< new QRegExp("\\bAPI\\s+r(\\d+)\\b", Qt::CaseInsensitive
);
106 void VapoursynthSource::checkVersion_parseLine(const QString
&line
, const QList
<QRegExp
*> &patterns
, unsigned int &core
, unsigned int &build
, bool &modified
)
110 if((offset
= patterns
[1]->lastIndexIn(line
)) >= 0)
113 unsigned int temp
= patterns
[1]->cap(1).toUInt(&ok
);
116 else if((offset
= patterns
[2]->lastIndexIn(line
)) >= 0)
119 unsigned int temp
= patterns
[2]->cap(1).toUInt(&ok
);
129 QString
VapoursynthSource::printVersion(const unsigned int &revision
, const bool &modified
)
131 unsigned int core
, build
;
132 splitRevision(revision
, core
, build
);
134 return tr("VapourSynth version: r%1 (API r%2)").arg(QString::number(build
), QString::number(core
));
137 bool VapoursynthSource::isVersionSupported(const unsigned int &revision
, const bool &modified
)
139 unsigned int core
, build
;
140 splitRevision(revision
, core
, build
);
142 if((build
< VER_X264_VSPIPE_VER
) || (core
< VER_X264_VSPIPE_API
))
145 if(core
< VER_X264_VSPIPE_API
)
147 log(tr("\nERROR: Your version of VapourSynth is unsupported! (requires API r%1 or newer)").arg(QString::number(VER_X264_VSPIPE_API
)));
149 if(build
< VER_X264_VSPIPE_VER
)
151 log(tr("\nERROR: Your version of VapourSynth is unsupported! (requires version r%1 or newer)").arg(QString::number(VER_X264_VSPIPE_VER
)));
153 log(tr("You can find the latest VapourSynth version at: http://www.vapoursynth.com/"));
157 if(core
!= VER_X264_VSPIPE_API
)
159 log(tr("\nWARNING: Running with an unknown VapourSynth API version, problem may appear! (this application works best with API r%1)").arg(QString::number(VER_X264_VSPIPE_API
)));
165 // ------------------------------------------------------------
166 // Check Source Properties
167 // ------------------------------------------------------------
169 void VapoursynthSource::checkSourceProperties_init(QList
<QRegExp
*> &patterns
, QStringList
&cmdLine
)
172 cmdLine
<< QDir::toNativeSeparators(x264_path2ansi(m_sourceFile
, true));
175 patterns
<< new QRegExp("\\bFrames:\\s+(\\d+)\\b");
176 patterns
<< new QRegExp("\\bWidth:\\s+(\\d+)\\b");
177 patterns
<< new QRegExp("\\bHeight:\\s+(\\d+)\\b");
178 patterns
<< new QRegExp("\\bFPS:\\s+(\\d+)\\b");
179 patterns
<< new QRegExp("\\bFPS:\\s+(\\d+)/(\\d+)\\b");
182 void VapoursynthSource::checkSourceProperties_parseLine(const QString
&line
, const QList
<QRegExp
*> &patterns
, ClipInfo
&clipInfo
)
186 if((offset
= patterns
[0]->lastIndexIn(line
)) >= 0)
189 unsigned int temp
= patterns
[0]->cap(1).toUInt(&ok
);
190 if(ok
) clipInfo
.setFrameCount(temp
);
192 if((offset
= patterns
[1]->lastIndexIn(line
)) >= 0)
195 unsigned int temp
=patterns
[1]->cap(1).toUInt(&ok
);
196 if(ok
) clipInfo
.setFrameSize(temp
, clipInfo
.getFrameSize().second
);
198 if((offset
= patterns
[2]->lastIndexIn(line
)) >= 0)
201 unsigned int temp
= patterns
[2]->cap(1).toUInt(&ok
);
202 if(ok
) clipInfo
.setFrameSize(clipInfo
.getFrameSize().first
, temp
);
204 if((offset
= patterns
[3]->lastIndexIn(line
)) >= 0)
207 unsigned int temp
= patterns
[3]->cap(1).toUInt(&ok
);
208 if(ok
) clipInfo
.setFrameRate(temp
, 0);
210 if((offset
= patterns
[4]->lastIndexIn(line
)) >= 0)
212 bool ok1
= false, ok2
= false;
213 unsigned int temp1
= patterns
[4]->cap(1).toUInt(&ok1
);
214 unsigned int temp2
= patterns
[4]->cap(2).toUInt(&ok2
);
217 clipInfo
.setFrameRate(temp1
, temp2
);
227 // ------------------------------------------------------------
229 // ------------------------------------------------------------
231 void VapoursynthSource::buildCommandLine(QStringList
&cmdLine
)
234 cmdLine
<< QDir::toNativeSeparators(x264_path2ansi(m_sourceFile
, true));
238 void VapoursynthSource::flushProcess(QProcess
&processInput
)
240 while(processInput
.bytesAvailable() > 0)
242 log(tr("vpyp [info]: %1").arg(QString::fromUtf8(processInput
.readLine()).simplified()));
245 if(processInput
.exitCode() != EXIT_SUCCESS
)
247 const int exitCode
= processInput
.exitCode();
248 log(tr("\nWARNING: Input process exited with error (code: %1), your encode might be *incomplete* !!!").arg(QString::number(exitCode
)));
249 if((exitCode
< 0) || (exitCode
>= 32))
251 log(tr("\nIMPORTANT: The Vapoursynth process terminated abnormally. This means Vapoursynth or one of your Vapoursynth-Plugin's just crashed."));