Much improved VapourSynth detection + added option "--no-deadlock-detection" to disable process termination on timeout.

This commit is contained in:
LoRd_MuldeR 2013-08-04 18:44:53 +02:00
parent 2aa2c7385f
commit 9635f092f6
6 changed files with 118 additions and 53 deletions

View File

@ -213,12 +213,14 @@ in older versions of the Simple x264 Launcher is *NOT* needed anymore!!
The following command-line switches are available: The following command-line switches are available:
--add <file> [<file>] ... Create new job(s) from files(s) --add <file> [<file>] ..... Create new job(s) from files(s)
--console ............... Show the "debug" console --console ................. Show the "debug" console
--no-console ............ Don't show the "debug" console --no-console .............. Don't show the "debug" console
--no-style .............. Don't use the Qt "Plastique" style --no-style ................ Don't use the Qt "Plastique" style
--skip-avisynth-check ... Skip Avisynth check (not recommended!) --skip-avisynth-check ..... Skip Avisynth check, disable .AVS input
--force-cpu-no-64bit .... Forcefully disable 64-Bit support --skip-vapoursynth-check .. Skip VapourSynth check, disables .VPY input
--force-cpu-no-64bit ...... Forcefully disable 64-Bit support
--no-deadlock-detection ... Don't abort processes on timeout/deadlock
These are parameters you can pass to Simple x264 Launcher, they can NOT These are parameters you can pass to Simple x264 Launcher, they can NOT
be passed to x264 itself as "custom" parameters! be passed to x264 itself as "custom" parameters!

View File

