OSDN Git Service

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