OSDN Git Service

Refactored code to better manage the encoder binary paths: They are now handled by...
[x264-launcher/x264-launcher.git] / src / source_vapoursynth.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Simple x264 Launcher
3 // Copyright (C) 2004-2015 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
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.
9 //
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.
14 //
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.
18 //
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #pragma once
23
24 #include "source_vapoursynth.h"
25
26 #include "global.h"
27 #include "model_sysinfo.h"
28 #include "model_preferences.h"
29 #include "binaries.h"
30
31 #include <QDir>
32 #include <QProcess>
33
34 static const unsigned int VER_X264_VSPIPE_API =  3;
35 static const unsigned int VER_X264_VSPIPE_VER = 24;
36
37 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)
38 :
39         AbstractSource(jobObject, options, sysinfo, preferences, jobStatus, abort, pause, semaphorePause, sourceFile),
40         m_sourceName("VapourSynth (vpy)"),
41         m_binaryFile(VPS_BINARY(m_sysinfo, m_preferences))
42 {
43         /*Nothing to do here*/
44 }
45
46 VapoursynthSource::~VapoursynthSource(void)
47 {
48         /*Nothing to do here*/
49 }
50
51 QString VapoursynthSource::getName(void) const
52 {
53         return m_sourceName;
54 }
55
56 // ------------------------------------------------------------
57 // Check Version
58 // ------------------------------------------------------------
59
60 bool VapoursynthSource::isSourceAvailable()
61 {
62         if(!(m_sysinfo->hasVapourSynth() && (!m_sysinfo->getVPSPath().isEmpty()) && QFileInfo(VPS_BINARY(m_sysinfo, m_preferences)).isFile()))
63         {
64                 log(tr("\nVPY INPUT REQUIRES VAPOURSYNTH, BUT IT IS *NOT* AVAILABLE !!!"));
65                 return false;
66         }
67         return true;
68 }
69
70 void VapoursynthSource::checkVersion_init(QList<QRegExp*> &patterns, QStringList &cmdLine)
71 {
72         cmdLine << "--version";
73         patterns << new QRegExp("\\bVapourSynth\\b", Qt::CaseInsensitive);
74         patterns << new QRegExp("\\bCore\\s+r(\\d+)\\b", Qt::CaseInsensitive);
75         patterns << new QRegExp("\\bAPI\\s+r(\\d+)\\b", Qt::CaseInsensitive);
76 }
77
78 void VapoursynthSource::checkVersion_parseLine(const QString &line, QList<QRegExp*> &patterns, unsigned int &core, unsigned int &build, bool &modified)
79 {
80         int offset = -1;
81
82         if((offset = patterns[1]->lastIndexIn(line)) >= 0)
83         {
84                 bool ok = false;
85                 unsigned int temp = patterns[1]->cap(1).toUInt(&ok);
86                 if(ok) build = temp;
87         }
88         else if((offset = patterns[2]->lastIndexIn(line)) >= 0)
89         {
90                 bool ok = false;
91                 unsigned int temp = patterns[2]->cap(1).toUInt(&ok);
92                 if(ok) core = temp;
93         }
94
95         if(!line.isEmpty())
96         {
97                 log(line);
98         }
99 }
100
101 QString VapoursynthSource::printVersion(const unsigned int &revision, const bool &modified)
102 {
103         unsigned int core, build;
104         splitRevision(revision, core, build);
105
106         return tr("\nVapourSynth version: r%1 (API r%2)").arg(QString::number(build), QString::number(core));
107 }
108
109 bool VapoursynthSource::isVersionSupported(const unsigned int &revision, const bool &modified)
110 {
111         unsigned int core, build;
112         splitRevision(revision, core, build);
113
114         if((build < VER_X264_VSPIPE_VER) || (core < VER_X264_VSPIPE_API))
115         {
116                 
117                 if(core < VER_X264_VSPIPE_API)
118                 {
119                         log(tr("\nERROR: Your version of VapourSynth is unsupported! (requires API r%1 or newer)").arg(QString::number(VER_X264_VSPIPE_API)));
120                 }
121                 if(build < VER_X264_VSPIPE_VER)
122                 {
123                         log(tr("\nERROR: Your version of VapourSynth is unsupported! (requires version r%1 or newer)").arg(QString::number(VER_X264_VSPIPE_VER)));
124                 }
125                 log(tr("You can find the latest VapourSynth version at: http://www.vapoursynth.com/"));
126                 return false;
127         }
128
129         if(core != VER_X264_VSPIPE_API)
130         {
131                 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)));
132         }
133
134         return true;
135 }
136
137 // ------------------------------------------------------------
138 // Check Source Properties
139 // ------------------------------------------------------------
140
141 void VapoursynthSource::checkSourceProperties_init(QList<QRegExp*> &patterns, QStringList &cmdLine)
142 {
143         cmdLine << "--info";
144         cmdLine << QDir::toNativeSeparators(x264_path2ansi(m_sourceFile, true));
145         cmdLine << "-";
146
147         patterns << new QRegExp("\\bFrames:\\s+(\\d+)\\b");
148         patterns << new QRegExp("\\bWidth:\\s+(\\d+)\\b");
149         patterns << new QRegExp("\\bHeight:\\s+(\\d+)\\b");
150         patterns << new QRegExp("\\bFPS:\\s+(\\d+)\\b");
151         patterns << new QRegExp("\\bFPS:\\s+(\\d+)/(\\d+)\\b");
152 }
153
154 void VapoursynthSource::checkSourceProperties_parseLine(const QString &line, QList<QRegExp*> &patterns, unsigned int &frames, unsigned int &fSizeW, unsigned int &fSizeH, unsigned int &fpsNom, unsigned int &fpsDen)
155 {
156         int offset = -1;
157
158         if((offset = patterns[0]->lastIndexIn(line)) >= 0)
159         {
160                 bool ok = false;
161                 unsigned int temp = patterns[0]->cap(1).toUInt(&ok);
162                 if(ok) frames = temp;
163         }
164         if((offset = patterns[1]->lastIndexIn(line)) >= 0)
165         {
166                 bool ok = false;
167                 unsigned int temp =patterns[1]->cap(1).toUInt(&ok);
168                 if(ok) fSizeW = temp;
169         }
170         if((offset = patterns[2]->lastIndexIn(line)) >= 0)
171         {
172                 bool ok = false;
173                 unsigned int temp = patterns[2]->cap(1).toUInt(&ok);
174                 if(ok) fSizeH = temp;
175         }
176         if((offset = patterns[3]->lastIndexIn(line)) >= 0)
177         {
178                 bool ok = false;
179                 unsigned int temp = patterns[3]->cap(1).toUInt(&ok);
180                 if(ok) fpsNom = temp;
181         }
182         if((offset = patterns[4]->lastIndexIn(line)) >= 0)
183         {
184                 bool ok1 = false, ok2 = false;
185                 unsigned int temp1 = patterns[4]->cap(1).toUInt(&ok1);
186                 unsigned int temp2 = patterns[4]->cap(2).toUInt(&ok2);
187                 if(ok1 && ok2)
188                 {
189                         fpsNom = temp1;
190                         fpsDen = temp2;
191                 }
192         }
193
194         if(!line.isEmpty())
195         {
196                 log(line);
197         }
198 }
199
200 // ------------------------------------------------------------
201 // Check Source Properties
202 // ------------------------------------------------------------
203
204 void VapoursynthSource::buildCommandLine(QStringList &cmdLine)
205 {
206         cmdLine << "--y4m";
207         cmdLine << QDir::toNativeSeparators(x264_path2ansi(m_sourceFile, true));
208         cmdLine << "-";
209 }
210
211 void VapoursynthSource::flushProcess(QProcess &processInput)
212 {
213         while(processInput.bytesAvailable() > 0)
214         {
215                 log(tr("vpyp [info]: %1").arg(QString::fromUtf8(processInput.readLine()).simplified()));
216         }
217         
218         if(processInput.exitCode() != EXIT_SUCCESS)
219         {
220                 const int exitCode = processInput.exitCode();
221                 log(tr("\nWARNING: Input process exited with error (code: %1), your encode might be *incomplete* !!!").arg(QString::number(exitCode)));
222                 if((exitCode < 0) || (exitCode >= 32))
223                 {
224                         log(tr("\nIMPORTANT: The Vapoursynth process terminated abnormally. This means Vapoursynth or one of your Vapoursynth-Plugin's just crashed."));
225                 }
226         }
227 }