Made the file size estimation less jumpy: Before the progress was rounded to a precision of 1.0 percent. This caused a "jump" of the estimated size each time the integral part of progress increased by one. Now the progress is rounded to a precision of 0.1 percent, which greatly reduces the effect. Furthermore, we apply a slight smoothing filter on the estimated values in order to make the output more "stable".

This commit is contained in:
LoRd_MuldeR 2014-05-14 17:17:40 +02:00
parent fff0cc76ef
commit 214cdc4e30
7 changed files with 51 additions and 38 deletions

View File

@ -96,13 +96,12 @@ bool AbstractEncoder::runEncodingPass(AbstractSource* pipedSource, const QString
QList<QRegExp*> patterns; QList<QRegExp*> patterns;
runEncodingPass_init(patterns); runEncodingPass_init(patterns);
double last_progress = 0.0;
double size_estimate = 0.0;
bool bTimeout = false; bool bTimeout = false;
bool bAborted = false; bool bAborted = false;
unsigned int last_progress = UINT_MAX;
unsigned int last_indexing = UINT_MAX;
qint64 size_estimate = 0I64;
//Main processing loop //Main processing loop
while(processEncode.state() != QProcess::NotRunning) while(processEncode.state() != QProcess::NotRunning)
{ {
@ -173,12 +172,12 @@ bool AbstractEncoder::runEncodingPass(AbstractSource* pipedSource, const QString
} }
//Process all output //Process all output
PROCESS_PENDING_LINES(processEncode, runEncodingPass_parseLine, patterns, pass); PROCESS_PENDING_LINES(processEncode, runEncodingPass_parseLine, patterns, pass, last_progress, size_estimate);
} }
if(!(bTimeout || bAborted)) if(!(bTimeout || bAborted))
{ {
PROCESS_PENDING_LINES(processEncode, runEncodingPass_parseLine, patterns, pass); PROCESS_PENDING_LINES(processEncode, runEncodingPass_parseLine, patterns, pass, last_progress, size_estimate);
} }
processEncode.waitForFinished(5000); processEncode.waitForFinished(5000);
@ -231,7 +230,6 @@ bool AbstractEncoder::runEncodingPass(AbstractSource* pipedSource, const QString
QFileInfo completedFileInfo(m_outputFile); QFileInfo completedFileInfo(m_outputFile);
const qint64 finalSize = (completedFileInfo.exists() && completedFileInfo.isFile()) ? completedFileInfo.size() : 0; const qint64 finalSize = (completedFileInfo.exists() && completedFileInfo.isFile()) ? completedFileInfo.size() : 0;
QLocale locale(QLocale::English);
log(tr("Final file size is %1 bytes.").arg(sizeToString(finalSize))); log(tr("Final file size is %1 bytes.").arg(sizeToString(finalSize)));
switch(pass) switch(pass)
@ -292,16 +290,19 @@ QStringList AbstractEncoder::splitParams(const QString &params, const QString &s
return list; return list;
} }
qint64 AbstractEncoder::estimateSize(const QString &fileName, const int &progress) double AbstractEncoder::estimateSize(const QString &fileName, const double &progress)
{ {
QFileInfo fileInfo(fileName); double estimatedSize = 0.0;
if((progress >= 3) && fileInfo.exists() && fileInfo.isFile()) if(progress >= 0.03)
{ {
qint64 currentSize = QFileInfo(fileName).size(); QFileInfo fileInfo(fileName);
qint64 estimatedSize = (currentSize * 100I64) / static_cast<qint64>(progress); if(fileInfo.exists() && fileInfo.isFile())
return estimatedSize; {
const qint64 currentSize = QFileInfo(fileName).size();
estimatedSize = static_cast<double>(currentSize) * (1.0 / qBound(0.0, progress, 1.0));
} }
return 0I64; }
return estimatedSize;
} }
QString AbstractEncoder::sizeToString(qint64 size) QString AbstractEncoder::sizeToString(qint64 size)

View File

@ -52,10 +52,10 @@ protected:
virtual void buildCommandLine(QStringList &cmdLine, const bool &usePipe, const unsigned int &frames, const QString &indexFile, const int &pass, const QString &passLogFile) = 0; virtual void buildCommandLine(QStringList &cmdLine, const bool &usePipe, const unsigned int &frames, const QString &indexFile, const int &pass, const QString &passLogFile) = 0;
virtual void runEncodingPass_init(QList<QRegExp*> &patterns) = 0; virtual void runEncodingPass_init(QList<QRegExp*> &patterns) = 0;
virtual void runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass) = 0; virtual void runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass, double &last_progress, double &size_estimate) = 0;
static QStringList splitParams(const QString &params, const QString &sourceFile, const QString &outputFile); static QStringList splitParams(const QString &params, const QString &sourceFile, const QString &outputFile);
static qint64 estimateSize(const QString &fileName, const int &progress); static double estimateSize(const QString &fileName, const double &progress);
static QString sizeToString(qint64 size); static QString sizeToString(qint64 size);
const QString &m_sourceFile; const QString &m_sourceFile;

