Implemented support for using 32-Bit Avisynth with 64-Bit x264.

This commit is contained in:
LoRd_MuldeR 2012-01-31 00:13:32 +01:00
parent a30b5b7300
commit a3ff0fda24
12 changed files with 443 additions and 43 deletions

View File

@ -233,7 +233,7 @@
<item> <item>
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>Quantiter/CRF:</string> <string>Quantizer/CRF:</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -606,7 +606,7 @@
</spacer> </spacer>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="labelHelpScreen">
<property name="palette"> <property name="palette">
<palette> <palette>
<active> <active>

View File

@ -30,6 +30,9 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<widget class="QTableView" name="jobsView"> <widget class="QTableView" name="jobsView">
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="alternatingRowColors"> <property name="alternatingRowColors">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -96,6 +99,9 @@
<family>Lucida Console</family> <family>Lucida Console</family>
</font> </font>
</property> </property>
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="horizontalScrollBarPolicy"> <property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum> <enum>Qt::ScrollBarAlwaysOff</enum>
</property> </property>
@ -296,7 +302,17 @@
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionAbout"/> <addaction name="actionAbout"/>
</widget> </widget>
<widget class="QMenu" name="menuJob">
<property name="title">
<string>Job</string>
</property>
<addaction name="actionJob_New"/>
<addaction name="separator"/>
<addaction name="actionJob_Start"/>
<addaction name="actionJob_Abort"/>
</widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menuJob"/>
<addaction name="menu"/> <addaction name="menu"/>
</widget> </widget>
<action name="actionExit"> <action name="actionExit">
@ -371,6 +387,39 @@
<string>x264 BluRay Authoring</string> <string>x264 BluRay Authoring</string>
</property> </property>
</action> </action>
<action name="actionJob_New">
<property name="icon">
<iconset resource="../res/resources.qrc">
<normaloff>:/buttons/add.png</normaloff>:/buttons/add.png</iconset>
</property>
<property name="text">
<string>Add New Job</string>
</property>
</action>
<action name="actionJob_Start">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../res/resources.qrc">
<normaloff>:/buttons/play_big.png</normaloff>:/buttons/play_big.png</iconset>
</property>
<property name="text">
<string>Start Job</string>
</property>
</action>
<action name="actionJob_Abort">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../res/resources.qrc">
<normaloff>:/buttons/cancel.png</normaloff>:/buttons/cancel.png</iconset>
</property>
<property name="text">
<string>Abort Job</string>
</property>
</action>
</widget> </widget>
<tabstops> <tabstops>
<tabstop>buttonAddJob</tabstop> <tabstop>buttonAddJob</tabstop>
@ -400,5 +449,53 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>actionJob_New</sender>
<signal>triggered()</signal>
<receiver>buttonAddJob</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>73</x>
<y>617</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionJob_Start</sender>
<signal>triggered()</signal>
<receiver>buttonStartJob</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>547</x>
<y>617</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionJob_Abort</sender>
<signal>triggered()</signal>
<receiver>buttonAbortJob</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>657</x>
<y>617</y>
</hint>
</hints>
</connection>
</connections> </connections>
</ui> </ui>

BIN
res/buttons/page_paste.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

View File

@ -14,6 +14,7 @@
<file>buttons/find.png</file> <file>buttons/find.png</file>
<file>buttons/information.png</file> <file>buttons/information.png</file>
<file>buttons/lightning.png</file> <file>buttons/lightning.png</file>
<file>buttons/page_paste.png</file>
<file>buttons/play.png</file> <file>buttons/play.png</file>
<file>buttons/play_big.png</file> <file>buttons/play_big.png</file>
<file>buttons/world_link.png</file> <file>buttons/world_link.png</file>

View File

