diff --git a/HISTORY.txt b/HISTORY.txt index 4747b2f..5c1bb4f 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -2,6 +2,9 @@ Simple x264/x265 Launcher version history ----------------------------------------- +Version 2.71 [2016-??-??] +* Added NVEncC encoding support. + Version 2.70 [2016-04-29] * Fixed potential VapourSynth error, when Avisynth is *not* installed * Some installer improvements diff --git a/src/encoder_abstract.cpp b/src/encoder_abstract.cpp index 179c9ac..8ca9e44 100644 --- a/src/encoder_abstract.cpp +++ b/src/encoder_abstract.cpp @@ -164,12 +164,12 @@ bool AbstractEncoder::runEncodingPass(AbstractSource* pipedSource, const QString } //Process all output - PROCESS_PENDING_LINES(processEncode, runEncodingPass_parseLine, patterns, pass, last_progress, size_estimate); + PROCESS_PENDING_LINES(processEncode, runEncodingPass_parseLine, patterns, frames, pass, last_progress, size_estimate); } if(!(bTimeout || bAborted)) { - PROCESS_PENDING_LINES(processEncode, runEncodingPass_parseLine, patterns, pass, last_progress, size_estimate); + PROCESS_PENDING_LINES(processEncode, runEncodingPass_parseLine, patterns, frames, pass, last_progress, size_estimate); } processEncode.waitForFinished(5000); @@ -297,3 +297,8 @@ const AbstractEncoderInfo& AbstractEncoder::getEncoderInfo(void) { MUTILS_THROW("[getEncoderInfo] This function must be overwritten in sub-classes!"); } + +QStringList AbstractEncoderInfo::getDependencies(const SysinfoModel *sysinfo, const OptionsModel::EncArch &encArch, const OptionsModel::EncVariant &encVariant) const +{ + return QStringList(); +} \ No newline at end of file diff --git a/src/encoder_abstract.h b/src/encoder_abstract.h index 01b9044..731ea62 100644 --- a/src/encoder_abstract.h +++ b/src/encoder_abstract.h @@ -39,6 +39,7 @@ public: virtual bool isRCModeSupported(const OptionsModel::RCMode &rcMode) const = 0; virtual bool isInputTypeSupported(const int format) const = 0; virtual QString getBinaryPath(const SysinfoModel *sysinfo, const OptionsModel::EncArch &encArch, const OptionsModel::EncVariant &encVariant) const = 0; + virtual QStringList getDependencies(const SysinfoModel *sysinfo, const OptionsModel::EncArch &encArch, const OptionsModel::EncVariant &encVariant) const; }; class AbstractEncoder : public AbstractTool @@ -55,7 +56,7 @@ 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 runEncodingPass_init(QList &patterns) = 0; - virtual void runEncodingPass_parseLine(const QString &line, QList &patterns, const int &pass, double &last_progress, double &size_estimate) = 0; + virtual void runEncodingPass_parseLine(const QString &line, QList &patterns, const unsigned int &totalFrames, const int &pass, double &last_progress, double &size_estimate) = 0; static double estimateSize(const QString &fileName, const double &progress); static QString sizeToString(qint64 size); diff --git a/src/encoder_factory.cpp b/src/encoder_factory.cpp index 3bc792d..bc8bb9d 100644 --- a/src/encoder_factory.cpp +++ b/src/encoder_factory.cpp @@ -14,7 +14,7 @@ // // 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. +// 51 Franklin Street, Fifth Floory, Boston, MA 02110-1301 USA. // // http://www.gnu.org/licenses/gpl-2.0.txt /////////////////////////////////////////////////////////////////////////////// @@ -26,6 +26,7 @@ #include "model_options.h" #include "encoder_x264.h" #include "encoder_x265.h" +#include "encoder_nvenc.h" //MUtils #include @@ -42,6 +43,9 @@ AbstractEncoder *EncoderFactory::createEncoder(JobObject *jobObject, const Optio case OptionsModel::EncType_X265: encoder = new X265Encoder(jobObject, options, sysinfo, preferences, jobStatus, abort, pause, semaphorePause, sourceFile, outputFile); break; + case OptionsModel::EncType_NVEnc: + encoder = new NVEncEncoder(jobObject, options, sysinfo, preferences, jobStatus, abort, pause, semaphorePause, sourceFile, outputFile); + break; default: MUTILS_THROW("Unknown encoder type encountered!"); } @@ -57,6 +61,8 @@ const AbstractEncoderInfo& EncoderFactory::getEncoderInfo(const OptionsModel::En return X264Encoder::getEncoderInfo(); case OptionsModel::EncType_X265: return X265Encoder::getEncoderInfo(); + case OptionsModel::EncType_NVEnc: + return NVEncEncoder::getEncoderInfo(); default: MUTILS_THROW("Unknown encoder type encountered!"); } diff --git a/src/encoder_nvenc.cpp b/src/encoder_nvenc.cpp new file mode 100644 index 0000000..75ccbd3 --- /dev/null +++ b/src/encoder_nvenc.cpp @@ -0,0 +1,385 @@ +/////////////////////////////////////////////////////////////////////////////// +// Simple x264 Launcher +// Copyright (C) 2004-2016 LoRd_MuldeR +// +// 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 "encoder_nvenc.h" + +//Internal +#include "global.h" +#include "model_options.h" +#include "model_status.h" +#include "mediainfo.h" +#include "model_sysinfo.h" + +//MUtils +#include + +//Qt +#include +#include +#include + +//x265 version info +static const unsigned int VERSION_NVENCC_MINIMUM_VER = 206; +static const unsigned int VERSION_NVENCC_MINIMUM_API = 60; + +// ------------------------------------------------------------ +// Helper Macros +// ------------------------------------------------------------ + +#define NVENCC_UPDATE_PROGRESS(X) do \ +{ \ + bool ok = false; \ + unsigned int progressFrames = (X)->cap(1).toUInt(&ok); \ + setStatus(JobStatus_Running); \ + if(ok && (totalFrames > 0) && (totalFrames != UINT_MAX)) \ + { \ + const double progress = (double(progressFrames) / double(totalFrames)); \ + 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(qRound64(size_estimate)))); \ +} \ +while(0) + +#define REMOVE_CUSTOM_ARG(LIST, ITER, FLAG, PARAM) do \ +{ \ + if(ITER != LIST.end()) \ + { \ + if((*ITER).compare(PARAM, Qt::CaseInsensitive) == 0) \ + { \ + log(tr("WARNING: Custom parameter \"" PARAM "\" will be ignored in Pipe'd mode!\n")); \ + ITER = LIST.erase(ITER); \ + if(ITER != LIST.end()) \ + { \ + if(!((*ITER).startsWith("--", Qt::CaseInsensitive))) ITER = LIST.erase(ITER); \ + } \ + FLAG = true; \ + } \ + } \ +} \ +while(0) + +// ------------------------------------------------------------ +// Encoder Info +// ------------------------------------------------------------ + +class NVEncEncoderInfo : public AbstractEncoderInfo +{ +public: + virtual QFlags getVariants(void) const + { + QFlags variants; + variants |= OptionsModel::EncVariant_8Bit; + return variants; + } + + virtual QStringList getTunings(void) const + { + return QStringList(); + } + + virtual QStringList getPresets(void) const + { + return QStringList(); + } + + virtual QStringList getProfiles(const OptionsModel::EncVariant &variant) const + { + QStringList profiles; + switch(variant) + { + case OptionsModel::EncVariant_8Bit: + profiles << "baseline" << "main" << "high"; + break; + } + return profiles; + } + + virtual QStringList supportedOutputFormats(void) const + { + QStringList extLst; + extLst << "mp4"; + return extLst; + } + + virtual bool isRCModeSupported(const OptionsModel::RCMode &rcMode) const + { + switch(rcMode) + { + case OptionsModel::RCMode_CQ: + case OptionsModel::RCMode_ABR: + return true; + default: + return false; + } + } + + virtual bool isInputTypeSupported(const int format) const + { + switch(format) + { + case MediaInfo::FILETYPE_YUV4MPEG2: + return true; + default: + return false; + } + } + + virtual QString getBinaryPath(const SysinfoModel *sysinfo, const OptionsModel::EncArch &encArch, const OptionsModel::EncVariant &encVariant) const + { + QString arch, variant; + switch(encArch) + { + case OptionsModel::EncArch_x86_32: arch = "x86"; break; + case OptionsModel::EncArch_x86_64: arch = "x64"; break; + default: MUTILS_THROW("Unknown encoder arch!"); + } + switch(encVariant) + { + case OptionsModel::EncVariant_8Bit: variant = "8bit"; break; + default: MUTILS_THROW("Unknown encoder arch!"); + } + return QString("%1/toolset/%2/nvencc_%2.exe").arg(sysinfo->getAppPath(), arch); + } + + virtual QStringList getDependencies(const SysinfoModel *sysinfo, const OptionsModel::EncArch &encArch, const OptionsModel::EncVariant &encVariant) const + { + QString arch, variant; + switch (encArch) + { + case OptionsModel::EncArch_x86_32: arch = "x86"; break; + case OptionsModel::EncArch_x86_64: arch = "x64"; break; + default: MUTILS_THROW("Unknown encoder arch!"); + } + switch (encVariant) + { + case OptionsModel::EncVariant_8Bit: variant = "8bit"; break; + default: MUTILS_THROW("Unknown encoder arch!"); + } + QStringList dependencies; + dependencies << QString("%1/toolset/%2/avcodec-57.dll" ).arg(sysinfo->getAppPath(), arch); + dependencies << QString("%1/toolset/%2/avfilter-6.dll" ).arg(sysinfo->getAppPath(), arch); + dependencies << QString("%1/toolset/%2/avformat-57.dll" ).arg(sysinfo->getAppPath(), arch); + dependencies << QString("%1/toolset/%2/avutil-55.dll" ).arg(sysinfo->getAppPath(), arch); + dependencies << QString("%1/toolset/%2/swresample-2.dll").arg(sysinfo->getAppPath(), arch); + return dependencies; + } +}; + +static const NVEncEncoderInfo s_x265EncoderInfo; + +const AbstractEncoderInfo &NVEncEncoder::getEncoderInfo(void) +{ + return s_x265EncoderInfo; +} + +// ------------------------------------------------------------ +// Constructor & Destructor +// ------------------------------------------------------------ + +NVEncEncoder::NVEncEncoder(JobObject *jobObject, const OptionsModel *options, const SysinfoModel *const sysinfo, const PreferencesModel *const preferences, JobStatus &jobStatus, volatile bool *abort, volatile bool *pause, QSemaphore *semaphorePause, const QString &sourceFile, const QString &outputFile) +: + AbstractEncoder(jobObject, options, sysinfo, preferences, jobStatus, abort, pause, semaphorePause, sourceFile, outputFile) +{ + if(options->encType() != OptionsModel::EncType_NVEnc) + { + MUTILS_THROW("Invalid encoder type!"); + } +} + +NVEncEncoder::~NVEncEncoder(void) +{ + /*Nothing to do here*/ +} + +QString NVEncEncoder::getName(void) const +{ + QString arch, variant; + switch(m_options->encArch()) + { + case OptionsModel::EncArch_x86_32: arch = "x86"; break; + case OptionsModel::EncArch_x86_64: arch = "x64"; break; + default: MUTILS_THROW("Unknown encoder arch!"); + } + switch(m_options->encVariant()) + { + case OptionsModel::EncVariant_8Bit: variant = "8-Bit"; break; + default: MUTILS_THROW("Unknown encoder arch!"); + } + return QString("NVEncC, %1, %2").arg(arch, variant); +} + +// ------------------------------------------------------------ +// Check Version +// ------------------------------------------------------------ + +void NVEncEncoder::checkVersion_init(QList &patterns, QStringList &cmdLine) +{ + cmdLine << "--version"; + patterns << new QRegExp("\\bNVEncC\\s+\\(\\w+\\)\\s+(\\d)\\.(\\d+)\\s+by\\s+rigaya\\s+\\[NVENC\\s+API\\s+v(\\d+)\\.(\\d+)\\]", Qt::CaseInsensitive); +} + +void NVEncEncoder::checkVersion_parseLine(const QString &line, QList &patterns, unsigned int &core, unsigned int &build, bool &modified) +{ + int offset = -1; + + if((offset = patterns[0]->lastIndexIn(line)) >= 0) + { + bool ok[4] = { false, false, false, false }; + unsigned int temp[4]; + temp[0] = patterns[0]->cap(1).toUInt(&ok[0]); + temp[1] = patterns[0]->cap(2).toUInt(&ok[1]); + temp[2] = patterns[0]->cap(2).toUInt(&ok[2]); + temp[3] = patterns[0]->cap(2).toUInt(&ok[3]); + if(ok[0] && ok[1]) + { + core = (100 * temp[0]) + temp[1]; + } + if (ok[2] && ok[3]) + { + build = (10 * temp[2]) + temp[3]; + } + } + + if(!line.isEmpty()) + { + log(line); + } +} + +bool NVEncEncoder::checkVersion_succeeded(const int &exitCode) +{ + return (exitCode == 0) || (exitCode == 1); +} + +QString NVEncEncoder::printVersion(const unsigned int &revision, const bool &modified) +{ + unsigned int core, build; + splitRevision(revision, core, build); + + return tr("NVEncC version: %1.%2").arg(QString::number(core / 100), QString::number(core % 100).leftJustified(2, QLatin1Char('0'))); +} + +bool NVEncEncoder::isVersionSupported(const unsigned int &revision, const bool &modified) +{ + unsigned int core, build; + splitRevision(revision, core, build); + + if(core < VERSION_NVENCC_MINIMUM_VER) + { + log(tr("\nERROR: Your version of NVEncC is too old! (Minimum required version is %1.%2)").arg(QString::number(VERSION_NVENCC_MINIMUM_VER / 100), QString::number(VERSION_NVENCC_MINIMUM_VER % 100))); + return false; + } + else if(core > VERSION_NVENCC_MINIMUM_VER) + { + log(tr("\nWARNING: Your version of NVEncC is newer than the latest tested version, take care!")); + log(tr("This application works best with NVEncC version %1.%2. Newer versions may work or not.").arg(QString::number(VERSION_NVENCC_MINIMUM_VER / 100), QString::number(VERSION_NVENCC_MINIMUM_VER % 100))); + } + + if (build < VERSION_NVENCC_MINIMUM_API) + { + log(tr("\nERROR: Your version of NVENC API is too old! (Minimum required version is %1.%2)").arg(QString::number(VERSION_NVENCC_MINIMUM_API / 10), QString::number(VERSION_NVENCC_MINIMUM_API % 10))); + return false; + } + + return true; +} + +// ------------------------------------------------------------ +// Encoding Functions +// ------------------------------------------------------------ + +void NVEncEncoder::buildCommandLine(QStringList &cmdLine, const bool &usePipe, const unsigned int &frames, const QString &indexFile, const int &pass, const QString &passLogFile) +{ + double crf_int = 0.0, crf_frc = 0.0; + + switch(m_options->rcMode()) + { + case OptionsModel::RCMode_ABR: + cmdLine << "--vbr" << QString::number(m_options->bitrate()); + break; + case OptionsModel::RCMode_CQ: + cmdLine << "--cqp" << QString::number(qRound(m_options->quantizer())); + break; + default: + MUTILS_THROW("Bad rate-control mode !!!"); + break; + } + + const QString profile = m_options->profile().simplified().toLower(); + if(!profile.isEmpty()) + { + if(profile.compare(QString::fromLatin1(OptionsModel::PROFILE_UNRESTRICTED), Qt::CaseInsensitive) != 0) + { + cmdLine << "--profile" << profile; + } + } + + if(!m_options->customEncParams().isEmpty()) + { + QStringList customArgs = splitParams(m_options->customEncParams(), m_sourceFile, m_outputFile); + if(usePipe) + { + QStringList::iterator i = customArgs.begin(); + while(i != customArgs.end()) + { + bool bModified = false; + REMOVE_CUSTOM_ARG(customArgs, i, bModified, "--fps"); + REMOVE_CUSTOM_ARG(customArgs, i, bModified, "--frames"); + if(!bModified) i++; + } + } + cmdLine.append(customArgs); + } + + cmdLine << "--output" << QDir::toNativeSeparators(m_outputFile); + + if(usePipe) + { + cmdLine << "--y4m" << "--input" << "-"; + } + else + { + cmdLine << "--input" << QDir::toNativeSeparators(m_sourceFile); + } +} + +void NVEncEncoder::runEncodingPass_init(QList &patterns) +{ + patterns << new QRegExp("^(\\d+) frames:"); //regExpFrameCnt +} + +void NVEncEncoder::runEncodingPass_parseLine(const QString &line, QList &patterns, const unsigned int &totalFrames, const int &pass, double &last_progress, double &size_estimate) +{ + int offset = -1; + if((offset = patterns[0]->lastIndexIn(line)) >= 0) + { + NVENCC_UPDATE_PROGRESS(patterns[0]); + } + else if(!line.isEmpty()) + { + log(line); + } +} diff --git a/src/encoder_nvenc.h b/src/encoder_nvenc.h new file mode 100644 index 0000000..430cdde --- /dev/null +++ b/src/encoder_nvenc.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////// +// Simple x264 Launcher +// Copyright (C) 2004-2016 LoRd_MuldeR +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "encoder_abstract.h" + +class NVEncEncoder : public AbstractEncoder +{ +public: + NVEncEncoder(JobObject *jobObject, const OptionsModel *options, const SysinfoModel *const sysinfo, const PreferencesModel *const preferences, JobStatus &jobStatus, volatile bool *abort, volatile bool *pause, QSemaphore *semaphorePause, const QString &sourceFile, const QString &outputFile); + virtual ~NVEncEncoder(void); + + virtual QString getName(void) const; + + virtual QString printVersion(const unsigned int &revision, const bool &modified); + virtual bool isVersionSupported(const unsigned int &revision, const bool &modified); + + static const AbstractEncoderInfo& getEncoderInfo(void); + +protected: + virtual QString getBinaryPath() const { return getEncoderInfo().getBinaryPath(m_sysinfo, m_options->encArch(), m_options->encVariant()); } + virtual void buildCommandLine(QStringList &cmdLine, const bool &usePipe, const unsigned int &frames, const QString &indexFile, const int &pass, const QString &passLogFile); + + virtual void checkVersion_init(QList &patterns, QStringList &cmdLine); + virtual void checkVersion_parseLine(const QString &line, QList &patterns, unsigned int &core, unsigned int &build, bool &modified); + virtual bool checkVersion_succeeded(const int &exitCode); + + virtual void runEncodingPass_init(QList &patterns); + virtual void runEncodingPass_parseLine(const QString &line, QList &patterns, const unsigned int &totalFrames, const int &pass, double &last_progress, double &size_estimate); +}; diff --git a/src/encoder_x264.cpp b/src/encoder_x264.cpp index ce1a957..83367a1 100644 --- a/src/encoder_x264.cpp +++ b/src/encoder_x264.cpp @@ -406,7 +406,7 @@ void X264Encoder::runEncodingPass_init(QList &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 } -void X264Encoder::runEncodingPass_parseLine(const QString &line, QList &patterns, const int &pass, double &last_progress, double &size_estimate) +void X264Encoder::runEncodingPass_parseLine(const QString &line, QList &patterns, const unsigned int &totalFrames, const int &pass, double &last_progress, double &size_estimate) { int offset = -1; if((offset = patterns[0]->lastIndexIn(line)) >= 0) diff --git a/src/encoder_x264.h b/src/encoder_x264.h index ce3f9d2..746e337 100644 --- a/src/encoder_x264.h +++ b/src/encoder_x264.h @@ -44,6 +44,6 @@ protected: virtual void checkVersion_parseLine(const QString &line, QList &patterns, unsigned int &core, unsigned int &build, bool &modified); virtual void runEncodingPass_init(QList &patterns); - virtual void runEncodingPass_parseLine(const QString &line, QList &patterns, const int &pass, double &last_progress, double &size_estimate); + virtual void runEncodingPass_parseLine(const QString &line, QList &patterns, const unsigned int &totalFrames, const int &pass, double &last_progress, double &size_estimate); }; diff --git a/src/encoder_x265.cpp b/src/encoder_x265.cpp index 7e0f7a2..fcf8ff5 100644 --- a/src/encoder_x265.cpp +++ b/src/encoder_x265.cpp @@ -400,7 +400,7 @@ void X265Encoder::runEncodingPass_init(QList &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 } -void X265Encoder::runEncodingPass_parseLine(const QString &line, QList &patterns, const int &pass, double &last_progress, double &size_estimate) +void X265Encoder::runEncodingPass_parseLine(const QString &line, QList &patterns, const unsigned int &totalFrames, const int &pass, double &last_progress, double &size_estimate) { int offset = -1; if((offset = patterns[0]->lastIndexIn(line)) >= 0) diff --git a/src/encoder_x265.h b/src/encoder_x265.h index 978f388..4d6f28d 100644 --- a/src/encoder_x265.h +++ b/src/encoder_x265.h @@ -44,5 +44,5 @@ protected: virtual void checkVersion_parseLine(const QString &line, QList &patterns, unsigned int &core, unsigned int &build, bool &modified); virtual void runEncodingPass_init(QList &patterns); - virtual void runEncodingPass_parseLine(const QString &line, QList &patterns, const int &pass, double &last_progress, double &size_estimate); + virtual void runEncodingPass_parseLine(const QString &line, QList &patterns, const unsigned int &totalFrames, const int &pass, double &last_progress, double &size_estimate); }; diff --git a/src/model_options.h b/src/model_options.h index 00b31b6..38f1f3c 100644 --- a/src/model_options.h +++ b/src/model_options.h @@ -37,11 +37,12 @@ public: enum EncType { - EncType_X264 = 0, - EncType_X265 = 1, + EncType_X264 = 0, + EncType_X265 = 1, + EncType_NVEnc = 2, EncType_MIN = EncType_X264, - EncType_MAX = EncType_X265, + EncType_MAX = EncType_NVEnc, }; enum EncArch @@ -91,9 +92,9 @@ public: QString customAvs2YUV(void) const { return m_custom_avs2yuv; } //Setter - void setEncType(EncType type) { m_encoderType = qBound(EncType_X264, type, EncType_X265); } - void setEncArch(EncArch arch) { m_encoderArch = qBound(EncArch_x86_32, arch, EncArch_x86_64); } - void setEncVariant(EncVariant variant) { m_encoderVariant = qBound(EncVariant_8Bit, variant, EncVariant_12Bit); } + void setEncType(EncType type) { m_encoderType = qBound(EncType_MIN, type, EncType_MAX); } + void setEncArch(EncArch arch) { m_encoderArch = qBound(EncArch_MIN, arch, EncArch_MAX); } + void setEncVariant(EncVariant variant) { m_encoderVariant = qBound(EncVariant_MIN, variant, EncVariant_MAX); } void setRCMode(RCMode mode) { m_rcMode = qBound(RCMode_CRF, mode, RCMode_ABR); } void setBitrate(unsigned int bitrate) { m_bitrate = qBound(10U, bitrate, 800000U); } void setQuantizer(double quantizer) { m_quantizer = qBound(0.0, quantizer, 52.0); } diff --git a/src/thread_binaries.cpp b/src/thread_binaries.cpp index a210085..8041456 100644 --- a/src/thread_binaries.cpp +++ b/src/thread_binaries.cpp @@ -145,8 +145,9 @@ void BinariesCheckThread::checkBinaries3(volatile bool &success, const SysinfoMo success = true; //Create list of all required binary files - QStringList binFiles; - for(OptionsModel::EncType encdr = OptionsModel::EncType_X264; encdr <= OptionsModel::EncType_X265; NEXT(encdr)) + typedef QPair FileEntry; + QList binFiles; + for(OptionsModel::EncType encdr = OptionsModel::EncType_MIN; encdr <= OptionsModel::EncType_MAX; NEXT(encdr)) { const AbstractEncoderInfo &encInfo = EncoderFactory::getEncoderInfo(encdr); const QFlags variants = encInfo.getVariants(); @@ -156,34 +157,42 @@ void BinariesCheckThread::checkBinaries3(volatile bool &success, const SysinfoMo { if(variants.testFlag(varnt)) { - binFiles << encInfo.getBinaryPath(sysinfo, arch, varnt); + binFiles << qMakePair(encInfo.getBinaryPath(sysinfo, arch, varnt), false); + const QStringList dependencies = encInfo.getDependencies(sysinfo, arch, varnt); + if (!dependencies.empty()) + { + for (QStringList::ConstIterator iter = dependencies.constBegin(); iter != dependencies.constEnd(); iter++) + { + binFiles << qMakePair(*iter, true); + } + } } } } } for(int i = 0; i < 2; i++) { - binFiles << SourceFactory::getSourceInfo(SourceFactory::SourceType_AVS).getBinaryPath(sysinfo, bool(i)); - binFiles << AVS_CHECK_BINARY(sysinfo, bool(i)); + binFiles << qMakePair(SourceFactory::getSourceInfo(SourceFactory::SourceType_AVS).getBinaryPath(sysinfo, bool(i)), false); + binFiles << qMakePair(AVS_CHECK_BINARY(sysinfo, bool(i)), false); } for(size_t i = 0; UpdaterDialog::BINARIES[i].name; i++) { if(UpdaterDialog::BINARIES[i].exec) { - binFiles << QString("%1/toolset/common/%2").arg(sysinfo->getAppPath(), QString::fromLatin1(UpdaterDialog::BINARIES[i].name)); + binFiles << qMakePair(QString("%1/toolset/common/%2").arg(sysinfo->getAppPath(), QString::fromLatin1(UpdaterDialog::BINARIES[i].name)), false); } } //Actually validate the binaries size_t currentFile = 0; - for(QStringList::ConstIterator iter = binFiles.constBegin(); iter != binFiles.constEnd(); iter++) + for(QList::ConstIterator iter = binFiles.constBegin(); iter != binFiles.constEnd(); iter++) { - QScopedPointer file(new QFile(*iter)); + QScopedPointer file(new QFile(iter->first)); qDebug("%s", MUTILS_UTF8(file->fileName())); if(file->open(QIODevice::ReadOnly)) { - if(!MUtils::OS::is_executable_file(file->fileName())) + if(!(iter->second || MUtils::OS::is_executable_file(file->fileName()))) { success = false; qWarning("Required tool does NOT look like a valid Win32/Win64 binary:\n%s\n", MUTILS_UTF8(file->fileName())); diff --git a/src/version.h b/src/version.h index e55ab3a..8164c4d 100644 --- a/src/version.h +++ b/src/version.h @@ -26,7 +26,7 @@ #define VER_X264_MAJOR 2 #define VER_X264_MINOR 7 #define VER_X264_PATCH 0 -#define VER_X264_BUILD 1026 +#define VER_X264_BUILD 1028 #define VER_X264_PORTABLE_EDITION (0) diff --git a/src/win_addJob.cpp b/src/win_addJob.cpp index f503ca0..eacbd80 100644 --- a/src/win_addJob.cpp +++ b/src/win_addJob.cpp @@ -322,8 +322,9 @@ AddJobDialog::AddJobDialog(QWidget *parent, OptionsModel *const options, Recentl setMaximumHeight(height()); //Init encoder combobox - ui->cbxEncoderType->addItem(tr("x264 (AVC)"), OptionsModel::EncType_X264); + ui->cbxEncoderType->addItem(tr("x264 (AVC)"), OptionsModel::EncType_X264); ui->cbxEncoderType->addItem(tr("x265 (HEVC)"), OptionsModel::EncType_X265); + ui->cbxEncoderType->addItem(tr("NVEncC"), OptionsModel::EncType_NVEnc); //Init arch combobox ui->cbxEncoderArch->addItem(tr("32-Bit"), OptionsModel::EncArch_x86_32); diff --git a/x264_launcher_MSVC2015.vcxproj b/x264_launcher_MSVC2015.vcxproj index 885c41e..2c3ef5b 100644 --- a/x264_launcher_MSVC2015.vcxproj +++ b/x264_launcher_MSVC2015.vcxproj @@ -167,6 +167,8 @@ mkdir "$(TargetDir)\imageformats" copy /Y "$(SolutionDir)res\toolset\x86\*.exe" "$(TargetDir)\toolset\x86\" copy /Y "$(SolutionDir)res\toolset\x64\*.exe" "$(TargetDir)\toolset\x64\" +copy /Y "$(SolutionDir)res\toolset\x86\*.dll" "$(TargetDir)\toolset\x86\" +copy /Y "$(SolutionDir)res\toolset\x64\*.dll" "$(TargetDir)\toolset\x64\" copy /Y "$(SolutionDir)res\toolset\common\*.exe" "$(TargetDir)\toolset\common\" copy /Y "$(SolutionDir)res\toolset\common\*.gpg" "$(TargetDir)\toolset\common\" @@ -285,6 +287,7 @@ copy /Y "$(ProjectDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\im $(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp;%(Outputs) $(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp;%(Outputs) + @@ -428,6 +431,7 @@ copy /Y "$(ProjectDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\im + diff --git a/x264_launcher_MSVC2015.vcxproj.filters b/x264_launcher_MSVC2015.vcxproj.filters index 2aa795a..40db07c 100644 --- a/x264_launcher_MSVC2015.vcxproj.filters +++ b/x264_launcher_MSVC2015.vcxproj.filters @@ -111,6 +111,9 @@ Header Files + + Header Files + @@ -266,6 +269,9 @@ Source Files + + Source Files +