@ -92,8 +92,9 @@ while(0)
} \ } \
while(0) while(0)
#define AVS2_BINARY(BIN_DIR, IS_X64) QString("%1/%2/avs2yuv_%2.exe").arg((BIN_DIR), ((IS_X64) ? "x64" : "x86")) #define AVS2_BINARY(BIN_DIR, IS_X64) (QString("%1/%2/avs2yuv_%2.exe").arg((BIN_DIR), ((IS_X64) ? "x64" : "x86")))
#define X264_BINARY(BIN_DIR, IS_10BIT, IS_X64) QString("%1/%2/x264_%3_%2.exe").arg((BIN_DIR), ((IS_X64) ? "x64" : "x86"), ((IS_10BIT) ? "10bit" : "8bit")) #define X264_BINARY(BIN_DIR, IS_10BIT, IS_X64) (QString("%1/%2/x264_%3_%2.exe").arg((BIN_DIR), ((IS_X64) ? "x64" : "x86"), ((IS_10BIT) ? "10bit" : "8bit")))
#define VPSP_BINARY(VPS_DIR) (QString("%1/vspipe.exe").arg((VPS_DIR)))
/* /*
* Static vars * Static vars
@ -105,7 +106,7 @@ static const char *VPS_TEST_FILE = "import vapoursynth as vs\ncore = vs.get_core
// Constructor & Destructor // Constructor & Destructor
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputFileName, const OptionsModel *options, const QString &binDir, const QString &vpsDir, bool x264_x64, bool x264_10bit, bool avs2yuv_x64, bool const skipVersionTest, int processPriroity) EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputFileName, const OptionsModel *options, const QString &binDir, const QString &vpsDir, const bool &x264_x64, const bool &x264_10bit, const bool &avs2yuv_x64, const bool &skipVersionTest, const int &processPriroity, const bool &abortOnTimeout)
: :
m_jobId(QUuid::createUuid()), m_jobId(QUuid::createUuid()),
m_sourceFileName(sourceFileName), m_sourceFileName(sourceFileName),
@ -118,6 +119,7 @@ EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputF
m_avs2yuv_x64(avs2yuv_x64), m_avs2yuv_x64(avs2yuv_x64),
m_skipVersionTest(skipVersionTest), m_skipVersionTest(skipVersionTest),
m_processPriority(processPriroity), m_processPriority(processPriroity),
m_abortOnTimeout(abortOnTimeout),
m_handle_jobObject(NULL), m_handle_jobObject(NULL),
m_semaphorePaused(0) m_semaphorePaused(0)
{ {
@ -248,7 +250,7 @@ void EncodeThread::encode(void)
CHECK_STATUS(m_abort, ok); CHECK_STATUS(m_abort, ok);
break; break;
case INPUT_VAPOUR: case INPUT_VAPOUR:
ok = checkVersionVapoursynth(QString("%1/vspipe.exe").arg(m_vpsDir)); ok = checkVersionVapoursynth();
CHECK_STATUS(m_abort, ok); CHECK_STATUS(m_abort, ok);
break; break;
} }
@ -288,7 +290,7 @@ void EncodeThread::encode(void)
CHECK_STATUS(m_abort, ok); CHECK_STATUS(m_abort, ok);
break; break;
case INPUT_VAPOUR: case INPUT_VAPOUR:
ok = checkPropertiesVapoursynth(QString("%1/vspipe.exe").arg(m_vpsDir), frames); ok = checkPropertiesVapoursynth(frames);
CHECK_STATUS(m_abort, ok); CHECK_STATUS(m_abort, ok);
break; break;
} }
@ -358,7 +360,7 @@ bool EncodeThread::runEncodingPass(bool x264_x64, bool x264_10bit, bool avs2yuv_
cmdLine_Input << pathToLocal(QDir::toNativeSeparators(m_sourceFileName)); cmdLine_Input << pathToLocal(QDir::toNativeSeparators(m_sourceFileName));
cmdLine_Input << "-" << "-y4m"; cmdLine_Input << "-" << "-y4m";
log("Creating Vapoursynth process:"); log("Creating Vapoursynth process:");
if(!startProcess(processInput, QString("%1/vspipe.exe").arg(m_vpsDir), cmdLine_Input, false)) if(!startProcess(processInput, VPSP_BINARY(m_vpsDir), cmdLine_Input, false))
{ {
return false; return false;
} }
@ -426,13 +428,16 @@ bool EncodeThread::runEncodingPass(bool x264_x64, bool x264_10bit, bool avs2yuv_
{ {
if(processEncode.state() == QProcess::Running) if(processEncode.state() == QProcess::Running)
{ {
if(waitCounter++ > m_processTimeoutMaxCounter) if(++waitCounter > m_processTimeoutMaxCounter)
{ {
processEncode.kill(); if(m_abortOnTimeout)
qWarning("x264 process timed out <-- killing!"); {
log("\nPROCESS TIMEOUT !!!"); processEncode.kill();
bTimeout = true; qWarning("x264 process timed out <-- killing!");
break; log("\nPROCESS TIMEOUT !!!");
bTimeout = true;
break;
}
} }
else if(waitCounter == m_processTimeoutWarning) else if(waitCounter == m_processTimeoutWarning)
{ {
@ -877,12 +882,19 @@ unsigned int EncodeThread::checkVersionAvs2yuv(bool x64)
return (ver_maj * REV_MULT) + ((ver_min % REV_MULT) * 10) + (ver_mod % 10); return (ver_maj * REV_MULT) + ((ver_min % REV_MULT) * 10) + (ver_mod % 10);
} }
bool EncodeThread::checkVersionVapoursynth(const QString &vspipePath) bool EncodeThread::checkVersionVapoursynth(/*const QString &vspipePath*/)
{ {
//Is VapourSynth available at all?
if(m_vpsDir.isEmpty() || (!QFileInfo(VPSP_BINARY(m_vpsDir)).isFile()))
{
log(tr("\nVPY INPUT REQUIRES VAPOURSYNTH, BUT IT IS *NOT* AVAILABLE !!!"));
return false;
}
QProcess process; QProcess process;
log("\nCreating process:"); log("\nCreating process:");
if(!startProcess(process, vspipePath, QStringList())) if(!startProcess(process, VPSP_BINARY(m_vpsDir), QStringList()))
{ {
return false;; return false;;
} }
@ -1004,14 +1016,17 @@ bool EncodeThread::checkPropertiesAvisynth(bool x64, unsigned int &frames)
{ {
if(process.state() == QProcess::Running) if(process.state() == QProcess::Running)
{ {
if(waitCounter++ > m_processTimeoutMaxCounter) if(++waitCounter > m_processTimeoutMaxCounter)
{ {
process.kill(); if(m_abortOnTimeout)
qWarning("Avs2YUV process timed out <-- killing!"); {
log("\nPROCESS TIMEOUT !!!"); process.kill();
log("\nAvisynth has encountered a deadlock or your script takes EXTREMELY long to initialize!"); qWarning("Avs2YUV process timed out <-- killing!");
bTimeout = true; log("\nPROCESS TIMEOUT !!!");
break; log("\nAvisynth has encountered a deadlock or your script takes EXTREMELY long to initialize!");
bTimeout = true;
break;
}
} }
else if(waitCounter == m_processTimeoutWarning) else if(waitCounter == m_processTimeoutWarning)
{ {
@ -1119,7 +1134,7 @@ bool EncodeThread::checkPropertiesAvisynth(bool x64, unsigned int &frames)
return true; return true;
} }
bool EncodeThread::checkPropertiesVapoursynth(const QString &vspipePath, unsigned int &frames) bool EncodeThread::checkPropertiesVapoursynth(/*const QString &vspipePath,*/ unsigned int &frames)
{ {
QProcess process; QProcess process;
QStringList cmdLine; QStringList cmdLine;
@ -1128,7 +1143,7 @@ bool EncodeThread::checkPropertiesVapoursynth(const QString &vspipePath, unsigne
cmdLine << "-" << "-info"; cmdLine << "-" << "-info";
log("Creating process:"); log("Creating process:");
if(!startProcess(process, vspipePath, cmdLine)) if(!startProcess(process, VPSP_BINARY(m_vpsDir), cmdLine))
{ {
return false;; return false;;
} }
@ -1161,14 +1176,17 @@ bool EncodeThread::checkPropertiesVapoursynth(const QString &vspipePath, unsigne
{ {
if(process.state() == QProcess::Running) if(process.state() == QProcess::Running)
{ {
if(waitCounter++ > m_processTimeoutMaxCounter) if(++waitCounter > m_processTimeoutMaxCounter)
{ {
process.kill(); if(m_abortOnTimeout)
qWarning("VSPipe process timed out <-- killing!"); {
log("\nPROCESS TIMEOUT !!!"); process.kill();
log("\nVapoursynth has encountered a deadlock or your script takes EXTREMELY long to initialize!"); qWarning("VSPipe process timed out <-- killing!");
bTimeout = true; log("\nPROCESS TIMEOUT !!!");
break; log("\nVapoursynth has encountered a deadlock or your script takes EXTREMELY long to initialize!");
bTimeout = true;
break;
}
} }
else if(waitCounter == m_processTimeoutWarning) else if(waitCounter == m_processTimeoutWarning)
{ {

View File

@ -37,7 +37,7 @@ class EncodeThread : public QThread
Q_OBJECT Q_OBJECT
public: public:
EncodeThread(const QString &sourceFileName, const QString &outputFileName, const OptionsModel *options, const QString &binDir, const QString &vpsDir, bool x264_x64, bool x264_10bit, bool avs2yuv_x64, bool const skipVersionTest, int processPriroity); EncodeThread(const QString &sourceFileName, const QString &outputFileName, const OptionsModel *options, const QString &binDir, const QString &vpsDir, const bool &x264_x64, const bool &x264_10bit, const bool &avs2yuv_x64, const bool &skipVersionTest, const int &processPriroity, const bool &abortOnTimeout);
~EncodeThread(void); ~EncodeThread(void);
QUuid getId(void) { return this->m_jobId; }; QUuid getId(void) { return this->m_jobId; };
@ -79,6 +79,7 @@ protected:
const bool m_avs2yuv_x64; const bool m_avs2yuv_x64;
const bool m_skipVersionTest; const bool m_skipVersionTest;
const int m_processPriority; const int m_processPriority;
const bool m_abortOnTimeout;
//Types //Types
enum inputType_t enum inputType_t
@ -112,9 +113,9 @@ protected:
QStringList buildCommandLine(bool usePipe, bool use10Bit, unsigned int frames, const QString &indexFile, int pass = 0, const QString &passLogFile = QString()); QStringList buildCommandLine(bool usePipe, bool use10Bit, unsigned int frames, const QString &indexFile, int pass = 0, const QString &passLogFile = QString());
unsigned int checkVersionX264(bool use_x64, bool use_10bit, bool &modified); unsigned int checkVersionX264(bool use_x64, bool use_10bit, bool &modified);
unsigned int checkVersionAvs2yuv(bool x64); unsigned int checkVersionAvs2yuv(bool x64);
bool checkVersionVapoursynth(const QString &vspipePath); bool checkVersionVapoursynth(void);
bool checkPropertiesAvisynth(bool x64, unsigned int &frames); bool checkPropertiesAvisynth(bool x64, unsigned int &frames);
bool checkPropertiesVapoursynth(const QString &vspipePath, unsigned int &frames); bool checkPropertiesVapoursynth(unsigned int &frames);
//Auxiallary Stuff //Auxiallary Stuff
void log(const QString &text) { emit messageLogged(m_jobId, text); } void log(const QString &text) { emit messageLogged(m_jobId, text); }

View File

@ -22,7 +22,7 @@
#define VER_X264_MAJOR 2 #define VER_X264_MAJOR 2
#define VER_X264_MINOR 1 #define VER_X264_MINOR 1
#define VER_X264_PATCH 8 #define VER_X264_PATCH 8
#define VER_X264_BUILD 530 #define VER_X264_BUILD 537
#define VER_X264_MINIMUM_REV 2339 #define VER_X264_MINIMUM_REV 2339
#define VER_X264_CURRENT_API 135 #define VER_X264_CURRENT_API 135

View File

@ -76,6 +76,7 @@ MainWindow::MainWindow(const x264_cpu_t *const cpuFeatures)
m_preferences(NULL), m_preferences(NULL),
m_recentlyUsed(NULL), m_recentlyUsed(NULL),
m_skipVersionTest(false), m_skipVersionTest(false),
m_abortOnTimeout(true),
m_firstShow(true) m_firstShow(true)
{ {
//Init the dialog, from the .ui file //Init the dialog, from the .ui file
@ -775,6 +776,13 @@ void MainWindow::init(void)
m_skipVersionTest = true; m_skipVersionTest = true;
} }
//Don't abort encoding process on timeout (not recommended!)
if(qApp->arguments().contains("--no-deadlock-detection", Qt::CaseInsensitive))
{
qWarning("Deadlock detection disabled, you have been warned!\n");
m_abortOnTimeout = false;
}
//Check for Avisynth support //Check for Avisynth support
if(!qApp->arguments().contains("--skip-avisynth-check", Qt::CaseInsensitive)) if(!qApp->arguments().contains("--skip-avisynth-check", Qt::CaseInsensitive))
{ {
@ -804,20 +812,11 @@ void MainWindow::init(void)
const QString vapursynthPath = getVapoursynthLocation(); const QString vapursynthPath = getVapoursynthLocation();
if(!vapursynthPath.isEmpty()) if(!vapursynthPath.isEmpty())
{ {
bool okay = false;
QFile *vpsExePath = new QFile(QString("%1/core/vspipe.exe").arg(vapursynthPath)); QFile *vpsExePath = new QFile(QString("%1/core/vspipe.exe").arg(vapursynthPath));
QFile *vpsDllPath = new QFile(QString("%1/core/vapoursynth.dll").arg(vapursynthPath)); QFile *vpsDllPath = new QFile(QString("%1/core/vapoursynth.dll").arg(vapursynthPath));
qDebug("VapourSynth EXE: %s", vpsExePath->fileName().toUtf8().constData()); qDebug("VapourSynth EXE: %s", vpsExePath->fileName().toUtf8().constData());
qDebug("VapourSynth DLL: %s", vpsDllPath->fileName().toUtf8().constData()); qDebug("VapourSynth DLL: %s", vpsDllPath->fileName().toUtf8().constData());
if(vpsExePath->open(QIODevice::ReadOnly) && vpsDllPath->open(QIODevice::ReadOnly)) if(checkVapourSynth(vpsExePath, vpsDllPath))
{
DWORD binaryType;
if(GetBinaryType(QWCHAR(QDir::toNativeSeparators(vpsExePath->fileName())), &binaryType))
{
okay = (binaryType == SCS_32BIT_BINARY || binaryType == SCS_64BIT_BINARY);
}
}
if(okay)
{ {
qDebug("VapourSynth support enabled."); qDebug("VapourSynth support enabled.");
m_vapoursynthPath = QFileInfo(vpsExePath->fileName()).canonicalPath(); m_vapoursynthPath = QFileInfo(vpsExePath->fileName()).canonicalPath();
@ -826,7 +825,7 @@ void MainWindow::init(void)
} }
else else
{ {
qDebug("VapourSynth binaries not found -> disable Vapousynth support!"); qDebug("VapourSynth not avilable -> disable Vapousynth support!");
X264_DELETE(vpsExePath); X264_DELETE(vpsExePath);
X264_DELETE(vpsDllPath); X264_DELETE(vpsDllPath);
int val = QMessageBox::warning(this, tr("VapourSynth Missing"), tr("<nobr>It appears that VapourSynth is <b>not</b> currently installed on your computer.<br>Therefore VapourSynth (.vpy) input will <b>not</b> be working at all!<br><br>Please download and install VapourSynth (r19 or later) here:<br><a href=\"http://www.vapoursynth.com/\">http://www.vapoursynth.com/</a></nobr>").replace("-", "&minus;"), tr("Quit"), tr("Ignore")); int val = QMessageBox::warning(this, tr("VapourSynth Missing"), tr("<nobr>It appears that VapourSynth is <b>not</b> currently installed on your computer.<br>Therefore VapourSynth (.vpy) input will <b>not</b> be working at all!<br><br>Please download and install VapourSynth (r19 or later) here:<br><a href=\"http://www.vapoursynth.com/\">http://www.vapoursynth.com/</a></nobr>").replace("-", "&minus;"), tr("Quit"), tr("Ignore"));
@ -1169,7 +1168,8 @@ bool MainWindow::appendJob(const QString &sourceFileName, const QString &outputF
m_preferences->use10BitEncoding(), m_preferences->use10BitEncoding(),
m_cpuFeatures->x64 && m_preferences->useAvisyth64Bit(), m_cpuFeatures->x64 && m_preferences->useAvisyth64Bit(),
m_skipVersionTest, m_skipVersionTest,
m_preferences->processPriority() m_preferences->processPriority(),
m_abortOnTimeout
); );
QModelIndex newIndex = m_jobList->insertJob(thrd); QModelIndex newIndex = m_jobList->insertJob(thrd);
@ -1307,6 +1307,7 @@ QString MainWindow::getVapoursynthLocation(void)
QString vapoursynthPath; QString vapoursynthPath;
static const wchar_t *VPS_REG_KEY = L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VapourSynth_is1"; static const wchar_t *VPS_REG_KEY = L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VapourSynth_is1";
HKEY hKey = NULL; HKEY hKey = NULL;
if(RegOpenKey(HKEY_LOCAL_MACHINE, VPS_REG_KEY, &hKey) == ERROR_SUCCESS) if(RegOpenKey(HKEY_LOCAL_MACHINE, VPS_REG_KEY, &hKey) == ERROR_SUCCESS)
{ {
const size_t DATA_LEN = 2048; const size_t DATA_LEN = 2048;
@ -1325,7 +1326,46 @@ QString MainWindow::getVapoursynthLocation(void)
} }
else else
{ {
qDebug("Vapoursynth registry key not found -> not installed!"); qWarning("Vapoursynth registry key not found -> not installed!");
} }
return vapoursynthPath; return vapoursynthPath;
} }
bool MainWindow::checkVapourSynth(QFile *vpsExePath, QFile *vpsDllPath)
{
bool okay = false;
static const char *VSSCRIPT_ENTRY = "_vsscript_init@0";
if(vpsExePath->open(QIODevice::ReadOnly) && vpsDllPath->open(QIODevice::ReadOnly))
{
DWORD binaryType;
if(GetBinaryType(QWCHAR(QDir::toNativeSeparators(vpsExePath->fileName())), &binaryType))
{
okay = (binaryType == SCS_32BIT_BINARY || binaryType == SCS_64BIT_BINARY);
}
}
if(okay)
{
qDebug("VapourSynth binaries found -> load VSSCRIPT.DLL");
QLibrary vspLibrary("vsscript.dll");
if(okay = vspLibrary.load())
{
if(!(okay = (vspLibrary.resolve(VSSCRIPT_ENTRY) != NULL)))
{
qWarning("Entrypoint '%s' not found in VSSCRIPT.DLL !!!", VSSCRIPT_ENTRY);
}
}
else
{
qWarning("Failed to load VSSCRIPT.DLL !!!");
}
}
else
{
qWarning("VapourSynth binaries could not be found !!!");
}
return okay;
}

View File

@ -54,6 +54,8 @@ protected:
private: private:
bool m_firstShow; bool m_firstShow;
bool m_skipVersionTest; bool m_skipVersionTest;
bool m_abortOnTimeout;
QLabel *m_label; QLabel *m_label;
IPCThread *m_ipcThread; IPCThread *m_ipcThread;
@ -64,6 +66,7 @@ private:
PreferencesModel *m_preferences; PreferencesModel *m_preferences;
RecentlyUsed *m_recentlyUsed; RecentlyUsed *m_recentlyUsed;
QString m_vapoursynthPath; QString m_vapoursynthPath;
const x264_cpu_t *const m_cpuFeatures; const x264_cpu_t *const m_cpuFeatures;
@ -79,6 +82,7 @@ private:
unsigned int countRunningJobs(void); unsigned int countRunningJobs(void);
static QString getVapoursynthLocation(void); static QString getVapoursynthLocation(void);
static bool checkVapourSynth(QFile *vpsExePath, QFile *vpsDllPath);
private slots: private slots:
void addButtonPressed(); void addButtonPressed();