@ -23,6 +23,8 @@
#include "thread_encode.h" #include "thread_encode.h"
#include <QIcon> #include <QIcon>
#include <QApplication>
#include <QClipboard>
LogFileModel::LogFileModel(void) LogFileModel::LogFileModel(void)
{ {
@ -76,6 +78,16 @@ QVariant LogFileModel::data(const QModelIndex &index, int role) const
return QVariant(); return QVariant();
} }
///////////////////////////////////////////////////////////////////////////////
// Public API
///////////////////////////////////////////////////////////////////////////////
void LogFileModel::copyToClipboard(void)
{
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(m_lines.join("\r\n"));
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Slots // Slots
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -43,6 +43,8 @@ public:
virtual QModelIndex parent (const QModelIndex &index) const; virtual QModelIndex parent (const QModelIndex &index) const;
virtual QVariant data(const QModelIndex &index, int role) const; virtual QVariant data(const QModelIndex &index, int role) const;
void copyToClipboard(void);
protected: protected:
QStringList m_lines; QStringList m_lines;
bool m_firstLine; bool m_firstLine;

View File

@ -27,6 +27,7 @@
#include <QDate> #include <QDate>
#include <QTime> #include <QTime>
#include <QDateTime>
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include <QProcess> #include <QProcess>
@ -44,7 +45,6 @@ typedef BOOL (WINAPI *AssignProcessToJobObjectFun)(__in HANDLE hJob, __in HANDLE
* Static vars * Static vars
*/ */
QMutex EncodeThread::m_mutex_startProcess; QMutex EncodeThread::m_mutex_startProcess;
HANDLE EncodeThread::m_handle_jobObject = NULL;
/* /*
* Macros * Macros
@ -80,7 +80,8 @@ EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputF
m_outputFileName(outputFileName), m_outputFileName(outputFileName),
m_options(new OptionsModel(*options)), m_options(new OptionsModel(*options)),
m_binDir(binDir), m_binDir(binDir),
m_x64(x64) m_x64(x64),
m_handle_jobObject(NULL)
{ {
m_abort = false; m_abort = false;
} }
@ -88,6 +89,12 @@ EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputF
EncodeThread::~EncodeThread(void) EncodeThread::~EncodeThread(void)
{ {
X264_DELETE(m_options); X264_DELETE(m_options);
if(m_handle_jobObject)
{
CloseHandle(m_handle_jobObject);
m_handle_jobObject = NULL;
}
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -96,10 +103,11 @@ EncodeThread::~EncodeThread(void)
void EncodeThread::run(void) void EncodeThread::run(void)
{ {
m_progress = 0;
m_status = JobStatus_Starting;
try try
{ {
m_progress = 0;
m_status = JobStatus_Starting;
encode(); encode();
} }
catch(char *msg) catch(char *msg)
@ -110,6 +118,12 @@ void EncodeThread::run(void)
{ {
log(tr("EXCEPTION ERROR !!!")); log(tr("EXCEPTION ERROR !!!"));
} }
if(m_handle_jobObject)
{
CloseHandle(m_handle_jobObject);
m_handle_jobObject = NULL;
}
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -118,27 +132,35 @@ void EncodeThread::run(void)
void EncodeThread::encode(void) void EncodeThread::encode(void)
{ {
Sleep(500); QDateTime startTime = QDateTime::currentDateTime();
//Print some basic info //Print some basic info
log(tr("Job started at %1, %2.\n").arg(QDate::currentDate().toString(Qt::ISODate), QTime::currentTime().toString( Qt::ISODate))); log(tr("Job started at %1, %2.\n").arg(QDate::currentDate().toString(Qt::ISODate), QTime::currentTime().toString( Qt::ISODate)));
log(tr("Source file: %1").arg(m_sourceFileName)); log(tr("Source file: %1").arg(m_sourceFileName));
log(tr("Output file: %1").arg(m_outputFileName)); log(tr("Output file: %1").arg(m_outputFileName));
log(tr("\n[Encoder Options]"));
log(tr("RC Mode: %1").arg(OptionsModel::rcMode2String(m_options->rcMode())));
log(tr("Preset: %1").arg(m_options->preset()));
log(tr("Tuning: %1").arg(m_options->tune()));
log(tr("Profile: %1").arg(m_options->profile()));
log(tr("Custom: %1").arg(m_options->custom().isEmpty() ? tr("(None)") : m_options->custom()));
//Detect source info //Print encoder settings
log(tr("\n[Input Properties]")); log(tr("\n--- SETTINGS ---\n"));
log(tr("Not implemented yet, sorry ;-)\n")); log(tr("RC Mode: %1").arg(OptionsModel::rcMode2String(m_options->rcMode())));
log(tr("Preset: %1").arg(m_options->preset()));
log(tr("Tuning: %1").arg(m_options->tune()));
log(tr("Profile: %1").arg(m_options->profile()));
log(tr("Custom: %1").arg(m_options->custom().isEmpty() ? tr("(None)") : m_options->custom()));
bool ok = false; bool ok = false;
unsigned int frames = 0;
//Detect source info
bool usePipe = m_x64 && (QFileInfo(m_sourceFileName).suffix().compare("avs", Qt::CaseInsensitive) == 0);
if(usePipe)
{
log(tr("\n--- AVS INFO ---\n"));
ok = checkProperties(frames);
CHECK_STATUS(m_abort, ok);
}
//Checking version //Checking version
log(tr("--- VERSION ---\n")); log(tr("\n--- X264 VERSION ---\n"));
unsigned int revision; unsigned int revision;
ok = ((revision = checkVersion(m_x64)) != UINT_MAX); ok = ((revision = checkVersion(m_x64)) != UINT_MAX);
CHECK_STATUS(m_abort, ok); CHECK_STATUS(m_abort, ok);
@ -173,38 +195,50 @@ void EncodeThread::encode(void)
} }
log(tr("\n--- PASS 1 ---\n")); log(tr("\n--- PASS 1 ---\n"));
ok = runEncodingPass(m_x64, 1, passLogFile); ok = runEncodingPass(m_x64, usePipe, frames, 1, passLogFile);
CHECK_STATUS(m_abort, ok); CHECK_STATUS(m_abort, ok);
log(tr("\n--- PASS 2 ---\n")); log(tr("\n--- PASS 2 ---\n"));
ok = runEncodingPass(m_x64,2, passLogFile); ok = runEncodingPass(m_x64, usePipe, frames, 2, passLogFile);
CHECK_STATUS(m_abort, ok); CHECK_STATUS(m_abort, ok);
} }
else else
{ {
log(tr("\n--- ENCODING ---\n")); log(tr("\n--- ENCODING ---\n"));
ok = runEncodingPass(m_x64); ok = runEncodingPass(m_x64, usePipe, frames);
CHECK_STATUS(m_abort, ok); CHECK_STATUS(m_abort, ok);
} }
log(tr("\n--- DONE ---\n")); log(tr("\n--- DONE ---\n"));
log(tr("Job finished at %1, %2.\n").arg(QDate::currentDate().toString(Qt::ISODate), QTime::currentTime().toString( Qt::ISODate))); int timePassed = startTime.secsTo(QDateTime::currentDateTime());
log(tr("Job finished at %1, %2. Process took %3 minutes, %4 seconds.").arg(QDate::currentDate().toString(Qt::ISODate), QTime::currentTime().toString( Qt::ISODate), QString::number(timePassed / 60), QString::number(timePassed % 60)));
setStatus(JobStatus_Completed); setStatus(JobStatus_Completed);
} }
bool EncodeThread::runEncodingPass(bool x64, int pass, const QString &passLogFile) bool EncodeThread::runEncodingPass(bool x64, bool usePipe, unsigned int frames, int pass, const QString &passLogFile)
{ {
QProcess process; QProcess process;
QStringList cmdLine = buildCommandLine(pass, passLogFile); QStringList cmdLine;
if(usePipe)
{
cmdLine << QString("%1/avs2yuv.exe").arg(m_binDir);
cmdLine << QDir::toNativeSeparators(m_sourceFileName);
cmdLine << "-" << ":";
cmdLine << QString("%1/%2.exe").arg(m_binDir,(x64 ? "x264_x64" : "x264"));
}
cmdLine << buildCommandLine(usePipe, frames, pass, passLogFile);
log("Creating process:"); log("Creating process:");
if(!startProcess(process, QString("%1/%2.exe").arg(m_binDir, x64 ? "x264_x64" : "x264"), cmdLine)) if(!startProcess(process, QString("%1/%2.exe").arg(m_binDir, usePipe ? "pipebuf" : (x64 ? "x264_x64" : "x264")), cmdLine))
{ {
return false;; return false;;
} }
QRegExp regExpIndexing("indexing.+\\[(\\d+)\\.\\d+%\\]"); QRegExp regExpIndexing("indexing.+\\[(\\d+)\\.\\d+%\\]");
QRegExp regExpProgress("\\[(\\d+)\\.\\d+%\\].+frames"); QRegExp regExpProgress("\\[(\\d+)\\.\\d+%\\].+frames");
QRegExp regExpFrameCnt("^(\\d+) frames:");
bool bTimeout = false; bool bTimeout = false;
bool bAborted = false; bool bAborted = false;
@ -251,6 +285,11 @@ bool EncodeThread::runEncodingPass(bool x64, int pass, const QString &passLogFil
setDetails(text.mid(offset).trimmed()); setDetails(text.mid(offset).trimmed());
if(ok) setProgress(progress); if(ok) setProgress(progress);
} }
else if((offset = regExpFrameCnt.lastIndexIn(text)) >= 0)
{
setStatus((pass == 2) ? JobStatus_Running_Pass2 : ((pass == 1) ? JobStatus_Running_Pass1 : JobStatus_Running));
setDetails(text.mid(offset).trimmed());
}
else if(!text.isEmpty()) else if(!text.isEmpty())
{ {
log(text); log(text);
@ -268,6 +307,10 @@ bool EncodeThread::runEncodingPass(bool x64, int pass, const QString &passLogFil
if(bTimeout || bAborted || process.exitCode() != EXIT_SUCCESS) if(bTimeout || bAborted || process.exitCode() != EXIT_SUCCESS)
{ {
if(!(bTimeout || bAborted))
{
log(tr("\nPROCESS EXITED WITH ERROR CODE: %1").arg(QString::number(process.exitCode())));
}
return false; return false;
} }
@ -276,7 +319,7 @@ bool EncodeThread::runEncodingPass(bool x64, int pass, const QString &passLogFil
return true; return true;
} }
QStringList EncodeThread::buildCommandLine(int pass, const QString &passLogFile) QStringList EncodeThread::buildCommandLine(bool usePipe, unsigned int frames, int pass, const QString &passLogFile)
{ {
QStringList cmdLine; QStringList cmdLine;
@ -317,7 +360,17 @@ QStringList EncodeThread::buildCommandLine(int pass, const QString &passLogFile)
} }
cmdLine << "--output" << QDir::toNativeSeparators(m_outputFileName); cmdLine << "--output" << QDir::toNativeSeparators(m_outputFileName);
cmdLine << m_sourceFileName;
if(usePipe)
{
cmdLine << "--frames" << QString::number(frames);
cmdLine << "--demuxer" << "y4m";
cmdLine << "--stdin" << "y4m" << "-";
}
else
{
cmdLine << QDir::toNativeSeparators(m_sourceFileName);
}
return cmdLine; return cmdLine;
} }
@ -392,6 +445,10 @@ unsigned int EncodeThread::checkVersion(bool x64)
if(bTimeout || bAborted || process.exitCode() != EXIT_SUCCESS) if(bTimeout || bAborted || process.exitCode() != EXIT_SUCCESS)
{ {
if(!(bTimeout || bAborted))
{
log(tr("\nPROCESS EXITED WITH ERROR CODE: %1").arg(QString::number(process.exitCode())));
}
return UINT_MAX; return UINT_MAX;
} }
@ -404,6 +461,138 @@ unsigned int EncodeThread::checkVersion(bool x64)
return (coreVers * REV_MULT) + revision; return (coreVers * REV_MULT) + revision;
} }
bool EncodeThread::checkProperties(unsigned int &frames)
{
QProcess process;
QStringList cmdLine = QStringList() << "-frames" << "1";
cmdLine << QDir::toNativeSeparators(m_sourceFileName) << "NUL";
log("Creating process:");
if(!startProcess(process, QString("%1/avs2yuv.exe").arg(m_binDir), cmdLine))
{
return false;;
}
QRegExp regExpInt(": (\\d+)x(\\d+), (\\d+) fps, (\\d+) frames");
QRegExp regExpFrc(": (\\d+)x(\\d+), (\\d+)/(\\d+) fps, (\\d+) frames");
bool bTimeout = false;
bool bAborted = false;
frames = 0;
unsigned int fpsNom = 0;
unsigned int fpsDen = 0;
unsigned int fSizeW = 0;
unsigned int fSizeH = 0;
while(process.state() != QProcess::NotRunning)
{
if(m_abort)
{
process.kill();
bAborted = true;
break;
}
if(!process.waitForReadyRead(m_processTimeoutInterval))
{
if(process.state() == QProcess::Running)
{
process.kill();
qWarning("x264 process timed out <-- killing!");
log("\nPROCESS TIMEOUT !!!");
bTimeout = true;
break;
}
}
while(process.bytesAvailable() > 0)
{
QList<QByteArray> lines = process.readLine().split('\r');
while(!lines.isEmpty())
{
QString text = QString::fromUtf8(lines.takeFirst().constData()).simplified();
int offset = -1;
if((offset = regExpInt.lastIndexIn(text)) >= 0)
{
bool ok1 = false, ok2 = false;
bool ok3 = false, ok4 = false;
unsigned int temp1 = regExpInt.cap(1).toUInt(&ok1);
unsigned int temp2 = regExpInt.cap(2).toUInt(&ok2);
unsigned int temp3 = regExpInt.cap(3).toUInt(&ok3);
unsigned int temp4 = regExpInt.cap(4).toUInt(&ok4);
if(ok1) fSizeW = temp1;
if(ok2) fSizeH = temp2;
if(ok3) fpsNom = temp3;
if(ok4) frames = temp4;
}
else if((offset = regExpFrc.lastIndexIn(text)) >= 0)
{
bool ok1 = false, ok2 = false;
bool ok3 = false, ok4 = false, ok5 = false;
unsigned int temp1 = regExpFrc.cap(1).toUInt(&ok1);
unsigned int temp2 = regExpFrc.cap(2).toUInt(&ok2);
unsigned int temp3 = regExpFrc.cap(3).toUInt(&ok3);
unsigned int temp4 = regExpFrc.cap(4).toUInt(&ok4);
unsigned int temp5 = regExpFrc.cap(5).toUInt(&ok5);
if(ok1) fSizeW = temp1;
if(ok2) fSizeH = temp2;
if(ok3) fpsNom = temp3;
if(ok4) fpsDen = temp4;
if(ok5) frames = temp5;
}
if(!text.isEmpty())
{
log(text);
}
}
}
}
process.waitForFinished();
if(process.state() != QProcess::NotRunning)
{
process.kill();
process.waitForFinished(-1);
}
if(bTimeout || bAborted || process.exitCode() != EXIT_SUCCESS)
{
if(!(bTimeout || bAborted))
{
log(tr("\nPROCESS EXITED WITH ERROR CODE: %1").arg(QString::number(process.exitCode())));
}
return false;
}
if(frames == 0)
{
log(tr("\nFAILED TO DETERMINE AVS PROPERTIES !!!"));
return false;
}
log("");
if((fSizeW > 0) && (fSizeH > 0))
{
log(tr("Resolution: %1x%2").arg(QString::number(fSizeW), QString::number(fSizeH)));
}
if((fpsNom > 0) && (fpsDen > 0))
{
log(tr("Frame Rate: %1/%2").arg(QString::number(fpsNom), QString::number(fpsDen)));
}
if((fpsNom > 0) && (fpsDen == 0))
{
log(tr("Frame Rate: %1").arg(QString::number(fpsNom)));
}
if(frames > 0)
{
log(tr("No. Frames: %1").arg(QString::number(frames)));
}
return true;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Misc functions // Misc functions
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -446,10 +635,39 @@ void EncodeThread::setDetails(const QString &text)
bool EncodeThread::startProcess(QProcess &process, const QString &program, const QStringList &args) bool EncodeThread::startProcess(QProcess &process, const QString &program, const QStringList &args)
{ {
static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL; static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL;
static CreateJobObjectFun CreateJobObjectPtr = NULL;
static SetInformationJobObjectFun SetInformationJobObjectPtr = NULL;
QMutexLocker lock(&m_mutex_startProcess); QMutexLocker lock(&m_mutex_startProcess);
log(commandline2string(program, args) + "\n"); log(commandline2string(program, args) + "\n");
//Create a new job object, if not done yet
if(!m_handle_jobObject)
{
if(!CreateJobObjectPtr || !SetInformationJobObjectPtr)
{
QLibrary Kernel32Lib("kernel32.dll");
CreateJobObjectPtr = (CreateJobObjectFun) Kernel32Lib.resolve("CreateJobObjectA");
SetInformationJobObjectPtr = (SetInformationJobObjectFun) Kernel32Lib.resolve("SetInformationJobObject");
}
if(CreateJobObjectPtr && SetInformationJobObjectPtr)
{
m_handle_jobObject = CreateJobObjectPtr(NULL, NULL);
if(m_handle_jobObject == INVALID_HANDLE_VALUE)
{
m_handle_jobObject = NULL;
}
if(m_handle_jobObject)
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
SetInformationJobObjectPtr(m_handle_jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
}
}
}
//Initialize AssignProcessToJobObject function
if(!AssignProcessToJobObjectPtr) if(!AssignProcessToJobObjectPtr)
{ {
QLibrary Kernel32Lib("kernel32.dll"); QLibrary Kernel32Lib("kernel32.dll");
@ -462,7 +680,6 @@ bool EncodeThread::startProcess(QProcess &process, const QString &program, const
if(process.waitForStarted()) if(process.waitForStarted())
{ {
if(AssignProcessToJobObjectPtr) if(AssignProcessToJobObjectPtr)
{ {
AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess); AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess);

View File

@ -59,8 +59,6 @@ public:
protected: protected:
static QMutex m_mutex_startProcess; static QMutex m_mutex_startProcess;
static void *m_handle_jobObject;
static const int m_processTimeoutInterval = 60000; static const int m_processTimeoutInterval = 60000;
//Constants //Constants
@ -74,6 +72,9 @@ protected:
//Flags //Flags
volatile bool m_abort; volatile bool m_abort;
//Job handle
void *m_handle_jobObject;
//Internal status values //Internal status values
JobStatus m_status; JobStatus m_status;
unsigned int m_progress; unsigned int m_progress;
@ -83,9 +84,10 @@ protected:
//Encode functions //Encode functions
void encode(void); void encode(void);
bool runEncodingPass(bool x64, int pass = 0, const QString &passLogFile = QString()); bool runEncodingPass(bool x64, bool usePipe, unsigned int frames, int pass = 0, const QString &passLogFile = QString());
QStringList buildCommandLine(int pass = 0, const QString &passLogFile = QString()); QStringList buildCommandLine(bool usePipe, unsigned int frames, int pass = 0, const QString &passLogFile = QString());
unsigned int checkVersion(bool x64); unsigned int checkVersion(bool x64);
bool checkProperties(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

@ -107,6 +107,9 @@ AddJobDialog::AddJobDialog(QWidget *parent, OptionsModel *options)
cbxCustomParams->setValidator(new StringValidator()); cbxCustomParams->setValidator(new StringValidator());
cbxCustomParams->addItem("--bluray-compat --vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 25 --open-gop --slices 4"); cbxCustomParams->addItem("--bluray-compat --vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 25 --open-gop --slices 4");
cbxCustomParams->clearEditText(); cbxCustomParams->clearEditText();
//Install event filter
labelHelpScreen->installEventFilter(this);
} }
AddJobDialog::~AddJobDialog(void) AddJobDialog::~AddJobDialog(void)
@ -124,6 +127,16 @@ void AddJobDialog::showEvent(QShowEvent *event)
modeIndexChanged(cbxRateControlMode->currentIndex()); modeIndexChanged(cbxRateControlMode->currentIndex());
} }
bool AddJobDialog::eventFilter(QObject *o, QEvent *e)
{
if((o == labelHelpScreen) && (e->type() == QEvent::MouseButtonPress))
{
QMessageBox::information(this, tr("Not yet"), tr("Not implemented yet. Please use the '?' menu for now!"));
return true;
}
return false;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Slots // Slots
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -262,7 +275,6 @@ void AddJobDialog::restoreOptions(OptionsModel *options)
void AddJobDialog::saveOptions(OptionsModel *options) void AddJobDialog::saveOptions(OptionsModel *options)
{ {
qWarning("Current index: %d", cbxRateControlMode->currentIndex());
options->setRCMode(static_cast<OptionsModel::RCMode>(cbxRateControlMode->currentIndex())); options->setRCMode(static_cast<OptionsModel::RCMode>(cbxRateControlMode->currentIndex()));
options->setQuantizer(spinQuantizer->value()); options->setQuantizer(spinQuantizer->value());
options->setBitrate(spinBitrate->value()); options->setBitrate(spinBitrate->value());

View File

@ -45,7 +45,8 @@ public:
protected: protected:
OptionsModel *m_options; OptionsModel *m_options;
virtual void AddJobDialog::showEvent(QShowEvent *event); virtual void showEvent(QShowEvent *event);
virtual bool eventFilter(QObject *o, QEvent *e);
private slots: private slots:
void modeIndexChanged(int index); void modeIndexChanged(int index);

View File

@ -39,6 +39,9 @@ const char *home_url = "http://mulder.brhack.net/";
#define PRE_RELEASE (1) #define PRE_RELEASE (1)
#define SET_FONT_BOLD(WIDGET,BOLD) { QFont _font = WIDGET->font(); _font.setBold(BOLD); WIDGET->setFont(_font); }
#define SET_TEXT_COLOR(WIDGET,COLOR) { QPalette _palette = WIDGET->palette(); _palette.setColor(QPalette::WindowText, (COLOR)); _palette.setColor(QPalette::Text, (COLOR)); WIDGET->setPalette(_palette); }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Constructor & Destructor // Constructor & Destructor
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -59,7 +62,7 @@ MainWindow::MainWindow(bool x64supported)
//Freeze minimum size //Freeze minimum size
setMinimumSize(size()); setMinimumSize(size());
splitter->setSizes(QList<int>() << 200 << SHRT_MAX); splitter->setSizes(QList<int>() << 16 << 196);
//Update title //Update title
labelBuildDate->setText(tr("Built on %1 at %2").arg(x264_version_date().toString(Qt::ISODate), QString::fromLatin1(x264_version_time()))); labelBuildDate->setText(tr("Built on %1 at %2").arg(x264_version_date().toString(Qt::ISODate), QString::fromLatin1(x264_version_time())));
@ -81,6 +84,12 @@ MainWindow::MainWindow(bool x64supported)
jobsView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); jobsView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
connect(jobsView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(jobSelected(QModelIndex, QModelIndex))); connect(jobsView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(jobSelected(QModelIndex, QModelIndex)));
//Create context menu
QAction *actionClipboard = new QAction(QIcon(":/buttons/page_paste.png"), tr("Copy to Clipboard"), logView);
logView->addAction(actionClipboard);
connect(actionClipboard, SIGNAL(triggered(bool)), this, SLOT(copyLogToClipboard(bool)));
jobsView->addActions(menuJob->actions());
//Enable buttons //Enable buttons
connect(buttonAddJob, SIGNAL(clicked()), this, SLOT(addButtonPressed())); connect(buttonAddJob, SIGNAL(clicked()), this, SLOT(addButtonPressed()));
connect(buttonStartJob, SIGNAL(clicked()), this, SLOT(startButtonPressed())); connect(buttonStartJob, SIGNAL(clicked()), this, SLOT(startButtonPressed()));
@ -95,6 +104,18 @@ MainWindow::MainWindow(bool x64supported)
connect(actionWebWiki, SIGNAL(triggered()), this, SLOT(showWebLink())); connect(actionWebWiki, SIGNAL(triggered()), this, SLOT(showWebLink()));
connect(actionWebBluRay, SIGNAL(triggered()), this, SLOT(showWebLink())); connect(actionWebBluRay, SIGNAL(triggered()), this, SLOT(showWebLink()));
//Create floating label
m_label = new QLabel(jobsView);
m_label->setText(tr("No job created yet. Please click the 'Add New Job' button!"));
m_label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
SET_TEXT_COLOR(m_label, Qt::darkGray);
SET_FONT_BOLD(m_label, true);
m_label->setVisible(true);
m_label->setContextMenuPolicy(Qt::ActionsContextMenu);
m_label->addActions(jobsView->actions());
connect(splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(updateLabel()));
updateLabel();
//Create options object //Create options object
m_options = new OptionsModel(); m_options = new OptionsModel();
} }
@ -103,6 +124,7 @@ MainWindow::~MainWindow(void)
{ {
X264_DELETE(m_jobList); X264_DELETE(m_jobList);
X264_DELETE(m_options); X264_DELETE(m_options);
X264_DELETE(m_label);
while(!m_toolsList.isEmpty()) while(!m_toolsList.isEmpty())
{ {
@ -123,7 +145,6 @@ void MainWindow::addButtonPressed(void)
if(result == QDialog::Accepted) if(result == QDialog::Accepted)
{ {
qDebug("RC Mode: %d", m_options->rcMode());
EncodeThread *thrd = new EncodeThread EncodeThread *thrd = new EncodeThread
( (
@ -142,6 +163,8 @@ void MainWindow::addButtonPressed(void)
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
m_jobList->startJob(newIndex); m_jobList->startJob(newIndex);
} }
m_label->setVisible(false);
} }
X264_DELETE(addDialog); X264_DELETE(addDialog);
@ -173,6 +196,8 @@ void MainWindow::jobSelected(const QModelIndex & current, const QModelIndex & pr
progressBar->setValue(m_jobList->getJobProgress(current)); progressBar->setValue(m_jobList->getJobProgress(current));
editDetails->setText(m_jobList->data(m_jobList->index(current.row(), 3, QModelIndex()), Qt::DisplayRole).toString()); editDetails->setText(m_jobList->data(m_jobList->index(current.row(), 3, QModelIndex()), Qt::DisplayRole).toString());
updateButtons(m_jobList->getJobStatus(current)); updateButtons(m_jobList->getJobStatus(current));
progressBar->repaint();
} }
void MainWindow::jobChangedData(const QModelIndex &topLeft, const QModelIndex &bottomRight) void MainWindow::jobChangedData(const QModelIndex &topLeft, const QModelIndex &bottomRight)
@ -281,6 +306,8 @@ void MainWindow::init(void)
static const char *binFiles = "x264.exe:x264_x64.exe:avs2yuv.exe:pipebuf.exe"; static const char *binFiles = "x264.exe:x264_x64.exe:avs2yuv.exe:pipebuf.exe";
QStringList binaries = QString::fromLatin1(binFiles).split(":", QString::SkipEmptyParts); QStringList binaries = QString::fromLatin1(binFiles).split(":", QString::SkipEmptyParts);
updateLabel();
//Check all binaries //Check all binaries
while(!binaries.isEmpty()) while(!binaries.isEmpty())
{ {
@ -322,6 +349,22 @@ void MainWindow::init(void)
} }
} }
void MainWindow::updateLabel(void)
{
m_label->setGeometry(0, 0, jobsView->width(), jobsView->height());
}
void MainWindow::copyLogToClipboard(bool checked)
{
qDebug("copyLogToClipboard");
if(LogFileModel *log = dynamic_cast<LogFileModel*>(logView->model()))
{
log->copyToClipboard();
MessageBeep(MB_ICONINFORMATION);
}
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Event functions // Event functions
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -349,6 +392,12 @@ void MainWindow::closeEvent(QCloseEvent *e)
QMainWindow::closeEvent(e); QMainWindow::closeEvent(e);
} }
void MainWindow::resizeEvent(QResizeEvent *e)
{
QMainWindow::resizeEvent(e);
updateLabel();
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Private functions // Private functions
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -376,4 +425,7 @@ void MainWindow::updateButtons(EncodeThread::JobStatus status)
buttonStartJob->setEnabled(status == EncodeThread::JobStatus_Enqueued); buttonStartJob->setEnabled(status == EncodeThread::JobStatus_Enqueued);
buttonAbortJob->setEnabled(status == EncodeThread::JobStatus_Indexing || status == EncodeThread::JobStatus_Running || buttonAbortJob->setEnabled(status == EncodeThread::JobStatus_Indexing || status == EncodeThread::JobStatus_Running ||
status == EncodeThread::JobStatus_Running_Pass1 || status == EncodeThread::JobStatus_Running_Pass2 ); status == EncodeThread::JobStatus_Running_Pass1 || status == EncodeThread::JobStatus_Running_Pass2 );
actionJob_Start->setEnabled(buttonStartJob->isEnabled());
actionJob_Abort->setEnabled(buttonAbortJob->isEnabled());
} }

View File

@ -39,9 +39,11 @@ public:
protected: protected:
virtual void closeEvent(QCloseEvent *e); virtual void closeEvent(QCloseEvent *e);
virtual void showEvent(QShowEvent *e); virtual void showEvent(QShowEvent *e);
virtual void resizeEvent(QResizeEvent *e);
private: private:
bool m_firstShow; bool m_firstShow;
QLabel *m_label;
JobListModel *m_jobList; JobListModel *m_jobList;
OptionsModel *m_options; OptionsModel *m_options;
@ -55,13 +57,15 @@ private:
private slots: private slots:
void addButtonPressed(void); void addButtonPressed(void);
void startButtonPressed(void);
void abortButtonPressed(void); void abortButtonPressed(void);
void copyLogToClipboard(bool checked);
void init(void); void init(void);
void jobSelected(const QModelIndex & current, const QModelIndex & previous); void jobSelected(const QModelIndex & current, const QModelIndex & previous);
void jobChangedData(const QModelIndex &top, const QModelIndex &bottom); void jobChangedData(const QModelIndex &top, const QModelIndex &bottom);
void jobLogExtended(const QModelIndex & parent, int start, int end); void jobLogExtended(const QModelIndex & parent, int start, int end);
void launchNextJob(void);
void showAbout(void); void showAbout(void);
void showWebLink(void); void showWebLink(void);
void launchNextJob(void); void startButtonPressed(void);
void updateLabel(void);
}; };