OSDN Git Service

Moved the Avisynth detected code into a background thread.
authorlordmulder <mulder2@gmx.de>
Tue, 2 Apr 2013 21:10:58 +0000 (23:10 +0200)
committerlordmulder <mulder2@gmx.de>
Tue, 2 Apr 2013 21:10:58 +0000 (23:10 +0200)
src/thread_avisynth.cpp [new file with mode: 0644]
src/thread_avisynth.h [new file with mode: 0644]
src/version.h
src/win_main.cpp
src/win_main.h
x264_launcher_MSVC2012.vcxproj
x264_launcher_MSVC2012.vcxproj.filters

diff --git a/src/thread_avisynth.cpp b/src/thread_avisynth.cpp
new file mode 100644 (file)
index 0000000..5240b02
--- /dev/null
@@ -0,0 +1,217 @@
+///////////////////////////////////////////////////////////////////////////////
+// Simple x264 Launcher
+// Copyright (C) 2004-2012 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// http://www.gnu.org/licenses/gpl-2.0.txt
+///////////////////////////////////////////////////////////////////////////////
+
+#include "thread_avisynth.h"
+
+#include <QLibrary>
+#include <QEventLoop>
+#include <QTimer>
+#include <QMutexLocker>
+#include <QApplication>
+
+#include "global.h"
+#include "avisynth_c.h"
+
+QMutex AvisynthCheckThread::m_avsLock;
+QLibrary *AvisynthCheckThread::m_avsLib = NULL;
+
+AvisynthCheckThread::AvisynthCheckThread(void)
+{
+       m_success = false;
+       m_exception = false;
+       m_version = 0.0;
+}
+
+AvisynthCheckThread::~AvisynthCheckThread(void)
+{
+}
+
+int AvisynthCheckThread::detect(volatile double *version)
+{
+       *version = 0.0;
+       QMutexLocker lock(&m_avsLock);
+
+       QEventLoop loop;
+       AvisynthCheckThread thread;
+       QTimer timer;
+
+       QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+
+       connect(&thread, SIGNAL(finished()), &loop, SLOT(quit()));
+       connect(&thread, SIGNAL(terminated()), &loop, SLOT(quit()));
+       connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
+       
+       thread.start();
+       timer.start(8000);
+       
+       qDebug("Avisynth thread has been created, please wait...");
+       loop.exec(QEventLoop::ExcludeUserInputEvents);
+       qDebug("Avisynth thread finished.");
+
+       QApplication::restoreOverrideCursor();
+
+       if(!thread.wait(1000))
+       {
+               qWarning("Avisynth thread encountered timeout -> probably deadlock!");
+               thread.terminate();
+               thread.wait();
+               return -1;
+       }
+
+       if(thread.getException())
+       {
+               qWarning("Avisynth thread encountered an exception !!!");
+               return -1;
+       }
+       
+       if(thread.getSuccess())
+       {
+               *version = thread.getVersion();
+               qDebug("Version check completed: %.2f", *version);
+               return 1;
+       }
+
+       qWarning("Avisynth thread failed to determine the version!");
+       return 0;
+}
+
+void AvisynthCheckThread::unload(void)
+{
+       QMutexLocker lock(&m_avsLock);
+
+       if(m_avsLib)
+       {
+               if(m_avsLib->isLoaded())
+               {
+                       m_avsLib->unload();
+               }
+               X264_DELETE(m_avsLib);
+       }
+}
+
+void AvisynthCheckThread::run(void)
+{
+       m_success = detectAvisynthVersion1(&m_version, &m_exception);
+}
+
+bool AvisynthCheckThread::detectAvisynthVersion1(volatile double *version_number, volatile bool *exception)
+{
+       __try
+       {
+               return detectAvisynthVersion2(version_number, exception);
+       }
+       __except(1)
+       {
+               *exception = true;
+               qWarning("Unhandled exception error in Avisynth thread !!!");
+               return false;
+       }
+}
+
+bool AvisynthCheckThread::detectAvisynthVersion2(volatile double *version_number, volatile bool *exception)
+{
+       try
+       {
+               return detectAvisynthVersion3(version_number);
+       }
+       catch(...)
+       {
+               *exception = true;
+               qWarning("Avisynth initializdation raised an C++ exception!");
+               return false;
+       }
+}
+
+bool AvisynthCheckThread::detectAvisynthVersion3(volatile double *version_number)
+{
+       bool success = false;
+       *version_number = 0.0;
+
+       if(!m_avsLib)
+       {
+               m_avsLib = new QLibrary("avisynth.dll");
+       }
+
+       if(m_avsLib->isLoaded() || m_avsLib->load())
+       {
+               avs_create_script_environment_func avs_create_script_environment_ptr = (avs_create_script_environment_func) m_avsLib->resolve("avs_create_script_environment");
+               avs_invoke_func avs_invoke_ptr = (avs_invoke_func) m_avsLib->resolve("avs_invoke");
+               avs_function_exists_func avs_function_exists_ptr = (avs_function_exists_func) m_avsLib->resolve("avs_function_exists");
+               avs_delete_script_environment_func avs_delete_script_environment_ptr = (avs_delete_script_environment_func) m_avsLib->resolve("avs_delete_script_environment");
+               avs_release_value_func avs_release_value_ptr = (avs_release_value_func) m_avsLib->resolve("avs_release_value");
+       
+               if((avs_create_script_environment_ptr != NULL) && (avs_invoke_ptr != NULL) && (avs_function_exists_ptr != NULL))
+               {
+                       qDebug("avs_create_script_environment_ptr(AVS_INTERFACE_25)");
+                       AVS_ScriptEnvironment* avs_env = avs_create_script_environment_ptr(AVS_INTERFACE_25);
+                       if(avs_env != NULL)
+                       {
+                               qDebug("avs_function_exists_ptr(avs_env, \"VersionNumber\")");
+                               if(avs_function_exists_ptr(avs_env, "VersionNumber"))
+                               {
+                                       qDebug("avs_invoke_ptr(avs_env, \"VersionNumber\", avs_new_value_array(NULL, 0), NULL)");
+                                       AVS_Value avs_version = avs_invoke_ptr(avs_env, "VersionNumber", avs_new_value_array(NULL, 0), NULL);
+                                       if(!avs_is_error(avs_version))
+                                       {
+                                               if(avs_is_float(avs_version))
+                                               {
+                                                       qDebug("Avisynth version: v%.2f", avs_as_float(avs_version));
+                                                       *version_number = avs_as_float(avs_version);
+                                                       if(avs_release_value_ptr) avs_release_value_ptr(avs_version);
+                                                       success = true;
+                                               }
+                                               else
+                                               {
+                                                       qWarning("Failed to determine version number, Avisynth didn't return a float!");
+                                               }
+                                       }
+                                       else
+                                       {
+                                               qWarning("Failed to determine version number, Avisynth returned an error!");
+                                       }
+                               }
+                               else
+                               {
+                                       qWarning("The 'VersionNumber' function does not exist in your Avisynth DLL, can't determine version!");
+                               }
+                               if(avs_delete_script_environment_ptr != NULL)
+                               {
+                                       avs_delete_script_environment_ptr(avs_env);
+                                       avs_env = NULL;
+                               }
+                       }
+                       else
+                       {
+                               qWarning("The Avisynth DLL failed to create the script environment!");
+                       }
+               }
+               else
+               {
+                       qWarning("It seems the Avisynth DLL is missing required API functions!");
+               }
+       }
+       else
+       {
+               qWarning("Failed to load Avisynth.dll library!");
+       }
+
+       return success;
+}
diff --git a/src/thread_avisynth.h b/src/thread_avisynth.h
new file mode 100644 (file)
index 0000000..54d3421
--- /dev/null
@@ -0,0 +1,62 @@
+///////////////////////////////////////////////////////////////////////////////
+// Simple x264 Launcher
+// Copyright (C) 2004-2012 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// http://www.gnu.org/licenses/gpl-2.0.txt
+///////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include <QThread>
+#include <QMutex>
+
+class QLibrary;
+
+class AvisynthCheckThread : public QThread
+{
+       Q_OBJECT
+
+public:
+       AvisynthCheckThread(void);
+       ~AvisynthCheckThread(void);
+
+       static int detect(volatile double *version);
+       static void unload(void);
+
+       bool getSuccess(void) { return m_success; }
+       bool getException(void) { return m_exception; }
+       double getVersion(void) { return m_version; }
+
+private slots:
+       void start(Priority priority = InheritPriority) { QThread::start(priority); }
+
+private:
+       volatile bool m_exception;
+       volatile bool m_success;
+       volatile double m_version;
+
+       static QMutex m_avsLock;
+       static QLibrary *m_avsLib;
+       
+       //Entry point
+       virtual void run(void);
+
+       //Functions
+       static bool detectAvisynthVersion1(volatile double *version_number, volatile bool *exception);
+       static bool detectAvisynthVersion2(volatile double *version_number, volatile bool *exception);
+       static bool detectAvisynthVersion3(volatile double *version_number);
+};
index da45895..2d359df 100644 (file)
@@ -20,9 +20,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #define VER_X264_MAJOR 2
-#define VER_X264_MINOR 0
-#define VER_X264_PATCH 9
-#define VER_X264_BUILD 408
+#define VER_X264_MINOR 1
+#define VER_X264_PATCH 0
+#define VER_X264_BUILD 419
 
 #define VER_X264_MINIMUM_REV 2250
 #define VER_X264_CURRENT_API 130
