feat: add vaapi path for video wallpapers on generic gpus
C++ / fmt (pull_request) Failing after 6s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 11s
JS/TS / fmt (pull_request) Successful in 10s
JS/TS / lint (pull_request) Successful in 8s
Python / static (pull_request) Failing after 32s
Rust / build (pull_request) Successful in 52s
Python / verify (pull_request) Failing after 1m23s
Rust / fmt (pull_request) Successful in 51s
Rust / clippy (pull_request) Successful in 1m2s
C++ / fmt (pull_request) Failing after 6s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 11s
JS/TS / fmt (pull_request) Successful in 10s
JS/TS / lint (pull_request) Successful in 8s
Python / static (pull_request) Failing after 32s
Rust / build (pull_request) Successful in 52s
Python / verify (pull_request) Failing after 1m23s
Rust / fmt (pull_request) Successful in 51s
Rust / clippy (pull_request) Successful in 1m2s
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
#include "videotranscoder.hpp"
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
#include <QStringList>
|
||||
|
||||
#include <QtLogging>
|
||||
|
||||
Q_LOGGING_CATEGORY(transcodeLog, "ZShell.Internal.wallpaper")
|
||||
|
||||
namespace ZShell::wallpaper {
|
||||
|
||||
VideoTranscoder::VideoTranscoder(QObject* parent) : QObject(parent) {}
|
||||
|
||||
bool VideoTranscoder::isHardwareCodec(const QString& codec) {
|
||||
static const QStringList hardware{
|
||||
"av1",
|
||||
"hevc",
|
||||
"h264",
|
||||
"vp9",
|
||||
"vp8",
|
||||
"vc1",
|
||||
"mpeg2",
|
||||
"mpeg2video",
|
||||
"mpeg4",
|
||||
"mjpeg",
|
||||
};
|
||||
|
||||
return hardware.contains(codec);
|
||||
}
|
||||
|
||||
QString VideoTranscoder::codecName(const QString& path) const {
|
||||
QProcess probe;
|
||||
probe.start(
|
||||
"ffprobe",
|
||||
{
|
||||
"-v",
|
||||
"error",
|
||||
"-select_streams",
|
||||
"v:0",
|
||||
"-show_entries",
|
||||
"stream=codec_name",
|
||||
"-of",
|
||||
"default=nw=1:nk=1",
|
||||
path,
|
||||
});
|
||||
|
||||
if (!probe.waitForFinished(2000) || probe.exitCode() != 0) {
|
||||
qWarning(transcodeLog) << "WallpaperService: ffprobe failed for" << path
|
||||
<< "(exit" << probe.exitCode() << ")";
|
||||
return {};
|
||||
}
|
||||
|
||||
return QString::fromUtf8(probe.readAllStandardOutput()).trimmed().toLower();
|
||||
}
|
||||
|
||||
QString VideoTranscoder::cacheDir() const {
|
||||
return QDir::homePath() + "/.cache/zshell/wallpaper-videos";
|
||||
}
|
||||
|
||||
QString VideoTranscoder::transcodeTarget(const QString& path) const {
|
||||
const QFileInfo info(path);
|
||||
|
||||
const QByteArray key =
|
||||
path.toUtf8() + '|' + QByteArray::number(info.size()) + '|' +
|
||||
QByteArray::number(info.lastModified().toMSecsSinceEpoch());
|
||||
|
||||
const QString hash = QString::fromUtf8(
|
||||
QCryptographicHash::hash(key, QCryptographicHash::Sha1).toHex());
|
||||
|
||||
return cacheDir() + '/' + hash + ".av1.mkv";
|
||||
}
|
||||
|
||||
bool VideoTranscoder::needsTranscode(const QString& path) const {
|
||||
if (path.startsWith(cacheDir())) return false;
|
||||
|
||||
const QString codec = codecName(path);
|
||||
if (codec.isEmpty()) return false;
|
||||
|
||||
return !isHardwareCodec(codec);
|
||||
}
|
||||
|
||||
void VideoTranscoder::start(const QString& src, const QString& dst) {
|
||||
QDir().mkpath(cacheDir());
|
||||
|
||||
if (m_process) {
|
||||
m_process->kill();
|
||||
m_process->deleteLater();
|
||||
m_process = nullptr;
|
||||
}
|
||||
|
||||
m_process = new QProcess(this);
|
||||
auto* proc = m_process;
|
||||
|
||||
connect(proc, &QProcess::readyReadStandardError, proc, [proc]() {
|
||||
qWarning(transcodeLog).noquote()
|
||||
<< "ffmpeg:" << QString::fromUtf8(proc->readAllStandardError());
|
||||
});
|
||||
|
||||
connect(
|
||||
proc,
|
||||
&QProcess::finished,
|
||||
this,
|
||||
[this, proc, dst](int code, QProcess::ExitStatus status) {
|
||||
const bool ok = code == 0 && status == QProcess::NormalExit &&
|
||||
QFile::exists(dst);
|
||||
|
||||
qWarning(transcodeLog)
|
||||
<< "WallpaperService: transcode finished, exit" << code
|
||||
<< "status" << int(status) << "exists" << QFile::exists(dst)
|
||||
<< "->" << dst;
|
||||
|
||||
if (proc == m_process) m_process = nullptr;
|
||||
proc->deleteLater();
|
||||
|
||||
emit transcoded(dst, ok);
|
||||
});
|
||||
|
||||
qWarning(transcodeLog) << "WallpaperService: transcoding" << src << "->"
|
||||
<< dst;
|
||||
|
||||
proc->setProgram("nice");
|
||||
proc->setArguments({
|
||||
"-n",
|
||||
"19",
|
||||
"ffmpeg",
|
||||
"-hide_banner",
|
||||
"-loglevel",
|
||||
"error",
|
||||
"-y",
|
||||
"-threads",
|
||||
"2",
|
||||
"-i",
|
||||
src,
|
||||
"-map",
|
||||
"0:v:0",
|
||||
"-vf",
|
||||
"scale=in_range=pc:out_range=tv:out_color_matrix=bt709",
|
||||
"-colorspace",
|
||||
"bt709",
|
||||
"-color_primaries",
|
||||
"bt709",
|
||||
"-color_trc",
|
||||
"bt709",
|
||||
"-color_range",
|
||||
"tv",
|
||||
"-c:v",
|
||||
"libsvtav1",
|
||||
"-preset",
|
||||
"6",
|
||||
"-crf",
|
||||
"20",
|
||||
"-pix_fmt",
|
||||
"yuv420p10le",
|
||||
"-an",
|
||||
dst,
|
||||
});
|
||||
|
||||
proc->start();
|
||||
}
|
||||
|
||||
} // namespace ZShell::wallpaper
|
||||
Reference in New Issue
Block a user