2012-01-28 16:40:14 +01:00
///////////////////////////////////////////////////////////////////////////////
// Simple x264 Launcher
2013-05-11 21:52:07 +02:00
// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
2012-01-28 16:40:14 +01:00
//
// 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 "global.h"
# include "version.h"
//Qt includes
# include <QApplication>
# include <QMessageBox>
# include <QDir>
# include <QUuid>
# include <QMap>
# include <QDate>
# include <QIcon>
# include <QPlastiqueStyle>
# include <QImageReader>
# include <QSharedMemory>
# include <QSysInfo>
# include <QStringList>
# include <QSystemSemaphore>
2012-02-10 18:40:28 +01:00
# include <QDesktopServices>
2012-01-28 16:40:14 +01:00
# include <QMutex>
# include <QTextCodec>
# include <QLibrary>
# include <QRegExp>
# include <QResource>
# include <QTranslator>
# include <QEventLoop>
# include <QTimer>
# include <QLibraryInfo>
# include <QEvent>
//CRT includes
# include <fstream>
# include <io.h>
# include <fcntl.h>
# include <intrin.h>
//Debug only includes
# if X264_DEBUG
# include <Psapi.h>
# endif
//Global vars
static bool g_x264_console_attached = false ;
static QMutex g_x264_message_mutex ;
static const DWORD g_main_thread_id = GetCurrentThreadId ( ) ;
static FILE * g_x264_log_file = NULL ;
static QDate g_x264_version_date ;
//Const
static const char * g_x264_months [ ] = { " Jan " , " Feb " , " Mar " , " Apr " , " May " , " Jun " , " Jul " , " Aug " , " Sep " , " Oct " , " Nov " , " Dec " } ;
static const char * g_x264_imageformats [ ] = { " png " , " jpg " , " gif " , " ico " , " svg " , NULL } ;
//Build version
static const struct
{
unsigned int ver_major ;
unsigned int ver_minor ;
2012-02-08 00:29:47 +01:00
unsigned int ver_patch ;
2012-02-11 00:19:24 +01:00
unsigned int ver_build ;
2012-01-28 16:40:14 +01:00
const char * ver_date ;
const char * ver_time ;
}
g_x264_version =
{
2012-02-08 00:29:47 +01:00
( VER_X264_MAJOR ) ,
( VER_X264_MINOR ) ,
( VER_X264_PATCH ) ,
2012-02-11 00:19:24 +01:00
( VER_X264_BUILD ) ,
2012-01-28 16:40:14 +01:00
__DATE__ ,
__TIME__
} ;
//Compiler detection
2013-05-05 14:11:34 +02:00
//The following code was borrowed from MPC-HC project: http://mpc-hc.sf.net/
2012-01-28 16:40:14 +01:00
# if defined(__INTEL_COMPILER)
2012-12-01 15:54:07 +01:00
# if (__INTEL_COMPILER >= 1300)
static const char * g_x264_version_compiler = " ICL 13. " LAMEXP_MAKE_STR ( __INTEL_COMPILER_BUILD_DATE ) ;
# elif (__INTEL_COMPILER >= 1200)
static const char * g_x264_version_compiler = " ICL 12. " LAMEXP_MAKE_STR ( __INTEL_COMPILER_BUILD_DATE ) ;
2012-01-28 16:40:14 +01:00
# elif (__INTEL_COMPILER >= 1100)
2012-12-01 15:54:07 +01:00
static const char * g_x264_version_compiler = " ICL 11.x " ;
2012-01-28 16:40:14 +01:00
# elif (__INTEL_COMPILER >= 1000)
2012-12-01 15:54:07 +01:00
static const char * g_x264_version_compiler = " ICL 10.x " ;
2012-01-28 16:40:14 +01:00
# else
# error Compiler is not supported!
# endif
# elif defined(_MSC_VER)
2012-12-01 15:54:07 +01:00
# if (_MSC_VER == 1700)
# if (_MSC_FULL_VER < 170050727)
static const char * g_x264_version_compiler = " MSVC 2012-Beta " ;
# elif (_MSC_FULL_VER < 170051020)
static const char * g_x264_version_compiler = " MSVC 2012-RTM " ;
# elif (_MSC_FULL_VER < 170051106)
static const char * g_x264_version_compiler = " MSVC 2012-U1 CTP " ;
2013-05-05 14:11:34 +02:00
# elif (_MSC_FULL_VER < 170060315)
2012-12-01 15:54:07 +01:00
static const char * g_x264_version_compiler = " MSVC 2012-U1 " ;
2013-07-01 03:03:21 +02:00
# elif (_MSC_FULL_VER < 170060610)
2013-05-05 14:11:34 +02:00
static const char * g_x264_version_compiler = " MSVC 2012-U2 " ;
2013-07-01 03:03:21 +02:00
# elif (_MSC_FULL_VER == 170060610)
static const char * g_x264_version_compiler = " MSVC 2012-U3 " ;
2012-12-01 15:54:07 +01:00
# else
# error Compiler version is not supported yet!
# endif
# elif (_MSC_VER == 1600)
# if (_MSC_FULL_VER < 160040219)
static const char * g_x264_version_compiler = " MSVC 2010-RTM " ;
# elif (_MSC_FULL_VER == 160040219)
2012-01-28 16:40:14 +01:00
static const char * g_x264_version_compiler = " MSVC 2010-SP1 " ;
# else
2012-12-01 15:54:07 +01:00
# error Compiler version is not supported yet!
2012-01-28 16:40:14 +01:00
# endif
# elif (_MSC_VER == 1500)
# if (_MSC_FULL_VER >= 150030729)
static const char * g_x264_version_compiler = " MSVC 2008-SP1 " ;
# else
static const char * g_x264_version_compiler = " MSVC 2008 " ;
# endif
# else
# error Compiler is not supported!
# endif
// Note: /arch:SSE and /arch:SSE2 are only available for the x86 platform
# if !defined(_M_X64) && defined(_M_IX86_FP)
# if (_M_IX86_FP == 1)
2012-12-01 15:54:07 +01:00
X264_COMPILER_WARNING ( " SSE instruction set is enabled! " )
2012-01-28 16:40:14 +01:00
# elif (_M_IX86_FP == 2)
2012-12-01 15:54:07 +01:00
X264_COMPILER_WARNING ( " SSE2 instruction set is enabled! " )
2012-01-28 16:40:14 +01:00
# endif
# endif
# else
# error Compiler is not supported!
# endif
//Architecture detection
# if defined(_M_X64)
static const char * g_x264_version_arch = " x64 " ;
# elif defined(_M_IX86)
static const char * g_x264_version_arch = " x86 " ;
# else
# error Architecture is not supported!
# endif
/*
* Global exception handler
*/
LONG WINAPI x264_exception_handler ( __in struct _EXCEPTION_POINTERS * ExceptionInfo )
{
if ( GetCurrentThreadId ( ) ! = g_main_thread_id )
{
HANDLE mainThread = OpenThread ( THREAD_TERMINATE , FALSE , g_main_thread_id ) ;
if ( mainThread ) TerminateThread ( mainThread , ULONG_MAX ) ;
}
2012-12-15 19:12:56 +01:00
x264_fatal_exit ( L " Unhandeled exception handler invoked, application will exit! " ) ;
2012-01-28 16:40:14 +01:00
return LONG_MAX ;
}
/*
* Invalid parameters handler
*/
void x264_invalid_param_handler ( const wchar_t * , const wchar_t * , const wchar_t * , unsigned int , uintptr_t )
{
if ( GetCurrentThreadId ( ) ! = g_main_thread_id )
{
HANDLE mainThread = OpenThread ( THREAD_TERMINATE , FALSE , g_main_thread_id ) ;
if ( mainThread ) TerminateThread ( mainThread , ULONG_MAX ) ;
}
2012-12-15 19:12:56 +01:00
x264_fatal_exit ( L " Invalid parameter handler invoked, application will exit! " ) ;
2012-01-28 16:40:14 +01:00
}
/*
* Change console text color
*/
static void x264_console_color ( FILE * file , WORD attributes )
{
const HANDLE hConsole = ( HANDLE ) ( _get_osfhandle ( _fileno ( file ) ) ) ;
if ( ( hConsole ! = NULL ) & & ( hConsole ! = INVALID_HANDLE_VALUE ) )
{
SetConsoleTextAttribute ( hConsole , attributes ) ;
}
}
/*
* Qt message handler
*/
void x264_message_handler ( QtMsgType type , const char * msg )
{
static const char * GURU_MEDITATION = " \n \n GURU MEDITATION !!! \n \n " ;
QMutexLocker lock ( & g_x264_message_mutex ) ;
if ( g_x264_log_file )
{
static char prefix [ ] = " DWCF " ;
int index = qBound ( 0 , static_cast < int > ( type ) , 3 ) ;
unsigned int timestamp = static_cast < unsigned int > ( _time64 ( NULL ) % 3600 I64 ) ;
QString str = QString : : fromUtf8 ( msg ) . trimmed ( ) . replace ( ' \n ' , ' \t ' ) ;
fprintf ( g_x264_log_file , " [%c][%04u] %s \r \n " , prefix [ index ] , timestamp , str . toUtf8 ( ) . constData ( ) ) ;
fflush ( g_x264_log_file ) ;
}
if ( g_x264_console_attached )
{
UINT oldOutputCP = GetConsoleOutputCP ( ) ;
if ( oldOutputCP ! = CP_UTF8 ) SetConsoleOutputCP ( CP_UTF8 ) ;
switch ( type )
{
case QtCriticalMsg :
case QtFatalMsg :
fflush ( stdout ) ;
fflush ( stderr ) ;
x264_console_color ( stderr , FOREGROUND_RED | FOREGROUND_INTENSITY ) ;
fprintf ( stderr , GURU_MEDITATION ) ;
fprintf ( stderr , " %s \n " , msg ) ;
fflush ( stderr ) ;
break ;
case QtWarningMsg :
x264_console_color ( stderr , FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY ) ;
fprintf ( stderr , " %s \n " , msg ) ;
fflush ( stderr ) ;
break ;
default :
x264_console_color ( stderr , FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY ) ;
fprintf ( stderr , " %s \n " , msg ) ;
fflush ( stderr ) ;
break ;
}
x264_console_color ( stderr , FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED ) ;
if ( oldOutputCP ! = CP_UTF8 ) SetConsoleOutputCP ( oldOutputCP ) ;
}
else
{
2012-01-30 17:50:19 +01:00
QString temp ( " [x264][%1] %2 " ) ;
2012-01-28 16:40:14 +01:00
switch ( type )
{
case QtCriticalMsg :
case QtFatalMsg :
temp = temp . arg ( " C " , QString : : fromUtf8 ( msg ) ) ;
break ;
case QtWarningMsg :
temp = temp . arg ( " W " , QString : : fromUtf8 ( msg ) ) ;
break ;
default :
temp = temp . arg ( " I " , QString : : fromUtf8 ( msg ) ) ;
break ;
}
temp . replace ( " \n " , " \t " ) . append ( " \n " ) ;
OutputDebugStringA ( temp . toLatin1 ( ) . constData ( ) ) ;
}
if ( type = = QtCriticalMsg | | type = = QtFatalMsg )
{
lock . unlock ( ) ;
2012-12-15 19:12:56 +01:00
x264_fatal_exit ( L " The application has encountered a critical error and will exit now! " , QWCHAR ( QString : : fromUtf8 ( msg ) ) ) ;
2012-01-28 16:40:14 +01:00
}
}
/*
* Initialize the console
*/
void x264_init_console ( int argc , char * argv [ ] )
{
2012-02-08 00:29:47 +01:00
bool enableConsole = x264_is_prerelease ( ) | | ( X264_DEBUG ) ;
2012-01-28 16:40:14 +01:00
if ( _environ )
{
wchar_t * logfile = NULL ;
size_t logfile_len = 0 ;
if ( ! _wdupenv_s ( & logfile , & logfile_len , L " X264_LAUNCHER_LOGFILE " ) )
{
if ( logfile & & ( logfile_len > 0 ) )
{
FILE * temp = NULL ;
if ( ! _wfopen_s ( & temp , logfile , L " wb " ) )
{
fprintf ( temp , " %c%c%c " , 0xEF , 0xBB , 0xBF ) ;
g_x264_log_file = temp ;
}
free ( logfile ) ;
}
}
}
if ( ! X264_DEBUG )
{
for ( int i = 0 ; i < argc ; i + + )
{
if ( ! _stricmp ( argv [ i ] , " --console " ) )
{
enableConsole = true ;
}
else if ( ! _stricmp ( argv [ i ] , " --no-console " ) )
{
enableConsole = false ;
}
}
}
if ( enableConsole )
{
if ( ! g_x264_console_attached )
{
2012-02-14 00:27:02 +01:00
if ( AllocConsole ( ) )
2012-01-28 16:40:14 +01:00
{
SetConsoleCtrlHandler ( NULL , TRUE ) ;
SetConsoleTitle ( L " Simple x264 Launcher | Debug Console " ) ;
SetConsoleOutputCP ( CP_UTF8 ) ;
g_x264_console_attached = true ;
}
}
if ( g_x264_console_attached )
{
//-------------------------------------------------------------------
//See: http://support.microsoft.com/default.aspx?scid=kb;en-us;105305
//-------------------------------------------------------------------
const int flags = _O_WRONLY | _O_U8TEXT ;
int hCrtStdOut = _open_osfhandle ( ( intptr_t ) GetStdHandle ( STD_OUTPUT_HANDLE ) , flags ) ;
int hCrtStdErr = _open_osfhandle ( ( intptr_t ) GetStdHandle ( STD_ERROR_HANDLE ) , flags ) ;
FILE * hfStdOut = ( hCrtStdOut > = 0 ) ? _fdopen ( hCrtStdOut , " wb " ) : NULL ;
FILE * hfStdErr = ( hCrtStdErr > = 0 ) ? _fdopen ( hCrtStdErr , " wb " ) : NULL ;
if ( hfStdOut ) { * stdout = * hfStdOut ; std : : cout . rdbuf ( new std : : filebuf ( hfStdOut ) ) ; }
if ( hfStdErr ) { * stderr = * hfStdErr ; std : : cerr . rdbuf ( new std : : filebuf ( hfStdErr ) ) ; }
}
HWND hwndConsole = GetConsoleWindow ( ) ;
if ( ( hwndConsole ! = NULL ) & & ( hwndConsole ! = INVALID_HANDLE_VALUE ) )
{
HMENU hMenu = GetSystemMenu ( hwndConsole , 0 ) ;
EnableMenuItem ( hMenu , SC_CLOSE , MF_BYCOMMAND | MF_GRAYED ) ;
RemoveMenu ( hMenu , SC_CLOSE , MF_BYCOMMAND ) ;
SetWindowPos ( hwndConsole , HWND_TOP , 0 , 0 , 0 , 0 , SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED ) ;
SetWindowLong ( hwndConsole , GWL_STYLE , GetWindowLong ( hwndConsole , GWL_STYLE ) & ( ~ WS_MAXIMIZEBOX ) & ( ~ WS_MINIMIZEBOX ) ) ;
SetWindowPos ( hwndConsole , HWND_TOP , 0 , 0 , 0 , 0 , SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED ) ;
}
}
}
/*
* Version info
*/
unsigned int x264_version_major ( void )
{
return g_x264_version . ver_major ;
}
unsigned int x264_version_minor ( void )
{
2012-02-11 00:19:24 +01:00
return ( g_x264_version . ver_minor * 10 ) + ( g_x264_version . ver_patch % 10 ) ;
2012-01-28 16:40:14 +01:00
}
2012-02-11 00:19:24 +01:00
unsigned int x264_version_build ( void )
2012-02-08 00:29:47 +01:00
{
2012-02-11 00:19:24 +01:00
return g_x264_version . ver_build ;
2012-02-08 00:29:47 +01:00
}
2012-01-28 16:40:14 +01:00
const char * x264_version_compiler ( void )
{
return g_x264_version_compiler ;
}
const char * x264_version_arch ( void )
{
return g_x264_version_arch ;
}
2012-02-10 01:58:45 +01:00
/*
* Check for portable mode
*/
bool x264_portable ( void )
{
static bool detected = false ;
static bool portable = false ;
if ( ! detected )
{
portable = portable | | QFileInfo ( QApplication : : applicationFilePath ( ) ) . baseName ( ) . contains ( QRegExp ( " ^portable[^A-Za-z0-9] " , Qt : : CaseInsensitive ) ) ;
portable = portable | | QFileInfo ( QApplication : : applicationFilePath ( ) ) . baseName ( ) . contains ( QRegExp ( " [^A-Za-z0-9]portable[^A-Za-z0-9] " , Qt : : CaseInsensitive ) ) ;
portable = portable | | QFileInfo ( QApplication : : applicationFilePath ( ) ) . baseName ( ) . contains ( QRegExp ( " [^A-Za-z0-9]portable$ " , Qt : : CaseInsensitive ) ) ;
detected = true ;
}
return portable ;
}
2012-02-10 18:40:28 +01:00
/*
* Get data path ( i . e . path to store config files )
*/
const QString & x264_data_path ( void )
{
2012-04-30 16:56:01 +02:00
static QString pathCache ;
2012-02-10 18:40:28 +01:00
2012-04-30 16:56:01 +02:00
if ( pathCache . isNull ( ) )
2012-02-10 18:40:28 +01:00
{
if ( ! x264_portable ( ) )
{
2012-04-30 16:56:01 +02:00
pathCache = QDesktopServices : : storageLocation ( QDesktopServices : : DataLocation ) ;
2012-02-10 18:40:28 +01:00
}
2012-04-30 16:56:01 +02:00
if ( pathCache . isEmpty ( ) | | x264_portable ( ) )
2012-02-10 18:40:28 +01:00
{
2012-04-30 16:56:01 +02:00
pathCache = QApplication : : applicationDirPath ( ) ;
2012-02-10 18:40:28 +01:00
}
2012-04-30 16:56:01 +02:00
if ( ! QDir ( pathCache ) . mkpath ( " . " ) )
2012-02-10 18:40:28 +01:00
{
2012-04-30 16:56:01 +02:00
qWarning ( " Data directory could not be created: \n %s \n " , pathCache . toUtf8 ( ) . constData ( ) ) ;
pathCache = QDir : : currentPath ( ) ;
2012-02-10 18:40:28 +01:00
}
}
2012-04-30 16:56:01 +02:00
return pathCache ;
2012-02-10 18:40:28 +01:00
}
2012-01-28 16:40:14 +01:00
/*
* Get build date date
*/
const QDate & x264_version_date ( void )
{
if ( ! g_x264_version_date . isValid ( ) )
{
int date [ 3 ] = { 0 , 0 , 0 } ; char temp [ 12 ] = { ' \0 ' } ;
strncpy_s ( temp , 12 , g_x264_version . ver_date , _TRUNCATE ) ;
if ( strlen ( temp ) = = 11 )
{
temp [ 3 ] = temp [ 6 ] = ' \0 ' ;
date [ 2 ] = atoi ( & temp [ 4 ] ) ;
date [ 0 ] = atoi ( & temp [ 7 ] ) ;
for ( int j = 0 ; j < 12 ; j + + )
{
if ( ! _strcmpi ( & temp [ 0 ] , g_x264_months [ j ] ) )
{
date [ 1 ] = j + 1 ;
break ;
}
}
g_x264_version_date = QDate ( date [ 0 ] , date [ 1 ] , date [ 2 ] ) ;
}
if ( ! g_x264_version_date . isValid ( ) )
{
qFatal ( " Internal error: Date format could not be recognized! " ) ;
}
}
return g_x264_version_date ;
}
const char * x264_version_time ( void )
{
return g_x264_version . ver_time ;
}
2012-02-02 22:53:40 +01:00
bool x264_is_prerelease ( void )
{
2012-02-04 19:09:27 +01:00
return ( VER_X264_PRE_RELEASE ) ;
2012-02-02 22:53:40 +01:00
}
2012-02-07 03:37:47 +01:00
/*
* CPUID prototype ( actual function is in ASM code )
*/
extern " C "
{
void x264_cpu_cpuid ( unsigned int op , unsigned int * eax , unsigned int * ebx , unsigned int * ecx , unsigned int * edx ) ;
}
2012-01-28 16:40:14 +01:00
/*
* Detect CPU features
*/
2012-02-07 21:48:25 +01:00
const x264_cpu_t x264_detect_cpu_features ( int argc , char * * argv )
2012-01-28 16:40:14 +01:00
{
typedef BOOL ( WINAPI * IsWow64ProcessFun ) ( __in HANDLE hProcess , __out PBOOL Wow64Process ) ;
typedef VOID ( WINAPI * GetNativeSystemInfoFun ) ( __out LPSYSTEM_INFO lpSystemInfo ) ;
static IsWow64ProcessFun IsWow64ProcessPtr = NULL ;
static GetNativeSystemInfoFun GetNativeSystemInfoPtr = NULL ;
x264_cpu_t features ;
SYSTEM_INFO systemInfo ;
2012-02-07 03:37:47 +01:00
unsigned int CPUInfo [ 4 ] ;
2012-01-28 16:40:14 +01:00
char CPUIdentificationString [ 0x40 ] ;
char CPUBrandString [ 0x40 ] ;
memset ( & features , 0 , sizeof ( x264_cpu_t ) ) ;
memset ( & systemInfo , 0 , sizeof ( SYSTEM_INFO ) ) ;
memset ( CPUIdentificationString , 0 , sizeof ( CPUIdentificationString ) ) ;
memset ( CPUBrandString , 0 , sizeof ( CPUBrandString ) ) ;
2012-02-07 03:37:47 +01:00
x264_cpu_cpuid ( 0 , & CPUInfo [ 0 ] , & CPUInfo [ 1 ] , & CPUInfo [ 2 ] , & CPUInfo [ 3 ] ) ;
memcpy ( CPUIdentificationString , & CPUInfo [ 1 ] , 4 ) ;
memcpy ( CPUIdentificationString + 4 , & CPUInfo [ 3 ] , 4 ) ;
memcpy ( CPUIdentificationString + 8 , & CPUInfo [ 2 ] , 4 ) ;
2012-01-28 16:40:14 +01:00
features . intel = ( _stricmp ( CPUIdentificationString , " GenuineIntel " ) = = 0 ) ;
strncpy_s ( features . vendor , 0x40 , CPUIdentificationString , _TRUNCATE ) ;
if ( CPUInfo [ 0 ] > = 1 )
{
2012-02-07 03:37:47 +01:00
x264_cpu_cpuid ( 1 , & CPUInfo [ 0 ] , & CPUInfo [ 1 ] , & CPUInfo [ 2 ] , & CPUInfo [ 3 ] ) ;
features . mmx = ( CPUInfo [ 3 ] & 0x800000U ) | | false ;
features . sse = ( CPUInfo [ 3 ] & 0x2000000U ) | | false ;
features . sse2 = ( CPUInfo [ 3 ] & 0x4000000U ) | | false ;
features . ssse3 = ( CPUInfo [ 2 ] & 0x200U ) | | false ;
features . sse3 = ( CPUInfo [ 2 ] & 0x1U ) | | false ;
features . ssse3 = ( CPUInfo [ 2 ] & 0x200U ) | | false ;
2012-01-28 16:40:14 +01:00
features . stepping = CPUInfo [ 0 ] & 0xf ;
features . model = ( ( CPUInfo [ 0 ] > > 4 ) & 0xf ) + ( ( ( CPUInfo [ 0 ] > > 16 ) & 0xf ) < < 4 ) ;
features . family = ( ( CPUInfo [ 0 ] > > 8 ) & 0xf ) + ( ( CPUInfo [ 0 ] > > 20 ) & 0xff ) ;
2012-02-07 03:37:47 +01:00
if ( features . sse ) features . mmx2 = true ; //MMXEXT is a subset of SSE!
2012-01-28 16:40:14 +01:00
}
2012-02-07 03:37:47 +01:00
x264_cpu_cpuid ( 0x80000000U , & CPUInfo [ 0 ] , & CPUInfo [ 1 ] , & CPUInfo [ 2 ] , & CPUInfo [ 3 ] ) ;
unsigned int nExIds = qBound ( 0x80000000U , CPUInfo [ 0 ] , 0x80000004U ) ;
if ( ( _stricmp ( CPUIdentificationString , " AuthenticAMD " ) = = 0 ) & & ( nExIds > = 0x80000001U ) )
{
x264_cpu_cpuid ( 0x80000001U , & CPUInfo [ 0 ] , & CPUInfo [ 1 ] , & CPUInfo [ 2 ] , & CPUInfo [ 3 ] ) ;
features . mmx2 = features . mmx2 | | ( CPUInfo [ 3 ] & 0x00400000U ) ;
}
2012-01-28 16:40:14 +01:00
2012-02-07 03:37:47 +01:00
for ( unsigned int i = 0x80000002U ; i < = nExIds ; + + i )
2012-01-28 16:40:14 +01:00
{
2012-02-07 03:37:47 +01:00
x264_cpu_cpuid ( i , & CPUInfo [ 0 ] , & CPUInfo [ 1 ] , & CPUInfo [ 2 ] , & CPUInfo [ 3 ] ) ;
2012-01-28 16:40:14 +01:00
switch ( i )
{
2012-02-07 03:37:47 +01:00
case 0x80000002U :
2012-01-28 16:40:14 +01:00
memcpy ( CPUBrandString , CPUInfo , sizeof ( CPUInfo ) ) ;
break ;
2012-02-07 03:37:47 +01:00
case 0x80000003U :
2012-01-28 16:40:14 +01:00
memcpy ( CPUBrandString + 16 , CPUInfo , sizeof ( CPUInfo ) ) ;
break ;
2012-02-07 03:37:47 +01:00
case 0x80000004U :
2012-01-28 16:40:14 +01:00
memcpy ( CPUBrandString + 32 , CPUInfo , sizeof ( CPUInfo ) ) ;
break ;
}
}
strncpy_s ( features . brand , 0x40 , CPUBrandString , _TRUNCATE ) ;
if ( strlen ( features . brand ) < 1 ) strncpy_s ( features . brand , 0x40 , " Unknown " , _TRUNCATE ) ;
if ( strlen ( features . vendor ) < 1 ) strncpy_s ( features . vendor , 0x40 , " Unknown " , _TRUNCATE ) ;
# if !defined(_M_X64 ) && !defined(_M_IA64)
if ( ! IsWow64ProcessPtr | | ! GetNativeSystemInfoPtr )
{
QLibrary Kernel32Lib ( " kernel32.dll " ) ;
IsWow64ProcessPtr = ( IsWow64ProcessFun ) Kernel32Lib . resolve ( " IsWow64Process " ) ;
GetNativeSystemInfoPtr = ( GetNativeSystemInfoFun ) Kernel32Lib . resolve ( " GetNativeSystemInfo " ) ;
}
if ( IsWow64ProcessPtr )
{
BOOL x64 = FALSE ;
if ( IsWow64ProcessPtr ( GetCurrentProcess ( ) , & x64 ) )
{
features . x64 = x64 ;
}
}
if ( GetNativeSystemInfoPtr )
{
GetNativeSystemInfoPtr ( & systemInfo ) ;
}
else
{
GetSystemInfo ( & systemInfo ) ;
}
features . count = qBound ( 1UL , systemInfo . dwNumberOfProcessors , 64UL ) ;
# else
GetNativeSystemInfo ( & systemInfo ) ;
features . count = systemInfo . dwNumberOfProcessors ;
features . x64 = true ;
# endif
if ( ( argv ! = NULL ) & & ( argc > 0 ) )
{
bool flag = false ;
for ( int i = 0 ; i < argc ; i + + )
{
if ( ! _stricmp ( " --force-cpu-no-64bit " , argv [ i ] ) ) { flag = true ; features . x64 = false ; }
2012-02-06 22:40:07 +01:00
if ( ! _stricmp ( " --force-cpu-no-mmx " , argv [ i ] ) ) { flag = true ; features . mmx = false ; }
2012-02-07 03:37:47 +01:00
if ( ! _stricmp ( " --force-cpu-no-mmx2 " , argv [ i ] ) ) { flag = true ; features . mmx2 = false ; }
2012-01-28 16:40:14 +01:00
if ( ! _stricmp ( " --force-cpu-no-sse " , argv [ i ] ) ) { flag = true ; features . sse = features . sse2 = features . sse3 = features . ssse3 = false ; }
if ( ! _stricmp ( " --force-cpu-no-intel " , argv [ i ] ) ) { flag = true ; features . intel = false ; }
2012-02-06 22:40:07 +01:00
if ( ! _stricmp ( " --force-cpu-have-64bit " , argv [ i ] ) ) { flag = true ; features . x64 = true ; }
if ( ! _stricmp ( " --force-cpu-have-mmx " , argv [ i ] ) ) { flag = true ; features . mmx = true ; }
2012-02-07 03:37:47 +01:00
if ( ! _stricmp ( " --force-cpu-have-mmx2 " , argv [ i ] ) ) { flag = true ; features . mmx2 = true ; }
2012-02-06 22:40:07 +01:00
if ( ! _stricmp ( " --force-cpu-have-sse " , argv [ i ] ) ) { flag = true ; features . sse = features . sse2 = features . sse3 = features . ssse3 = true ; }
if ( ! _stricmp ( " --force-cpu-have-intel " , argv [ i ] ) ) { flag = true ; features . intel = true ; }
2012-01-28 16:40:14 +01:00
}
if ( flag ) qWarning ( " CPU flags overwritten by user-defined parameters. Take care! \n " ) ;
}
return features ;
}
/*
* Get the native operating system version
*/
DWORD x264_get_os_version ( void )
{
OSVERSIONINFO osVerInfo ;
memset ( & osVerInfo , 0 , sizeof ( OSVERSIONINFO ) ) ;
osVerInfo . dwOSVersionInfoSize = sizeof ( OSVERSIONINFO ) ;
DWORD version = 0 ;
if ( GetVersionEx ( & osVerInfo ) = = TRUE )
{
if ( osVerInfo . dwPlatformId ! = VER_PLATFORM_WIN32_NT )
{
throw " Ouuups: Not running under Windows NT. This is not supposed to happen! " ;
}
version = ( DWORD ) ( ( osVerInfo . dwMajorVersion < < 16 ) | ( osVerInfo . dwMinorVersion & 0xffff ) ) ;
}
return version ;
}
/*
* Check for compatibility mode
*/
static bool x264_check_compatibility_mode ( const char * exportName , const char * executableName )
{
QLibrary kernel32 ( " kernel32.dll " ) ;
if ( exportName ! = NULL )
{
if ( kernel32 . resolve ( exportName ) ! = NULL )
{
qWarning ( " Function '%s' exported from 'kernel32.dll' -> Windows compatibility mode! " , exportName ) ;
qFatal ( " %s " , QApplication : : tr ( " Executable '%1' doesn't support Windows compatibility mode. " ) . arg ( QString : : fromLatin1 ( executableName ) ) . toLatin1 ( ) . constData ( ) ) ;
return false ;
}
}
return true ;
}
/*
* Check for process elevation
*/
static bool x264_check_elevation ( void )
{
typedef enum { x264_token_elevationType_class = 18 , x264_token_elevation_class = 20 } X264_TOKEN_INFORMATION_CLASS ;
typedef enum { x264_elevationType_default = 1 , x264_elevationType_full , x264_elevationType_limited } X264_TOKEN_ELEVATION_TYPE ;
HANDLE hToken = NULL ;
bool bIsProcessElevated = false ;
if ( OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_QUERY , & hToken ) )
{
X264_TOKEN_ELEVATION_TYPE tokenElevationType ;
DWORD returnLength ;
if ( GetTokenInformation ( hToken , ( TOKEN_INFORMATION_CLASS ) x264_token_elevationType_class , & tokenElevationType , sizeof ( X264_TOKEN_ELEVATION_TYPE ) , & returnLength ) )
{
if ( returnLength = = sizeof ( X264_TOKEN_ELEVATION_TYPE ) )
{
switch ( tokenElevationType )
{
case x264_elevationType_default :
qDebug ( " Process token elevation type: Default -> UAC is disabled. \n " ) ;
break ;
case x264_elevationType_full :
qWarning ( " Process token elevation type: Full -> potential security risk! \n " ) ;
bIsProcessElevated = true ;
break ;
case x264_elevationType_limited :
qDebug ( " Process token elevation type: Limited -> not elevated. \n " ) ;
break ;
}
}
}
CloseHandle ( hToken ) ;
}
else
{
qWarning ( " Failed to open process token! " ) ;
}
return ! bIsProcessElevated ;
}
/*
* Initialize Qt framework
*/
bool x264_init_qt ( int argc , char * argv [ ] )
{
static bool qt_initialized = false ;
bool isWine = false ;
typedef BOOL ( WINAPI * SetDllDirectoryProc ) ( WCHAR * lpPathName ) ;
//Don't initialized again, if done already
if ( qt_initialized )
{
return true ;
}
//Secure DLL loading
QLibrary kernel32 ( " kernel32.dll " ) ;
if ( kernel32 . load ( ) )
{
SetDllDirectoryProc pSetDllDirectory = ( SetDllDirectoryProc ) kernel32 . resolve ( " SetDllDirectoryW " ) ;
if ( pSetDllDirectory ! = NULL ) pSetDllDirectory ( L " " ) ;
kernel32 . unload ( ) ;
}
//Extract executable name from argv[] array
char * executableName = argv [ 0 ] ;
while ( char * temp = strpbrk ( executableName , " \\ /:? " ) )
{
executableName = temp + 1 ;
}
//Check Qt version
qDebug ( " Using Qt v%s [%s], %s, %s " , qVersion ( ) , QLibraryInfo : : buildDate ( ) . toString ( Qt : : ISODate ) . toLatin1 ( ) . constData ( ) , ( qSharedBuild ( ) ? " DLL " : " Static " ) , QLibraryInfo : : buildKey ( ) . toLatin1 ( ) . constData ( ) ) ;
qDebug ( " Compiled with Qt v%s [%s], %s \n " , QT_VERSION_STR , QT_PACKAGEDATE_STR , QT_BUILD_KEY ) ;
if ( _stricmp ( qVersion ( ) , QT_VERSION_STR ) )
{
qFatal ( " %s " , QApplication : : tr ( " Executable '%1' requires Qt v%2, but found Qt v%3. " ) . arg ( QString : : fromLatin1 ( executableName ) , QString : : fromLatin1 ( QT_VERSION_STR ) , QString : : fromLatin1 ( qVersion ( ) ) ) . toLatin1 ( ) . constData ( ) ) ;
return false ;
}
if ( QLibraryInfo : : buildKey ( ) . compare ( QString : : fromLatin1 ( QT_BUILD_KEY ) , Qt : : CaseInsensitive ) )
{
qFatal ( " %s " , QApplication : : tr ( " Executable '%1' was built for Qt '%2', but found Qt '%3'. " ) . arg ( QString : : fromLatin1 ( executableName ) , QString : : fromLatin1 ( QT_BUILD_KEY ) , QLibraryInfo : : buildKey ( ) ) . toLatin1 ( ) . constData ( ) ) ;
return false ;
}
//Check the Windows version
switch ( QSysInfo : : windowsVersion ( ) & QSysInfo : : WV_NT_based )
{
case 0 :
case QSysInfo : : WV_NT :
case QSysInfo : : WV_2000 :
2012-02-11 03:11:29 +01:00
qFatal ( " %s " , QApplication : : tr ( " Executable '%1' requires Windows XP or later. " ) . arg ( QString : : fromLatin1 ( executableName ) ) . toLatin1 ( ) . constData ( ) ) ;
2012-01-28 16:40:14 +01:00
break ;
2012-02-11 03:11:29 +01:00
//qDebug("Running on Windows 2000 (not officially supported!).\n");
//x264_check_compatibility_mode("GetNativeSystemInfo", executableName);
2012-01-28 16:40:14 +01:00
case QSysInfo : : WV_XP :
qDebug ( " Running on Windows XP. \n " ) ;
x264_check_compatibility_mode ( " GetLargePageMinimum " , executableName ) ;
break ;
case QSysInfo : : WV_2003 :
qDebug ( " Running on Windows Server 2003 or Windows XP x64-Edition. \n " ) ;
x264_check_compatibility_mode ( " GetLocaleInfoEx " , executableName ) ;
break ;
case QSysInfo : : WV_VISTA :
qDebug ( " Running on Windows Vista or Windows Server 2008. \n " ) ;
x264_check_compatibility_mode ( " CreateRemoteThreadEx " , executableName ) ;
break ;
case QSysInfo : : WV_WINDOWS7 :
qDebug ( " Running on Windows 7 or Windows Server 2008 R2. \n " ) ;
x264_check_compatibility_mode ( NULL , executableName ) ;
break ;
default :
{
DWORD osVersionNo = x264_get_os_version ( ) ;
qWarning ( " Running on an unknown/untested WinNT-based OS (v%u.%u). \n " , HIWORD ( osVersionNo ) , LOWORD ( osVersionNo ) ) ;
}
break ;
}
//Check for Wine
QLibrary ntdll ( " ntdll.dll " ) ;
if ( ntdll . load ( ) )
{
if ( ntdll . resolve ( " wine_nt_to_unix_file_name " ) ! = NULL ) isWine = true ;
if ( ntdll . resolve ( " wine_get_version " ) ! = NULL ) isWine = true ;
if ( isWine ) qWarning ( " It appears we are running under Wine, unexpected things might happen! \n " ) ;
ntdll . unload ( ) ;
}
//Create Qt application instance and setup version info
QApplication * application = new QApplication ( argc , argv ) ;
2012-01-30 17:50:19 +01:00
application - > setApplicationName ( " Simple x264 Launcher " ) ;
2012-01-28 16:40:14 +01:00
application - > setApplicationVersion ( QString ( ) . sprintf ( " %d.%02d " , x264_version_major ( ) , x264_version_minor ( ) ) ) ;
application - > setOrganizationName ( " LoRd_MuldeR " ) ;
application - > setOrganizationDomain ( " mulder.at.gg " ) ;
application - > setWindowIcon ( QIcon ( " :/icons/movie.ico " ) ) ;
//application->setEventFilter(x264_event_filter);
//Set text Codec for locale
QTextCodec : : setCodecForLocale ( QTextCodec : : codecForName ( " UTF-8 " ) ) ;
//Load plugins from application directory
QCoreApplication : : setLibraryPaths ( QStringList ( ) < < QApplication : : applicationDirPath ( ) ) ;
qDebug ( " Library Path: \n %s \n " , QApplication : : libraryPaths ( ) . first ( ) . toUtf8 ( ) . constData ( ) ) ;
//Check for supported image formats
QList < QByteArray > supportedFormats = QImageReader : : supportedImageFormats ( ) ;
for ( int i = 0 ; g_x264_imageformats [ i ] ; i + + )
{
if ( ! supportedFormats . contains ( g_x264_imageformats [ i ] ) )
{
qFatal ( " Qt initialization error: QImageIOHandler for '%s' missing! " , g_x264_imageformats [ i ] ) ;
return false ;
}
}
//Add default translations
// g_x264_translation.files.insert(x264_DEFAULT_LANGID, "");
// g_x264_translation.names.insert(x264_DEFAULT_LANGID, "English");
//Check for process elevation
if ( ! x264_check_elevation ( ) )
{
2012-01-30 17:50:19 +01:00
if ( QMessageBox : : warning ( NULL , " Simple x264 Launcher " , " <nobr>Program was started with elevated rights. This is a potential security risk!</nobr> " , " Quit Program (Recommended) " , " Ignore " ) = = 0 )
2012-01-28 16:40:14 +01:00
{
return false ;
}
}
//Update console icon, if a console is attached
if ( g_x264_console_attached & & ! isWine )
{
typedef DWORD ( __stdcall * SetConsoleIconFun ) ( HICON ) ;
QLibrary kernel32 ( " kernel32.dll " ) ;
if ( kernel32 . load ( ) )
{
SetConsoleIconFun SetConsoleIconPtr = ( SetConsoleIconFun ) kernel32 . resolve ( " SetConsoleIcon " ) ;
if ( SetConsoleIconPtr ! = NULL ) SetConsoleIconPtr ( QIcon ( " :/icons/movie.ico " ) . pixmap ( 16 , 16 ) . toWinHICON ( ) ) ;
kernel32 . unload ( ) ;
}
}
//Done
qt_initialized = true ;
return true ;
}
2012-02-04 01:12:21 +01:00
/*
* Shutdown the computer
*/
bool x264_shutdown_computer ( const QString & message , const unsigned long timeout , const bool forceShutdown )
{
HANDLE hToken = NULL ;
if ( OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , & hToken ) )
{
TOKEN_PRIVILEGES privileges ;
memset ( & privileges , 0 , sizeof ( TOKEN_PRIVILEGES ) ) ;
privileges . PrivilegeCount = 1 ;
privileges . Privileges [ 0 ] . Attributes = SE_PRIVILEGE_ENABLED ;
if ( LookupPrivilegeValue ( NULL , SE_SHUTDOWN_NAME , & privileges . Privileges [ 0 ] . Luid ) )
{
if ( AdjustTokenPrivileges ( hToken , FALSE , & privileges , NULL , NULL , NULL ) )
{
const DWORD reason = SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_FLAG_PLANNED ;
return InitiateSystemShutdownEx ( NULL , const_cast < wchar_t * > ( QWCHAR ( message ) ) , timeout , forceShutdown ? TRUE : FALSE , FALSE , reason ) ;
}
}
}
return false ;
}
2012-01-28 16:40:14 +01:00
/*
* Check for debugger ( detect routine )
*/
static bool x264_check_for_debugger ( void )
{
__try
{
DebugBreak ( ) ;
}
__except ( GetExceptionCode ( ) = = EXCEPTION_BREAKPOINT ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
{
return false ;
}
return true ;
}
/*
* Check for debugger ( thread proc )
*/
static void WINAPI x264_debug_thread_proc ( __in LPVOID lpParameter )
{
while ( ! ( IsDebuggerPresent ( ) | | x264_check_for_debugger ( ) ) )
{
Sleep ( 333 ) ;
}
2012-12-15 19:12:56 +01:00
for ( ; ; )
{
TerminateProcess ( GetCurrentProcess ( ) , - 1 ) ;
}
2012-01-28 16:40:14 +01:00
}
/*
* Check for debugger ( startup routine )
*/
static HANDLE x264_debug_thread_init ( void )
{
if ( IsDebuggerPresent ( ) | | x264_check_for_debugger ( ) )
{
2012-12-15 19:12:56 +01:00
x264_fatal_exit ( L " Not a debug build. Please unload debugger and try again! " ) ;
2012-01-28 16:40:14 +01:00
}
return CreateThread ( NULL , NULL , reinterpret_cast < LPTHREAD_START_ROUTINE > ( & x264_debug_thread_proc ) , NULL , NULL , NULL ) ;
}
2012-12-15 19:12:56 +01:00
/*
* Fatal application exit
*/
# pragma intrinsic(_InterlockedExchange)
void x264_fatal_exit ( const wchar_t * exitMessage , const wchar_t * errorBoxMessage )
{
static volatile long bFatalFlag = 0L ;
if ( _InterlockedExchange ( & bFatalFlag , 1L ) = = 0L )
{
if ( GetCurrentThreadId ( ) ! = g_main_thread_id )
{
HANDLE mainThread = OpenThread ( THREAD_TERMINATE , FALSE , g_main_thread_id ) ;
if ( mainThread ) TerminateThread ( mainThread , ULONG_MAX ) ;
}
if ( errorBoxMessage )
{
MessageBoxW ( NULL , errorBoxMessage , L " Simple x264 Launcher - GURU MEDITATION " , MB_ICONERROR | MB_TOPMOST | MB_TASKMODAL ) ;
}
FatalAppExit ( 0 , exitMessage ) ;
for ( ; ; )
{
TerminateProcess ( GetCurrentProcess ( ) , - 1 ) ;
}
}
}
2012-01-28 16:40:14 +01:00
/*
* Initialize debug thread
*/
static const HANDLE g_debug_thread = X264_DEBUG ? NULL : x264_debug_thread_init ( ) ;
/*
* Get number private bytes [ debug only ]
*/
SIZE_T x264_dbg_private_bytes ( void )
{
# if X264_DEBUG
PROCESS_MEMORY_COUNTERS_EX memoryCounters ;
memoryCounters . cb = sizeof ( PROCESS_MEMORY_COUNTERS_EX ) ;
GetProcessMemoryInfo ( GetCurrentProcess ( ) , ( PPROCESS_MEMORY_COUNTERS ) & memoryCounters , sizeof ( PROCESS_MEMORY_COUNTERS_EX ) ) ;
return memoryCounters . PrivateUsage ;
# else
throw " Cannot call this function in a non-debug build! " ;
# endif //X264_DEBUG
}
/*
* Finalization function
*/
void x264_finalization ( void )
{
2012-04-30 16:56:01 +02:00
//Destroy Qt application object
QApplication * application = dynamic_cast < QApplication * > ( QApplication : : instance ( ) ) ;
X264_DELETE ( application ) ;
//Free STDOUT and STDERR buffers
if ( g_x264_console_attached )
{
if ( std : : filebuf * tmp = dynamic_cast < std : : filebuf * > ( std : : cout . rdbuf ( ) ) )
{
std : : cout . rdbuf ( NULL ) ;
X264_DELETE ( tmp ) ;
}
if ( std : : filebuf * tmp = dynamic_cast < std : : filebuf * > ( std : : cerr . rdbuf ( ) ) )
{
std : : cerr . rdbuf ( NULL ) ;
X264_DELETE ( tmp ) ;
}
}
2012-01-28 16:40:14 +01:00
}