View File

@ -59,15 +59,21 @@ while(0)
#define X264_UPDATE_PROGRESS(X) do \ #define X264_UPDATE_PROGRESS(X) do \
{ \ { \
bool ok = false; qint64 size_estimate = 0; \ bool ok[2] = { false, false }; \
unsigned int progress = (X)->cap(1).toUInt(&ok); \ unsigned int progressInt = (X)->cap(1).toUInt(&ok[0]); \
unsigned int progressFrc = (X)->cap(2).toUInt(&ok[1]); \
setStatus((pass == 2) ? JobStatus_Running_Pass2 : ((pass == 1) ? JobStatus_Running_Pass1 : JobStatus_Running)); \ setStatus((pass == 2) ? JobStatus_Running_Pass2 : ((pass == 1) ? JobStatus_Running_Pass1 : JobStatus_Running)); \
if(ok) \ if(ok[0] && ok[1]) \
{ \ { \
setProgress(progress); \ const double progress = (double(progressInt) / 100.0) + (double(progressFrc) / 1000.0); \
size_estimate = estimateSize(m_outputFile, progress); \ if(!qFuzzyCompare(progress, last_progress)) \
{ \
setProgress(floor(progress * 100.0)); \
size_estimate = qFuzzyIsNull(size_estimate) ? estimateSize(m_outputFile, progress) : ((0.667 * size_estimate) + (0.333 * estimateSize(m_outputFile, progress))); \
last_progress = progress; \
} \ } \
setDetails(tr("%1, est. file size %2").arg(line.mid(offset).trimmed(), sizeToString(size_estimate))); \ } \
setDetails(tr("%1, est. file size %2").arg(line.mid(offset).trimmed(), sizeToString(qRound64(size_estimate)))); \
} \ } \
while(0) while(0)
@ -362,7 +368,7 @@ void X264Encoder::runEncodingPass_init(QList<QRegExp*> &patterns)
patterns << new QRegExp("\\[\\s*(\\d+)\\.(\\d+)%\\]\\s+(\\d+)/(\\d+)\\s(\\d+).(\\d+)\\s(\\d+).(\\d+)\\s+(\\d+):(\\d+):(\\d+)\\s+(\\d+):(\\d+):(\\d+)"); //regExpModified patterns << new QRegExp("\\[\\s*(\\d+)\\.(\\d+)%\\]\\s+(\\d+)/(\\d+)\\s(\\d+).(\\d+)\\s(\\d+).(\\d+)\\s+(\\d+):(\\d+):(\\d+)\\s+(\\d+):(\\d+):(\\d+)"); //regExpModified
} }
void X264Encoder::runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass) void X264Encoder::runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass, double &last_progress, double &size_estimate)
{ {
int offset = -1; int offset = -1;
if((offset = patterns[0]->lastIndexIn(line)) >= 0) if((offset = patterns[0]->lastIndexIn(line)) >= 0)

View File

@ -44,7 +44,7 @@ protected:
virtual void checkVersion_parseLine(const QString &line, QList<QRegExp*> &patterns, unsigned int &core, unsigned int &build, bool &modified); virtual void checkVersion_parseLine(const QString &line, QList<QRegExp*> &patterns, unsigned int &core, unsigned int &build, bool &modified);
virtual void runEncodingPass_init(QList<QRegExp*> &patterns); virtual void runEncodingPass_init(QList<QRegExp*> &patterns);
virtual void runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass); virtual void runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass, double &last_progress, double &size_estimate);
const QString m_encoderName; const QString m_encoderName;
const QString m_binaryFile; const QString m_binaryFile;

View File