index 53a1758..4fb26e0 100644 (file)
@@ -25,9 +25,9 @@
 #include "model_options.h"
 #include "win_addJob.h"
 #include "win_preferences.h"
+#include "thread_avisynth.h"
 #include "taskbar7.h"
 #include "resource.h"
-#include "avisynth_c.h"
 
 #include <QDate>
 #include <QTimer>
@@ -66,7 +66,6 @@ MainWindow::MainWindow(const x264_cpu_t *const cpuFeatures)
        m_appDir(QApplication::applicationDirPath()),
        m_options(NULL),
        m_jobList(NULL),
-       m_avsLib(NULL),
        m_droppedFiles(NULL),
        m_firstShow(true)
 {
@@ -198,12 +197,7 @@ MainWindow::~MainWindow(void)
        }
 
        X264_DELETE(m_ipcThread);
-
-       if(m_avsLib)
-       {
-               m_avsLib->unload();
-               X264_DELETE(m_avsLib);
-       }
+       AvisynthCheckThread::unload();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -770,32 +764,19 @@ void MainWindow::init(void)
        if(!qApp->arguments().contains("--skip-avisynth-check", Qt::CaseInsensitive))
        {
                qDebug("[Check for Avisynth support]");
-               double avisynthVersion = 0.0;
-               if(!m_avsLib)
-               {
-                       m_avsLib = new QLibrary("avisynth.dll");
-               }
-               if(m_avsLib->load())
-               {
-                       DWORD errorCode = 0;
-                       avisynthVersion = detectAvisynthVersion(m_avsLib, &errorCode);
-                       if((avisynthVersion < 0.0) || errorCode)
-                       {
-                               QString text = tr("A critical error (code: 0x%1) was encountered while checking your Avisynth version.").arg(QString().sprintf("%08X", errorCode)).append("<br>");
-                               text += tr("This is most likely caused by an erroneous Avisynth Plugin, please try to clean your Plugins foler!").append("<br>");
-                               text += tr("We suggest to move all .dll and .avsi files out of your Avisynth Plugins folder and try again.");
-                               int val = QMessageBox::critical(this, tr("Avisynth Error"), QString("<nobr>%1</nobr>").arg(text).replace("-", "&minus;"), tr("Quit"), tr("Ignore"));
-                               if(val != 1) { close(); qApp->exit(-1); return; }
-                       }
-               }
-               else
+               volatile double avisynthVersion = 0.0;
+               const int result = AvisynthCheckThread::detect(&avisynthVersion);
+               if(result < 0)
                {
-                       qWarning("Failed to load avisynth.dll libraray!");
+                       QString text = tr("A critical error was encountered while checking your Avisynth version.").append("<br>");
+                       text += tr("This is most likely caused by an erroneous Avisynth Plugin, please try to clean your Plugins folder!").append("<br>");
+                       text += tr("We suggest to move all .dll and .avsi files out of your Avisynth Plugins folder and try again.");
+                       int val = QMessageBox::critical(this, tr("Avisynth Error"), QString("<nobr>%1</nobr>").arg(text).replace("-", "&minus;"), tr("Quit"), tr("Ignore"));
+                       if(val != 1) { close(); qApp->exit(-1); return; }
                }
-               if(avisynthVersion < 2.5)
+               if((!result) || (avisynthVersion < 2.5))
                {
                        int val = QMessageBox::warning(this, tr("Avisynth Missing"), tr("<nobr>It appears that Avisynth is <b>not</b> currently installed on your computer.<br>Therefore Avisynth (.avs) input will <b>not</b> be working at all!<br><br>Please download and install Avisynth:<br><a href=\"http://sourceforge.net/projects/avisynth2/files/AviSynth%202.5/\">http://sourceforge.net/projects/avisynth2/files/AviSynth 2.5/</a></nobr>").replace("-", "&minus;"), tr("Quit"), tr("Ignore"));
-                       m_avsLib->unload(); X264_DELETE(m_avsLib);
                        if(val != 1) { close(); qApp->exit(-1); return; }
                }
                qDebug("");
@@ -1159,82 +1140,3 @@ void MainWindow::updateTaskbar(EncodeThread::JobStatus status, const QIcon &icon
 
        WinSevenTaskbar::setOverlayIcon(this, icon.isNull() ? NULL : &icon);
 }
-
-/*
- * Detect Avisynth version
- */
-double MainWindow::detectAvisynthVersion(QLibrary *avsLib, DWORD *errorCode)
-{
-       qDebug("detectAvisynthVersion(QLibrary *avsLib)");
-       if(errorCode) *errorCode = 0;
-       double version_number = 0.0;
-       EXCEPTION_RECORD exceptionRecord;
-       
-       __try
-       {
-               avs_create_script_environment_func avs_create_script_environment_ptr = (avs_create_script_environment_func) avsLib->resolve("avs_create_script_environment");
-               avs_invoke_func avs_invoke_ptr = (avs_invoke_func) avsLib->resolve("avs_invoke");
-               avs_function_exists_func avs_function_exists_ptr = (avs_function_exists_func) avsLib->resolve("avs_function_exists");
-               avs_delete_script_environment_func avs_delete_script_environment_ptr = (avs_delete_script_environment_func) avsLib->resolve("avs_delete_script_environment");
-               avs_release_value_func avs_release_value_ptr = (avs_release_value_func) avsLib->resolve("avs_release_value");
-
-               //volatile int x = 0, y = 0; x = 42 / y;
-
-               if((avs_create_script_environment_ptr != NULL) && (avs_invoke_ptr != NULL) && (avs_function_exists_ptr != NULL))
-               {
-                       qDebug("avs_create_script_environment_ptr(AVS_INTERFACE_25)");
-                       AVS_ScriptEnvironment* avs_env = avs_create_script_environment_ptr(AVS_INTERFACE_25);
-                       if(avs_env != NULL)
-                       {
-                               qDebug("avs_function_exists_ptr(avs_env, \"VersionNumber\")");
-                               if(avs_function_exists_ptr(avs_env, "VersionNumber"))
-                               {
-                                       qDebug("avs_invoke_ptr(avs_env, \"VersionNumber\", avs_new_value_array(NULL, 0), NULL)");
-                                       AVS_Value avs_version = avs_invoke_ptr(avs_env, "VersionNumber", avs_new_value_array(NULL, 0), NULL);
-                                       if(!avs_is_error(avs_version))
-                                       {
-                                               if(avs_is_float(avs_version))
-                                               {
-                                                       qDebug("Avisynth version: v%.2f", avs_as_float(avs_version));
-                                                       version_number = avs_as_float(avs_version);
-                                                       if(avs_release_value_ptr) avs_release_value_ptr(avs_version);
-                                               }
-                                               else
-                                               {
-                                                       qWarning("Failed to determine version number, Avisynth didn't return a float!");
-                                               }
-                                       }
-                                       else
-                                       {
-                                               qWarning("Failed to determine version number, Avisynth returned an error!");
-                                       }
-                               }
-                               else
-                               {
-                                       qWarning("The 'VersionNumber' function does not exist in your Avisynth DLL, can't determine version!");
-                               }
-                               if(avs_delete_script_environment_ptr != NULL)
-                               {
-                                       avs_delete_script_environment_ptr(avs_env);
-                                       avs_env = NULL;
-                               }
-                       }
-                       else
-                       {
-                               qWarning("The Avisynth DLL failed to create the script environment!");
-                       }
-               }
-               else
-               {
-                       qWarning("It seems the Avisynth DLL is missing required API functions!");
-               }
-       }
-       __except(exceptionFilter(&exceptionRecord, GetExceptionInformation()))
-       {
-               if(errorCode) *errorCode = exceptionRecord.ExceptionCode;
-               qWarning("Exception in Avisynth initialization code! (Address: %p, Code: 0x%08x)", exceptionRecord.ExceptionAddress, exceptionRecord.ExceptionCode);
-               version_number = -1.0;
-       }
-
-       return version_number;
-}
index 7697f6e..65b8921 100644 (file)
@@ -53,7 +53,6 @@ private:
        bool m_firstShow;
        QLabel *m_label;
        IPCThread *m_ipcThread;
-       QLibrary *m_avsLib;
 
        JobListModel *m_jobList;
        OptionsModel *m_options;
@@ -69,7 +68,6 @@ private:
        void updateTaskbar(EncodeThread::JobStatus status, const QIcon &icon);
        unsigned int countPendingJobs(void);
        unsigned int countRunningJobs(void);
-       double detectAvisynthVersion(QLibrary *avsLib, DWORD *errorCode = NULL);
 
 private slots:
        void addButtonPressed(const QString &filePathIn = QString(), const QString &filePathOut = QString(), OptionsModel *options = NULL, int fileNo = -1, int fileTotal = 0, bool *ok = NULL);
index 9934d7d..a5494e4 100644 (file)
@@ -287,6 +287,14 @@ copy /Y "$(QTDIR)\plugins\imageformats\qgif4.dll" "$(TargetDir)\imageformats"
       <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)tmp\moc\moc_%(Filename).cpp;%(Outputs)</Outputs>
       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\moc\moc_%(Filename).cpp;%(Outputs)</Outputs>
     </CustomBuild>
