OSDN Git Service

Added support for detecting "portable" Avisynth.
[x264-launcher/x264-launcher.git] / src / source_abstract.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Simple x264 Launcher
3 // Copyright (C) 2004-2016 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 #include "source_abstract.h"
23
24 //Internal
25 #include "global.h"
26 #include "model_sysinfo.h"
27 #include "model_options.h"
28 #include "model_preferences.h"
29
30 //MUtils
31 #include <MUtils/Global.h>
32 #include <MUtils/Exception.h>
33
34 //Qt
35 #include <QProcess>
36 #include <QTextCodec>
37 #include <QDir>
38 #include <QPair>
39
40 // ------------------------------------------------------------
41 // Constructor & Destructor
42 // ------------------------------------------------------------
43
44 AbstractSource::AbstractSource(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)
45 :
46         AbstractTool(jobObject, options, sysinfo, preferences, jobStatus, abort, pause, semaphorePause),
47         m_sourceFile(sourceFile)
48 {
49         /*Nothing to do here*/
50 }
51
52 AbstractSource::~AbstractSource(void)
53 {
54         /*Nothing to do here*/
55 }
56
57 // ------------------------------------------------------------
58 // Check Source Properties
59 // ------------------------------------------------------------
60
61 bool AbstractSource::checkSourceProperties(ClipInfo &clipInfo)
62 {
63         QStringList cmdLine;
64         QList<QRegExp*> patterns;
65         QProcess process;
66
67         checkSourceProperties_init(patterns, cmdLine);
68
69         log("Creating process:");
70         if(!startProcess(process, getBinaryPath(), cmdLine, true, getExtraPath()))
71         {
72                 return false;;
73         }
74         
75         QTextCodec *localCodec = QTextCodec::codecForName("System");
76
77         bool bTimeout = false;
78         bool bAborted = false;
79         
80         clipInfo.reset();
81                 
82         unsigned int waitCounter = 0;
83
84         while(process.state() != QProcess::NotRunning)
85         {
86                 if(*m_abort)
87                 {
88                         process.kill();
89                         bAborted = true;
90                         break;
91                 }
92                 if(!process.waitForReadyRead(m_processTimeoutInterval))
93                 {
94                         if(process.state() == QProcess::Running)
95                         {
96                                 if(++waitCounter > m_processTimeoutMaxCounter)
97                                 {
98                                         if(m_preferences->getAbortOnTimeout())
99                                         {
100                                                 process.kill();
101                                                 qWarning("Source process timed out <-- killing!");
102                                                 log("\nPROCESS TIMEOUT !!!");
103                                                 log("\nInput process has encountered a deadlock or your script takes EXTREMELY long to initialize!");
104                                                 bTimeout = true;
105                                                 break;
106                                         }
107                                 }
108                                 else if(waitCounter == m_processTimeoutWarning)
109                                 {
110                                         unsigned int timeOut = (waitCounter * m_processTimeoutInterval) / 1000U;
111                                         log(tr("Warning: Input process did not respond for %1 seconds, potential deadlock...").arg(QString::number(timeOut)));
112                                 }
113                         }
114                         continue;
115                 }
116                 
117                 waitCounter = 0;
118                 PROCESS_PENDING_LINES(process, checkSourceProperties_parseLine, patterns, clipInfo);
119         }
120
121         if(!(bTimeout || bAborted))
122         {
123                 PROCESS_PENDING_LINES(process, checkSourceProperties_parseLine, patterns, clipInfo);
124         }
125
126         process.waitForFinished();
127         if(process.state() != QProcess::NotRunning)
128         {
129                 process.kill();
130                 process.waitForFinished(-1);
131         }
132
133         while(!patterns.isEmpty())
134         {
135                 QRegExp *pattern = patterns.takeFirst();
136                 MUTILS_DELETE(pattern);
137         }
138
139         if(bTimeout || bAborted || process.exitCode() != EXIT_SUCCESS)
140         {
141                 if(!(bTimeout || bAborted))
142                 {
143                         const int exitCode = process.exitCode();
144                         log(tr("\nPROCESS EXITED WITH ERROR CODE: %1").arg(QString::number(exitCode)));
145                         if((exitCode < 0) || (exitCode >= 32))
146                         {
147                                 log(tr("\nIMPORTANT: The Avs2YUV process terminated abnormally. This means Avisynth or one of your Avisynth-Plugin's just crashed."));
148                                 log(tr("IMPORTANT: Please fix your Avisynth script and try again! If you use Avisynth-MT, try using a *stable* Avisynth instead!"));
149                         }
150                 }
151                 return false;
152         }
153
154         if(clipInfo.getFrameCount() < 1)
155         {
156                 log(tr("\nFAILED TO DETERMINE CLIP PROPERTIES !!!"));
157                 return false;
158         }
159         
160         log("");
161
162         const QPair<quint32, quint32> frameSize = clipInfo.getFrameSize();
163         if((frameSize.first > 0) && (frameSize.second > 0))
164         {
165                 log(tr("Resolution: %1 x %2").arg(QString::number(frameSize.first), QString::number(frameSize.second)));
166         }
167
168         const QPair<quint32, quint32> frameRate = clipInfo.getFrameRate();
169         if((frameRate.first > 0) && (frameRate.second > 0))
170         {
171                 log(tr("Frame Rate: %1/%2").arg(QString::number(frameRate.first), QString::number(frameRate.second)));
172         }
173         else if(frameRate.first > 0)
174         {
175                 log(tr("Frame Rate: %1").arg(QString::number(frameRate.first)));
176         }
177
178         log(tr("No. Frames: %1").arg(QString::number(clipInfo.getFrameCount())));
179         return true;
180 }
181
182 // ------------------------------------------------------------
183 // Source Processing
184 // ------------------------------------------------------------
185
186 bool AbstractSource::createProcess(QProcess &processEncode, QProcess&processInput)
187 {
188         processInput.setStandardOutputProcess(&processEncode);
189         
190         QStringList cmdLine_Input;
191         buildCommandLine(cmdLine_Input);
192
193         log("Creating input process:");
194         if(!startProcess(processInput, getBinaryPath(), cmdLine_Input, false, getExtraPath()))
195         {
196                 return false;
197         }
198
199         return true;
200 }
201
202 // ------------------------------------------------------------
203 // Source Info
204 // ------------------------------------------------------------
205
206 const AbstractSourceInfo& AbstractSource::getSourceInfo(void)
207 {
208         MUTILS_THROW("[getSourceInfo] This function must be overwritten in sub-classes!");
209 }