@ -39,17 +39,23 @@ static const unsigned int VERSION_X265_MINIMUM_REV = 38;
// Helper Macros // Helper Macros
// ------------------------------------------------------------ // ------------------------------------------------------------
#define X264_UPDATE_PROGRESS(X) do \ #define X265_UPDATE_PROGRESS(X) do \
{ \ { \
bool ok = false; qint64 size_estimate = 0; \ bool ok[2] = { false, false }; \
unsigned int progress = (X)->cap(1).toUInt(&ok); \ unsigned int progressInt = (X)->cap(1).toUInt(&ok[0]); \
unsigned int progressFrc = (X)->cap(2).toUInt(&ok[1]); \
setStatus((pass == 2) ? JobStatus_Running_Pass2 : ((pass == 1) ? JobStatus_Running_Pass1 : JobStatus_Running)); \ setStatus((pass == 2) ? JobStatus_Running_Pass2 : ((pass == 1) ? JobStatus_Running_Pass1 : JobStatus_Running)); \
if(ok) \ if(ok[0] && ok[1]) \
{ \ { \
setProgress(progress); \ const double progress = (double(progressInt) / 100.0) + (double(progressFrc) / 1000.0); \
size_estimate = estimateSize(m_outputFile, progress); \ if(!qFuzzyCompare(progress, last_progress)) \
{ \
setProgress(floor(progress * 100.0)); \
size_estimate = qFuzzyIsNull(size_estimate) ? estimateSize(m_outputFile, progress) : ((0.667 * size_estimate) + (0.333 * estimateSize(m_outputFile, progress))); \
last_progress = progress; \
} \ } \
setDetails(tr("%1, est. file size %2").arg(line.mid(offset).trimmed(), sizeToString(size_estimate))); \ } \
setDetails(tr("%1, est. file size %2").arg(line.mid(offset).trimmed(), sizeToString(qRound64(size_estimate)))); \
} \ } \
while(0) while(0)
@ -325,12 +331,12 @@ void X265Encoder::runEncodingPass_init(QList<QRegExp*> &patterns)
patterns << new QRegExp("\\[\\s*(\\d+)\\.(\\d+)%\\]\\s+(\\d+)/(\\d+)\\s(\\d+).(\\d+)\\s(\\d+).(\\d+)\\s+(\\d+):(\\d+):(\\d+)\\s+(\\d+):(\\d+):(\\d+)"); //regExpModified patterns << new QRegExp("\\[\\s*(\\d+)\\.(\\d+)%\\]\\s+(\\d+)/(\\d+)\\s(\\d+).(\\d+)\\s(\\d+).(\\d+)\\s+(\\d+):(\\d+):(\\d+)\\s+(\\d+):(\\d+):(\\d+)"); //regExpModified
} }
void X265Encoder::runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass) void X265Encoder::runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass, double &last_progress, double &size_estimate)
{ {
int offset = -1; int offset = -1;
if((offset = patterns[0]->lastIndexIn(line)) >= 0) if((offset = patterns[0]->lastIndexIn(line)) >= 0)
{ {
X264_UPDATE_PROGRESS(patterns[0]); X265_UPDATE_PROGRESS(patterns[0]);
} }
else if((offset = patterns[1]->lastIndexIn(line)) >= 0) else if((offset = patterns[1]->lastIndexIn(line)) >= 0)
{ {
@ -350,7 +356,7 @@ void X265Encoder::runEncodingPass_parseLine(const QString &line, QList<QRegExp*>
} }
else if((offset = patterns[3]->lastIndexIn(line)) >= 0) else if((offset = patterns[3]->lastIndexIn(line)) >= 0)
{ {
X264_UPDATE_PROGRESS(patterns[3]); X265_UPDATE_PROGRESS(patterns[3]);
} }
else if(!line.isEmpty()) else if(!line.isEmpty())
{ {

View File

@ -44,7 +44,7 @@ protected:
virtual void checkVersion_parseLine(const QString &line, QList<QRegExp*> &patterns, unsigned int &core, unsigned int &build, bool &modified); virtual void checkVersion_parseLine(const QString &line, QList<QRegExp*> &patterns, unsigned int &core, unsigned int &build, bool &modified);
virtual void runEncodingPass_init(QList<QRegExp*> &patterns); virtual void runEncodingPass_init(QList<QRegExp*> &patterns);
virtual void runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass); virtual void runEncodingPass_parseLine(const QString &line, QList<QRegExp*> &patterns, const int &pass, double &last_progress, double &size_estimate);
const QString m_encoderName; const QString m_encoderName;
const QString m_binaryFile; const QString m_binaryFile;

View File

@ -24,9 +24,9 @@
#endif #endif
#define VER_X264_MAJOR 2 #define VER_X264_MAJOR 2
#define VER_X264_MINOR 3 #define VER_X264_MINOR 4
#define VER_X264_PATCH 9 #define VER_X264_PATCH 0
#define VER_X264_BUILD 868 #define VER_X264_BUILD 874
#define VER_X264_PORTABLE_EDITION (0) #define VER_X264_PORTABLE_EDITION (0)