+    <CustomBuild Include="src\thread_avisynth.h">
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\moc\moc_%(Filename).cpp" "%(FullPath)"</Command>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\moc\moc_%(Filename).cpp" "%(FullPath)"</Command>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MOC "$(SolutionDir)tmp\moc\moc_%(Filename).cpp"</Message>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MOC "$(SolutionDir)tmp\moc\moc_%(Filename).cpp"</Message>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)tmp\moc\moc_%(Filename).cpp;%(Outputs)</Outputs>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\moc\moc_%(Filename).cpp;%(Outputs)</Outputs>
+    </CustomBuild>
     <ClInclude Include="src\version.h" />
     <CustomBuild Include="src\win_main.h">
       <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\moc\moc_%(Filename).cpp" "%(FullPath)"</Command>
@@ -306,6 +314,7 @@ copy /Y "$(QTDIR)\plugins\imageformats\qgif4.dll" "$(TargetDir)\imageformats"
       <TreatWChar_tAsBuiltInType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</TreatWChar_tAsBuiltInType>
     </ClCompile>
     <ClCompile Include="src\taskbar7.cpp" />
+    <ClCompile Include="src\thread_avisynth.cpp" />
     <ClCompile Include="src\thread_encode.cpp" />
     <ClCompile Include="src\global.cpp" />
     <ClCompile Include="src\main.cpp" />
@@ -317,6 +326,7 @@ copy /Y "$(QTDIR)\plugins\imageformats\qgif4.dll" "$(TargetDir)\imageformats"
     <ClCompile Include="src\win_preferences.cpp" />
     <ClCompile Include="tmp\moc\moc_model_jobList.cpp" />
     <ClCompile Include="tmp\moc\moc_model_logFile.cpp" />
+    <ClCompile Include="tmp\moc\moc_thread_avisynth.cpp" />
     <ClCompile Include="tmp\moc\moc_thread_encode.cpp" />
     <ClCompile Include="tmp\moc\moc_thread_ipc.cpp" />
     <ClCompile Include="tmp\moc\moc_win_addJob.cpp" />
index 2a9f9e5..78d48ff 100644 (file)
@@ -48,6 +48,9 @@
     <ClInclude Include="src\taskbar7.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="src\thread_avisynth.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="src\main.cpp">
     <ClCompile Include="src\qtmain_win.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\thread_avisynth.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="tmp\moc\moc_thread_avisynth.cpp">
+      <Filter>Generated Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="src\win_main.h">