Implemented support for using 32-Bit Avisynth with 64-Bit x264.
This commit is contained in:
parent
a30b5b7300
commit
a3ff0fda24
@ -233,7 +233,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Quantiter/CRF:</string>
|
||||
<string>Quantizer/CRF:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -606,7 +606,7 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<widget class="QLabel" name="labelHelpScreen">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
|
@ -30,6 +30,9 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QTableView" name="jobsView">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ActionsContextMenu</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -96,6 +99,9 @@
|
||||
<family>Lucida Console</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ActionsContextMenu</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
@ -296,7 +302,17 @@
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionAbout"/>
|
||||
</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="menuJob"/>
|
||||
<addaction name="menu"/>
|
||||
</widget>
|
||||
<action name="actionExit">
|
||||
@ -371,6 +387,39 @@
|
||||
<string>x264 BluRay Authoring</string>
|
||||
</property>
|
||||
</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>
|
||||
<tabstops>
|
||||
<tabstop>buttonAddJob</tabstop>
|
||||
@ -400,5 +449,53 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</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>
|
||||
</ui>
|
||||
|
BIN
res/buttons/page_paste.png
Normal file
BIN
res/buttons/page_paste.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 703 B |
@ -14,6 +14,7 @@
|
||||
<file>buttons/find.png</file>
|
||||
<file>buttons/information.png</file>
|
||||
<file>buttons/lightning.png</file>
|
||||
<file>buttons/page_paste.png</file>
|
||||
<file>buttons/play.png</file>
|
||||
<file>buttons/play_big.png</file>
|
||||
<file>buttons/world_link.png</file>
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "thread_encode.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
|
||||
LogFileModel::LogFileModel(void)
|
||||
{
|
||||
@ -76,6 +78,16 @@ QVariant LogFileModel::data(const QModelIndex &index, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Public API
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LogFileModel::copyToClipboard(void)
|
||||
{
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(m_lines.join("\r\n"));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Slots
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -43,6 +43,8 @@ public:
|
||||
virtual QModelIndex parent (const QModelIndex &index) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||
|
||||
void copyToClipboard(void);
|
||||
|
||||
protected:
|
||||
QStringList m_lines;
|
||||
bool m_firstLine;
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <QDate>
|
||||
#include <QTime>
|
||||
#include <QDateTime>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
@ -44,7 +45,6 @@ typedef BOOL (WINAPI *AssignProcessToJobObjectFun)(__in HANDLE hJob, __in HANDLE
|
||||
* Static vars
|
||||
*/
|
||||
QMutex EncodeThread::m_mutex_startProcess;
|
||||
HANDLE EncodeThread::m_handle_jobObject = NULL;
|
||||
|
||||
/*
|
||||
* Macros
|
||||
@ -80,7 +80,8 @@ EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputF
|
||||
m_outputFileName(outputFileName),
|
||||
m_options(new OptionsModel(*options)),
|
||||
m_binDir(binDir),
|
||||
m_x64(x64)
|
||||
m_x64(x64),
|
||||
m_handle_jobObject(NULL)
|
||||
{
|
||||
m_abort = false;
|
||||
}
|
||||
@ -88,6 +89,12 @@ EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputF
|
||||
EncodeThread::~EncodeThread(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_progress = 0;
|
||||
m_status = JobStatus_Starting;
|
||||
|
||||
try
|
||||
{
|
||||
m_progress = 0;
|
||||
m_status = JobStatus_Starting;
|
||||
encode();
|
||||
}
|
||||
catch(char *msg)
|
||||
@ -110,6 +118,12 @@ void EncodeThread::run(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Sleep(500);
|
||||
|
||||
QDateTime startTime = QDateTime::currentDateTime();
|
||||
|
||||
//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("Source file: %1").arg(m_sourceFileName));
|
||||
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
|
||||
log(tr("\n[Input Properties]"));
|
||||
log(tr("Not implemented yet, sorry ;-)\n"));
|
||||
|
||||
//Print encoder settings
|
||||
log(tr("\n--- SETTINGS ---\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;
|
||||
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
|
||||
log(tr("--- VERSION ---\n"));
|
||||
log(tr("\n--- X264 VERSION ---\n"));
|
||||
unsigned int revision;
|
||||
ok = ((revision = checkVersion(m_x64)) != UINT_MAX);
|
||||
CHECK_STATUS(m_abort, ok);
|
||||
@ -156,7 +178,7 @@ void EncodeThread::encode(void)
|
||||
log(tr("\nWARNING: Your revision of x264 uses an unsupported core (API) version, take care!"));
|
||||
log(tr("This application works best with x264 core (API) version %2.").arg(QString::number(VER_X264_CURRENT_API)));
|
||||
}
|
||||
|
||||
|
||||
//Run encoding passes
|
||||
if(m_options->rcMode() == OptionsModel::RCMode_2Pass)
|
||||
{
|
||||
@ -173,38 +195,50 @@ void EncodeThread::encode(void)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
log(tr("\n--- ENCODING ---\n"));
|
||||
ok = runEncodingPass(m_x64);
|
||||
ok = runEncodingPass(m_x64, usePipe, frames);
|
||||
CHECK_STATUS(m_abort, ok);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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:");
|
||||
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;;
|
||||
}
|
||||
|
||||
QRegExp regExpIndexing("indexing.+\\[(\\d+)\\.\\d+%\\]");
|
||||
QRegExp regExpProgress("\\[(\\d+)\\.\\d+%\\].+frames");
|
||||
QRegExp regExpFrameCnt("^(\\d+) frames:");
|
||||
|
||||
bool bTimeout = false;
|
||||
bool bAborted = false;
|
||||
@ -251,6 +285,11 @@ bool EncodeThread::runEncodingPass(bool x64, int pass, const QString &passLogFil
|
||||
setDetails(text.mid(offset).trimmed());
|
||||
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())
|
||||
{
|
||||
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))
|
||||
{
|
||||
log(tr("\nPROCESS EXITED WITH ERROR CODE: %1").arg(QString::number(process.exitCode())));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -276,7 +319,7 @@ bool EncodeThread::runEncodingPass(bool x64, int pass, const QString &passLogFil
|
||||
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;
|
||||
|
||||
@ -317,7 +360,17 @@ QStringList EncodeThread::buildCommandLine(int pass, const QString &passLogFile)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -392,6 +445,10 @@ unsigned int EncodeThread::checkVersion(bool x64)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -404,6 +461,138 @@ unsigned int EncodeThread::checkVersion(bool x64)
|
||||
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
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -446,10 +635,39 @@ void EncodeThread::setDetails(const QString &text)
|
||||
bool EncodeThread::startProcess(QProcess &process, const QString &program, const QStringList &args)
|
||||
{
|
||||
static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL;
|
||||
static CreateJobObjectFun CreateJobObjectPtr = NULL;
|
||||
static SetInformationJobObjectFun SetInformationJobObjectPtr = NULL;
|
||||
|
||||
QMutexLocker lock(&m_mutex_startProcess);
|
||||
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)
|
||||
{
|
||||
QLibrary Kernel32Lib("kernel32.dll");
|
||||
@ -462,7 +680,6 @@ bool EncodeThread::startProcess(QProcess &process, const QString &program, const
|
||||
|
||||
if(process.waitForStarted())
|
||||
{
|
||||
|
||||
if(AssignProcessToJobObjectPtr)
|
||||
{
|
||||
AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess);
|
||||
|
@ -59,8 +59,6 @@ public:
|
||||
|
||||
protected:
|
||||
static QMutex m_mutex_startProcess;
|
||||
static void *m_handle_jobObject;
|
||||
|
||||
static const int m_processTimeoutInterval = 60000;
|
||||
|
||||
//Constants
|
||||
@ -74,6 +72,9 @@ protected:
|
||||
//Flags
|
||||
volatile bool m_abort;
|
||||
|
||||
//Job handle
|
||||
void *m_handle_jobObject;
|
||||
|
||||
//Internal status values
|
||||
JobStatus m_status;
|
||||
unsigned int m_progress;
|
||||
@ -83,9 +84,10 @@ protected:
|
||||
|
||||
//Encode functions
|
||||
void encode(void);
|
||||
bool runEncodingPass(bool x64, int pass = 0, const QString &passLogFile = QString());
|
||||
QStringList buildCommandLine(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(bool usePipe, unsigned int frames, int pass = 0, const QString &passLogFile = QString());
|
||||
unsigned int checkVersion(bool x64);
|
||||
bool checkProperties(unsigned int &frames);
|
||||
|
||||
//Auxiallary Stuff
|
||||
void log(const QString &text) { emit messageLogged(m_jobId, text); }
|
||||
|
@ -107,6 +107,9 @@ AddJobDialog::AddJobDialog(QWidget *parent, OptionsModel *options)
|
||||
cbxCustomParams->setValidator(new StringValidator());
|
||||
cbxCustomParams->addItem("--bluray-compat --vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 25 --open-gop --slices 4");
|
||||
cbxCustomParams->clearEditText();
|
||||
|
||||
//Install event filter
|
||||
labelHelpScreen->installEventFilter(this);
|
||||
}
|
||||
|
||||
AddJobDialog::~AddJobDialog(void)
|
||||
@ -124,6 +127,16 @@ void AddJobDialog::showEvent(QShowEvent *event)
|
||||
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
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -262,7 +275,6 @@ void AddJobDialog::restoreOptions(OptionsModel *options)
|
||||
|
||||
void AddJobDialog::saveOptions(OptionsModel *options)
|
||||
{
|
||||
qWarning("Current index: %d", cbxRateControlMode->currentIndex());
|
||||
options->setRCMode(static_cast<OptionsModel::RCMode>(cbxRateControlMode->currentIndex()));
|
||||
options->setQuantizer(spinQuantizer->value());
|
||||
options->setBitrate(spinBitrate->value());
|
||||
|
@ -45,7 +45,8 @@ public:
|
||||
protected:
|
||||
OptionsModel *m_options;
|
||||
|
||||
virtual void AddJobDialog::showEvent(QShowEvent *event);
|
||||
virtual void showEvent(QShowEvent *event);
|
||||
virtual bool eventFilter(QObject *o, QEvent *e);
|
||||
|
||||
private slots:
|
||||
void modeIndexChanged(int index);
|
||||
|
@ -39,6 +39,9 @@ const char *home_url = "http://mulder.brhack.net/";
|
||||
|
||||
#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
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -59,7 +62,7 @@ MainWindow::MainWindow(bool x64supported)
|
||||
|
||||
//Freeze minimum size
|
||||
setMinimumSize(size());
|
||||
splitter->setSizes(QList<int>() << 200 << SHRT_MAX);
|
||||
splitter->setSizes(QList<int>() << 16 << 196);
|
||||
|
||||
//Update title
|
||||
labelBuildDate->setText(tr("Built on %1 at %2").arg(x264_version_date().toString(Qt::ISODate), QString::fromLatin1(x264_version_time())));
|
||||
@ -70,7 +73,7 @@ MainWindow::MainWindow(bool x64supported)
|
||||
m_jobList = new JobListModel();
|
||||
connect(m_jobList, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(jobChangedData(QModelIndex, QModelIndex)));
|
||||
jobsView->setModel(m_jobList);
|
||||
|
||||
|
||||
//Setup view
|
||||
jobsView->horizontalHeader()->setSectionHidden(3, true);
|
||||
jobsView->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
|
||||
@ -81,6 +84,12 @@ MainWindow::MainWindow(bool x64supported)
|
||||
jobsView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
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
|
||||
connect(buttonAddJob, SIGNAL(clicked()), this, SLOT(addButtonPressed()));
|
||||
connect(buttonStartJob, SIGNAL(clicked()), this, SLOT(startButtonPressed()));
|
||||
@ -95,6 +104,18 @@ MainWindow::MainWindow(bool x64supported)
|
||||
connect(actionWebWiki, 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
|
||||
m_options = new OptionsModel();
|
||||
}
|
||||
@ -103,6 +124,7 @@ MainWindow::~MainWindow(void)
|
||||
{
|
||||
X264_DELETE(m_jobList);
|
||||
X264_DELETE(m_options);
|
||||
X264_DELETE(m_label);
|
||||
|
||||
while(!m_toolsList.isEmpty())
|
||||
{
|
||||
@ -123,7 +145,6 @@ void MainWindow::addButtonPressed(void)
|
||||
|
||||
if(result == QDialog::Accepted)
|
||||
{
|
||||
qDebug("RC Mode: %d", m_options->rcMode());
|
||||
|
||||
EncodeThread *thrd = new EncodeThread
|
||||
(
|
||||
@ -142,6 +163,8 @@ void MainWindow::addButtonPressed(void)
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
m_jobList->startJob(newIndex);
|
||||
}
|
||||
|
||||
m_label->setVisible(false);
|
||||
}
|
||||
|
||||
X264_DELETE(addDialog);
|
||||
@ -173,6 +196,8 @@ void MainWindow::jobSelected(const QModelIndex & current, const QModelIndex & pr
|
||||
progressBar->setValue(m_jobList->getJobProgress(current));
|
||||
editDetails->setText(m_jobList->data(m_jobList->index(current.row(), 3, QModelIndex()), Qt::DisplayRole).toString());
|
||||
updateButtons(m_jobList->getJobStatus(current));
|
||||
|
||||
progressBar->repaint();
|
||||
}
|
||||
|
||||
void MainWindow::jobChangedData(const QModelIndex &topLeft, const QModelIndex &bottomRight)
|
||||
@ -280,7 +305,9 @@ void MainWindow::init(void)
|
||||
{
|
||||
static const char *binFiles = "x264.exe:x264_x64.exe:avs2yuv.exe:pipebuf.exe";
|
||||
QStringList binaries = QString::fromLatin1(binFiles).split(":", QString::SkipEmptyParts);
|
||||
|
||||
|
||||
updateLabel();
|
||||
|
||||
//Check all binaries
|
||||
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
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -349,6 +392,12 @@ void MainWindow::closeEvent(QCloseEvent *e)
|
||||
QMainWindow::closeEvent(e);
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QMainWindow::resizeEvent(e);
|
||||
updateLabel();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -376,4 +425,7 @@ void MainWindow::updateButtons(EncodeThread::JobStatus status)
|
||||
buttonStartJob->setEnabled(status == EncodeThread::JobStatus_Enqueued);
|
||||
buttonAbortJob->setEnabled(status == EncodeThread::JobStatus_Indexing || status == EncodeThread::JobStatus_Running ||
|
||||
status == EncodeThread::JobStatus_Running_Pass1 || status == EncodeThread::JobStatus_Running_Pass2 );
|
||||
|
||||
actionJob_Start->setEnabled(buttonStartJob->isEnabled());
|
||||
actionJob_Abort->setEnabled(buttonAbortJob->isEnabled());
|
||||
}
|
||||
|
@ -39,9 +39,11 @@ public:
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *e);
|
||||
virtual void showEvent(QShowEvent *e);
|
||||
virtual void resizeEvent(QResizeEvent *e);
|
||||
|
||||
private:
|
||||
bool m_firstShow;
|
||||
QLabel *m_label;
|
||||
|
||||
JobListModel *m_jobList;
|
||||
OptionsModel *m_options;
|
||||
@ -55,13 +57,15 @@ private:
|
||||
|
||||
private slots:
|
||||
void addButtonPressed(void);
|
||||
void startButtonPressed(void);
|
||||
void abortButtonPressed(void);
|
||||
void copyLogToClipboard(bool checked);
|
||||
void init(void);
|
||||
void jobSelected(const QModelIndex & current, const QModelIndex & previous);
|
||||
void jobChangedData(const QModelIndex &top, const QModelIndex &bottom);
|
||||
void jobLogExtended(const QModelIndex & parent, int start, int end);
|
||||
void launchNextJob(void);
|
||||
void showAbout(void);
|
||||
void showWebLink(void);
|
||||
void launchNextJob(void);
|
||||
void startButtonPressed(void);
|
||||
void updateLabel(void);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user