Package: release.debian.org Severity: normal X-Debbugs-Cc: kpipew...@packages.debian.org, Debian Qt/KDE Maintainers <debian-qt-kde@lists.debian.org> Control: affects -1 + src:kpipewire User: release.debian....@packages.debian.org Usertags: unblock
Dear Release Team, please unblock package kpipewire. [ Reason ] It contains the following changes: * New upstream release (6.3.5). - Tranlation fixes. * Backport upstream commits: - Fix major VP9 encoding performance issue in apps using kpipewire like spectacle by actually passing the encoding options to FFmpeg. (kde#488896) - Correctly handle asynchronous request and feedback of encoding status changes. - Improve encoding startup performance by only querying VAAPI when actually necessary. * Update symbols from build for 6.3.5. There is one symbol removal caused by this change : - Correctly handle asynchronous request and feedback of encoding status changes. The symbol is from the protected PipeWireBaseEncodedStream::refresh() method, that is was only used in derived classes also shipped by the kpipewire package and all uses replaced in the patch. Reverse dependencies don’t use this (or any other) protected field from PipeWireBaseEncodedStream as can be seen in [1], [2] and [3]. [ Impact ] This upload fixes 2 issues that have major usability impacts: - kde#488896 [4] Huge frame drops when recording WebM/VP9 with spectacle due to incorrect parameters being passed to the encoder. - necessary changes to fix kde#505142 [5] in spectacle: spectacle freezing when finishing recording. [ Tests ] - Tested locally that the users of kpipewire spectacle and krdp work correctly. - Upstream test suite passes in local debuild. [ Risks ] Only backport of upstream commits that apply cleanly. Further fixes can easily be backported or the changes reverted. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing Thanks! [1] https://codesearch.debian.net/search?q=PipeWireBaseEncodedStream&perpkg=1 [2] https://codesearch.debian.net/search?q=PipeWireBaseEncodedStream+package%3A%5CQkde-spectacle%5CE [3] https://codesearch.debian.net/search?q=PipeWireBaseEncodedStream+package%3A%5CQkrdp%5CE [4] https://bugs.kde.org/show_bug.cgi?id=488896 [5] https://bugs.kde.org/show_bug.cgi?id=505142 unblock kpipewire/6.3.5-1
diff -Nru kpipewire-6.3.4/CMakeLists.txt kpipewire-6.3.5/CMakeLists.txt --- kpipewire-6.3.4/CMakeLists.txt 2025-04-02 05:36:16.000000000 +0200 +++ kpipewire-6.3.5/CMakeLists.txt 2025-05-06 19:56:52.000000000 +0200 @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.16) -project(KPipewire VERSION "6.3.4") +project(KPipewire VERSION "6.3.5") set(KF6_MIN_VERSION "6.10.0") find_package(ECM ${KF6_MIN_VERSION} REQUIRED NO_MODULE) diff -Nru kpipewire-6.3.4/debian/changelog kpipewire-6.3.5/debian/changelog --- kpipewire-6.3.4/debian/changelog 2025-04-03 00:58:40.000000000 +0200 +++ kpipewire-6.3.5/debian/changelog 2025-05-19 00:58:37.000000000 +0200 @@ -1,3 +1,18 @@ +kpipewire (6.3.5-1) unstable; urgency=medium + + [ Aurélien COUDERC ] + * New upstream release (6.3.5). + * Backport upstream commits: + - Fix major VP9 encoding performance issue in apps using kpipewire like + spectacle by actually passing the encoding options to FFmpeg. (kde#488896) + - Correctly handle asynchronous request and feedback of encoding status + changes. + - Improve encoding startup performance by only querying VAAPI when + actually necessary. + * Update symbols from build for 6.3.5. + + -- Aurélien COUDERC <couc...@debian.org> Mon, 19 May 2025 00:58:37 +0200 + kpipewire (6.3.4-1) unstable; urgency=medium [ Patrick Franz ] diff -Nru kpipewire-6.3.4/debian/libkpipewirerecord6.symbols kpipewire-6.3.5/debian/libkpipewirerecord6.symbols --- kpipewire-6.3.4/debian/libkpipewirerecord6.symbols 2024-11-26 23:48:55.000000000 +0100 +++ kpipewire-6.3.5/debian/libkpipewirerecord6.symbols 2025-05-19 00:58:37.000000000 +0200 @@ -1,4 +1,4 @@ -# SymbolsHelper-Confirmed: 6.1.0 amd64 armel armhf riscv64 +# SymbolsHelper-Confirmed: 6.3.5 amd64 libKPipeWireRecord.so.6 libkpipewirerecord6 #MINVER# * Build-Depends-Package: libkpipewire-dev _ZN14PipeWireRecord11makeProduceEv@Base 6.1.0 @@ -43,8 +43,9 @@ _ZN25PipeWireBaseEncodedStream19setMaxPendingFramesEi@Base 6.1.0 _ZN25PipeWireBaseEncodedStream21setEncodingPreferenceENS_18EncodingPreferenceE@Base 6.1.0 _ZN25PipeWireBaseEncodedStream23maxPendingFramesChangedEv@Base 6.1.0 + _ZN25PipeWireBaseEncodedStream4stopEv@Base 6.3.5 _ZN25PipeWireBaseEncodedStream5setFdEj@Base 6.1.0 - _ZN25PipeWireBaseEncodedStream7refreshEv@Base 6.1.0 + _ZN25PipeWireBaseEncodedStream5startEv@Base 6.3.5 _ZN25PipeWireBaseEncodedStream9fdChangedEj@Base 6.1.0 _ZN25PipeWireBaseEncodedStream9setActiveEb@Base 6.1.0 _ZN25PipeWireBaseEncodedStream9setNodeIdEj@Base 6.1.0 diff -Nru kpipewire-6.3.4/debian/patches/series kpipewire-6.3.5/debian/patches/series --- kpipewire-6.3.4/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ kpipewire-6.3.5/debian/patches/series 2025-05-19 00:58:37.000000000 +0200 @@ -0,0 +1,8 @@ +upstream_686df1e3_Tweak-compiler-warning-flags-to-reduce-unneeded-output.patch +upstream_52911b70_Change-Encoder-applyEncodingPreference-to-buildEncodingOptions-.patch +upstream_c928ed5c_Add-logging-of-encoding-options-if-log-level-is-set-to-info.patch +upstream_f127a2cc_Set-threads-option-by-default-in-Encoder.patch +upstream_5a223fe4_Port-Encoder-away-from-deprecated-avcodec-close.patch +upstream_123ae0d2_Tweak-encoding-options-for-VP9.patch +upstream_0ac4aa41_encodedstream-Deprecate-setActive-and-replace-with-an-explicit-API.patch +upstream_8793ae86_encodedstream-Don-t-query-VAAPI-in-the-constructor.patch diff -Nru kpipewire-6.3.4/debian/patches/upstream_0ac4aa41_encodedstream-Deprecate-setActive-and-replace-with-an-explicit-API.patch kpipewire-6.3.5/debian/patches/upstream_0ac4aa41_encodedstream-Deprecate-setActive-and-replace-with-an-explicit-API.patch --- kpipewire-6.3.4/debian/patches/upstream_0ac4aa41_encodedstream-Deprecate-setActive-and-replace-with-an-explicit-API.patch 1970-01-01 01:00:00.000000000 +0100 +++ kpipewire-6.3.5/debian/patches/upstream_0ac4aa41_encodedstream-Deprecate-setActive-and-replace-with-an-explicit-API.patch 2025-05-19 00:58:37.000000000 +0200 @@ -0,0 +1,365 @@ +From 0ac4aa418b6a7665f3d9e811c7f6632687651e6b Mon Sep 17 00:00:00 2001 +From: Arjen Hiemstra <ahiems...@heimr.nl> +Date: Tue, 8 Oct 2024 14:03:20 +0200 +Subject: [PATCH] encodedstream: Deprecate setActive() and replace with an + explicit API + +setActive() currently implies starting/stopping the recording process. +However, this is somewhat awkward as everything is rather asynchronous +with multiple threads involved, which means calling setActive() may mean +things are not actually active or may still be active. + +To avoid this awkwardness, deprecate setActive() and replace it with an +explicit start() and stop() method that are clearly documented to be +purely requests, with the real active/inactive state matching the stream +state. + +This also makes the "Rendering" state more explicit, when "Stop" is +called we immediately switch to the "Rendering" state to indicate we may +still be processing frames but are no longer receiving new frames. +--- + src/pipewirebaseencodedstream.cpp | 111 +++++++++++++++++++----------- + src/pipewirebaseencodedstream.h | 40 ++++++++++- + src/pipewireproduce.cpp | 2 + + src/pipewireproduce_p.h | 2 + + src/pipewirerecord.cpp | 1 - + tests/HeadlessTest.cpp | 20 ++++-- + 6 files changed, 127 insertions(+), 49 deletions(-) + +diff --git a/src/pipewirebaseencodedstream.cpp b/src/pipewirebaseencodedstream.cpp +index 67c5445..27ef198 100644 +--- a/src/pipewirebaseencodedstream.cpp ++++ b/src/pipewirebaseencodedstream.cpp +@@ -17,6 +17,8 @@ extern "C" { + } + #include <unistd.h> + ++#include <QThread> ++ + #include "pipewireproduce_p.h" + #include "vaapiutils_p.h" + +@@ -29,6 +31,7 @@ struct PipeWireEncodedStreamPrivate { + PipeWireBaseEncodedStream::Encoder m_encoder; + std::optional<quint8> m_quality; + PipeWireBaseEncodedStream::EncodingPreference m_encodingPreference; ++ PipeWireBaseEncodedStream::State m_state = PipeWireBaseEncodedStream::Idle; + + std::unique_ptr<QThread> m_produceThread; + std::unique_ptr<PipeWireProduce> m_produce; +@@ -36,13 +39,7 @@ struct PipeWireEncodedStreamPrivate { + + PipeWireBaseEncodedStream::State PipeWireBaseEncodedStream::state() const + { +- if (isActive()) { +- return Recording; +- } else if (d->m_produceThread && d->m_produce->m_deactivated && d->m_produceThread->isRunning()) { +- return Rendering; +- } +- +- return Idle; ++ return d->m_state; + } + + PipeWireBaseEncodedStream::PipeWireBaseEncodedStream(QObject *parent) +@@ -65,10 +62,10 @@ PipeWireBaseEncodedStream::PipeWireBaseEncodedStream(QObject *parent) + + PipeWireBaseEncodedStream::~PipeWireBaseEncodedStream() + { +- setActive(false); ++ stop(); + +- if (d->m_fd) { +- close(*d->m_fd); ++ if (d->m_produceThread) { ++ d->m_produceThread->wait(); + } + } + +@@ -78,7 +75,6 @@ void PipeWireBaseEncodedStream::setNodeId(uint nodeId) + return; + + d->m_nodeId = nodeId; +- refresh(); + Q_EMIT nodeIdChanged(nodeId); + } + +@@ -91,7 +87,6 @@ void PipeWireBaseEncodedStream::setFd(uint fd) + close(*d->m_fd); + } + d->m_fd = fd; +- refresh(); + Q_EMIT fdChanged(fd); + } + +@@ -141,50 +136,84 @@ int PipeWireBaseEncodedStream::maxBufferSize() const + + void PipeWireBaseEncodedStream::setActive(bool active) + { +- if (d->m_active == active) +- return; ++ if (active) { ++ start(); ++ } else { ++ stop(); + +- d->m_active = active; +- refresh(); +- Q_EMIT activeChanged(active); ++ if (d->m_produceThread) { ++ d->m_produceThread->wait(); ++ } ++ } + } + +-std::optional<quint8> PipeWireBaseEncodedStream::quality() const ++void PipeWireBaseEncodedStream::start() + { +- return d->m_quality; +-} ++ if (d->m_nodeId == 0) { ++ qCWarning(PIPEWIRERECORD_LOGGING) << "Cannot start recording on a stream without a node ID"; ++ return; ++ } + +-void PipeWireBaseEncodedStream::setQuality(quint8 quality) +-{ +- d->m_quality = quality; +- if (d->m_produce) { +- d->m_produce->setQuality(d->m_quality); ++ if (d->m_produceThread || d->m_state != Idle) { ++ return; + } ++ ++ d->m_produceThread = std::make_unique<QThread>(); ++ d->m_produceThread->setObjectName("PipeWireProduce::input"); ++ d->m_produce = makeProduce(); ++ d->m_produce->setQuality(d->m_quality); ++ d->m_produce->setMaxPendingFrames(d->m_maxPendingFrames); ++ d->m_produce->setEncodingPreference(d->m_encodingPreference); ++ d->m_produce->moveToThread(d->m_produceThread.get()); ++ d->m_produceThread->start(); ++ QMetaObject::invokeMethod(d->m_produce.get(), &PipeWireProduce::initialize, Qt::QueuedConnection); ++ ++ connect(d->m_produce.get(), &PipeWireProduce::started, this, [this]() { ++ d->m_active = true; ++ Q_EMIT activeChanged(true); ++ d->m_state = Recording; ++ Q_EMIT stateChanged(); ++ }); ++ ++ connect(d->m_produce.get(), &PipeWireProduce::finished, this, [this]() { ++ d->m_active = false; ++ Q_EMIT activeChanged(false); ++ d->m_state = Idle; ++ Q_EMIT stateChanged(); ++ }); ++ ++ connect(d->m_produceThread.get(), &QThread::finished, this, [this]() { ++ d->m_produce.reset(); ++ d->m_produceThread.reset(); ++ d->m_nodeId = 0; ++ ++ if (d->m_fd) { ++ close(d->m_fd.value()); ++ } ++ }); + } + +-void PipeWireBaseEncodedStream::refresh() ++void PipeWireBaseEncodedStream::stop() + { + if (d->m_produceThread) { + QMetaObject::invokeMethod(d->m_produce.get(), &PipeWireProduce::deactivate, Qt::QueuedConnection); +- d->m_produceThread->wait(); +- +- d->m_produce.reset(); +- d->m_produceThread.reset(); + } + +- if (d->m_active && d->m_nodeId > 0) { +- d->m_produceThread = std::make_unique<QThread>(); +- d->m_produceThread->setObjectName("PipeWireProduce::input"); +- d->m_produce = makeProduce(); ++ d->m_state = PipeWireBaseEncodedStream::Rendering; ++ Q_EMIT stateChanged(); ++} ++ ++std::optional<quint8> PipeWireBaseEncodedStream::quality() const ++{ ++ return d->m_quality; ++} ++ ++void PipeWireBaseEncodedStream::setQuality(quint8 quality) ++{ ++ d->m_quality = quality; ++ if (d->m_produce) { + d->m_produce->setQuality(d->m_quality); +- d->m_produce->setMaxPendingFrames(d->m_maxPendingFrames); +- d->m_produce->setEncodingPreference(d->m_encodingPreference); +- d->m_produce->moveToThread(d->m_produceThread.get()); +- d->m_produceThread->start(); +- QMetaObject::invokeMethod(d->m_produce.get(), &PipeWireProduce::initialize, Qt::QueuedConnection); + } +- +- Q_EMIT stateChanged(); + } + + void PipeWireBaseEncodedStream::setEncoder(Encoder encoder) +diff --git a/src/pipewirebaseencodedstream.h b/src/pipewirebaseencodedstream.h +index 9f4c0fd..8728252 100644 +--- a/src/pipewirebaseencodedstream.h ++++ b/src/pipewirebaseencodedstream.h +@@ -25,7 +25,7 @@ class KPIPEWIRE_EXPORT PipeWireBaseEncodedStream : public QObject + * Transfers the ownership of the fd, will close it when it's done with it. + */ + Q_PROPERTY(uint fd READ fd WRITE setFd NOTIFY fdChanged) +- Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) ++ Q_PROPERTY(bool active READ isActive NOTIFY activeChanged) + Q_PROPERTY(State state READ state NOTIFY stateChanged) + Q_PROPERTY(Encoder encoder READ encoder WRITE setEncoder NOTIFY encoderChanged) + +@@ -67,7 +67,42 @@ public: + int maxBufferSize() const; + + bool isActive() const; +- void setActive(bool active); ++ /** ++ * Set the active state of recording. ++ * ++ * @deprecated Since 6.4, use the separate `start()`/`stop()`calls instead. ++ * This function now just calls `start()`/`stop()`. ++ * ++ * @note When calling `setActive(false)`, unlike `stop()`, this function will ++ * block until the internal encoding threads are finished. ++ */ ++ KPIPEWIRE_DEPRECATED void setActive(bool active); ++ ++ /** ++ * Request to start recording. ++ * ++ * This will create everything required to perform recording, like a PipeWire ++ * stream and an encoder, then start receiving frames from the stream and ++ * encoding those. ++ * ++ * This requires a valid node ID to be set and that the current state is Idle. ++ * ++ * Note that recording all happens on separate threads, this method only ++ * starts the process, only when state() returns Recording is recording ++ * actually happening. ++ */ ++ Q_INVOKABLE void start(); ++ /** ++ * Request to stop recording. ++ * ++ * This will terminate receiving frames from PipeWire and do any cleanup ++ * necessary to fully terminate recording after that. ++ * ++ * Note that after this request, there may still be some processing required ++ * due to internal queues. As long as state() does not return Idle processing ++ * is still happening and teardown has not been completed. ++ */ ++ Q_INVOKABLE void stop(); + + /** + * The quality used for encoding. +@@ -127,6 +162,5 @@ protected: + virtual std::unique_ptr<PipeWireProduce> makeProduce() = 0; + EncodingPreference encodingPreference(); + +- void refresh(); + QScopedPointer<PipeWireEncodedStreamPrivate> d; + }; +diff --git a/src/pipewireproduce.cpp b/src/pipewireproduce.cpp +index aa6acbb..e5b05cc 100644 +--- a/src/pipewireproduce.cpp ++++ b/src/pipewireproduce.cpp +@@ -201,6 +201,7 @@ void PipeWireProduce::setupStream() + if (!m_encoder || streamState != PW_STREAM_STATE_STREAMING) { + QMetaObject::invokeMethod(this, &PipeWireProduce::destroy, Qt::QueuedConnection); + } ++ Q_EMIT started(); + } + + void PipeWireProduce::destroy() +@@ -251,6 +252,7 @@ void PipeWireProduce::destroy() + + qCDebug(PIPEWIRERECORD_LOGGING) << "finished"; + cleanup(); ++ Q_EMIT finished(); + QThread::currentThread()->quit(); + } + +diff --git a/src/pipewireproduce_p.h b/src/pipewireproduce_p.h +index 71ca34b..7cc49df 100644 +--- a/src/pipewireproduce_p.h ++++ b/src/pipewireproduce_p.h +@@ -154,6 +154,8 @@ public: + + Q_SIGNALS: + void producedFrames(); ++ void started(); ++ void finished(); + + private: + void initFiltersVaapi(); +diff --git a/src/pipewirerecord.cpp b/src/pipewirerecord.cpp +index 7293b57..cff7ade 100644 +--- a/src/pipewirerecord.cpp ++++ b/src/pipewirerecord.cpp +@@ -69,7 +69,6 @@ void PipeWireRecord::setOutput(const QString &_output) + return; + + d->m_output = output; +- refresh(); + Q_EMIT outputChanged(output); + } + +diff --git a/tests/HeadlessTest.cpp b/tests/HeadlessTest.cpp +index 33db742..6d31f77 100644 +--- a/tests/HeadlessTest.cpp ++++ b/tests/HeadlessTest.cpp +@@ -55,16 +55,29 @@ void createStream(int nodeId, std::optional<int> fd = {}) + } + encoded->setEncoder(enc); + } +- encoded->setActive(true); ++ encoded->start(); + QObject::connect(encoded, &PipeWireEncodedStream::newPacket, qGuiApp, [](const PipeWireEncodedStream::Packet &packet) { + qDebug() << "packet received" << packet.data().size() << "key:" << packet.isKeyFrame(); + }); + QObject::connect(encoded, &PipeWireEncodedStream::cursorChanged, qGuiApp, [](const PipeWireCursor &cursor) { + qDebug() << "cursor received. position:" << cursor.position << "hotspot:" << cursor.hotspot << "image:" << cursor.texture; + }); ++ QObject::connect(encoded, &PipeWireEncodedStream::stateChanged, qGuiApp, [encoded]() { ++ switch (encoded->state()) { ++ case PipeWireEncodedStream::Recording: ++ qDebug() << "Started recording"; ++ break; ++ case PipeWireEncodedStream::Rendering: ++ qDebug() << "Stopped recording, flushing remaining frames"; ++ break; ++ case PipeWireEncodedStream::Idle: ++ qDebug() << "Recording finished, quitting"; ++ exit(0); ++ break; ++ } ++ }); + QObject::connect(KSignalHandler::self(), &KSignalHandler::signalReceived, encoded, [encoded] { +- encoded->setActive(false); +- exit(0); ++ encoded->stop(); + }); + return; + } +@@ -96,7 +109,6 @@ void createStream(int nodeId, std::optional<int> fd = {}) + }); + QObject::connect(KSignalHandler::self(), &KSignalHandler::signalReceived, pwStream, [pwStream] { + pwStream->setActive(false); +- exit(0); + }); + } + +-- +GitLab + diff -Nru kpipewire-6.3.4/debian/patches/upstream_123ae0d2_Tweak-encoding-options-for-VP9.patch kpipewire-6.3.5/debian/patches/upstream_123ae0d2_Tweak-encoding-options-for-VP9.patch --- kpipewire-6.3.4/debian/patches/upstream_123ae0d2_Tweak-encoding-options-for-VP9.patch 1970-01-01 01:00:00.000000000 +0100 +++ kpipewire-6.3.5/debian/patches/upstream_123ae0d2_Tweak-encoding-options-for-VP9.patch 2025-05-19 00:58:37.000000000 +0200 @@ -0,0 +1,58 @@ +From 123ae0d2e77758583301e91e9d2b94cec124376e Mon Sep 17 00:00:00 2001 +From: Arjen Hiemstra <ahiems...@heimr.nl> +Date: Thu, 20 Mar 2025 14:31:24 +0100 +Subject: [PATCH] Tweak encoding options for VP9 + +Don't set both bitrate and CRF, as they are conflicting settings. +Instead only set CRF. Also enable row-mt and avoid modifying the codec +context in a function that is about options. +--- + src/libvpxvp9encoder.cpp | 18 ++++-------------- + 1 file changed, 4 insertions(+), 14 deletions(-) + +diff --git a/src/libvpxvp9encoder.cpp b/src/libvpxvp9encoder.cpp +index d877023..a9220f4 100644 +--- a/src/libvpxvp9encoder.cpp ++++ b/src/libvpxvp9encoder.cpp +@@ -60,16 +60,6 @@ bool LibVpxVp9Encoder::initialize(const QSize &size) + + m_avCodecContext->gop_size = fps * 2; + +- // TODO: Make bitrate depend on the framerate? More frames is more data. +- // maxFramerate can apparently be changed while recording, so keep that in mind. +- m_avCodecContext->bit_rate = std::round(area * 2); +- m_avCodecContext->rc_min_rate = std::round(area); +- m_avCodecContext->rc_max_rate = std::round(area * 3); +- +- m_avCodecContext->rc_buffer_size = m_avCodecContext->bit_rate; +- +- m_avCodecContext->thread_count = QThread::idealThreadCount(); +- + if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) { + qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result); + return false; +@@ -100,8 +90,9 @@ AVDictionary *LibVpxVp9Encoder::buildEncodingOptions() + if (m_quality) { + crf = percentageToAbsoluteQuality(m_quality); + } +- m_avCodecContext->qmin = std::clamp(crf / 2, 0, crf); +- m_avCodecContext->qmax = std::clamp(qRound(crf * 1.5), crf, 63); ++ ++ av_dict_set_int(&options, "qmin", std::clamp(crf / 2, 0, crf), 0); ++ av_dict_set_int(&options, "qmax", std::clamp(int(crf * 1.5), crf, 63), 0); + av_dict_set_int(&options, "crf", crf, 0); + + // 0-4 are for Video-On-Demand with the good or best deadline. +@@ -117,8 +108,7 @@ AVDictionary *LibVpxVp9Encoder::buildEncodingOptions() + av_dict_set(&options, "tile-columns", "6", 0); + av_dict_set(&options, "tile-rows", "2", 0); + +- // This should make things faster, but it only seems to consume 100MB more RAM. +- // av_dict_set(&options, "row-mt", "1", 0); ++ av_dict_set(&options, "row-mt", "1", 0); + av_dict_set(&options, "frame-parallel", "1", 0); + + return options; +-- +GitLab + diff -Nru kpipewire-6.3.4/debian/patches/upstream_52911b70_Change-Encoder-applyEncodingPreference-to-buildEncodingOptions-.patch kpipewire-6.3.5/debian/patches/upstream_52911b70_Change-Encoder-applyEncodingPreference-to-buildEncodingOptions-.patch --- kpipewire-6.3.4/debian/patches/upstream_52911b70_Change-Encoder-applyEncodingPreference-to-buildEncodingOptions-.patch 1970-01-01 01:00:00.000000000 +0100 +++ kpipewire-6.3.5/debian/patches/upstream_52911b70_Change-Encoder-applyEncodingPreference-to-buildEncodingOptions-.patch 2025-05-19 00:58:37.000000000 +0200 @@ -0,0 +1,351 @@ +From 52911b7060fc3341c4ab4b308be1e47f985e8576 Mon Sep 17 00:00:00 2001 +From: Arjen Hiemstra <ahiems...@heimr.nl> +Date: Thu, 20 Mar 2025 14:26:36 +0100 +Subject: [PATCH] Change Encoder::applyEncodingPreference() to + buildEncodingOptions() + +As it turns out, FFmpeg does something to the pointers here that causes +the dictionary to never be properly used. This means we were never +applying the encoding options, as avcodec_open() was passed a nullptr +for options. + +Fix this by changing the function to return an AVDictionary* instead of +trying to modify a passed-in pointer. This results in a proper dict +being returned, that can then be passed to avcodec_open(). + +The main result of this is that we now properly apply the encoding +options for VP9 encoding, which means we can now encode VP9 at realtime +speeds instead of it massively lagging behind. + +BUG: 488896 +--- + src/encoder.cpp | 6 +++++- + src/encoder_p.h | 2 +- + src/gifencoder.cpp | 7 ------- + src/gifencoder_p.h | 1 - + src/h264vaapiencoder.cpp | 10 +++++----- + src/h264vaapiencoder_p.h | 2 +- + src/libopenh264encoder.cpp | 10 +++++----- + src/libopenh264encoder_p.h | 2 +- + src/libvpxencoder.cpp | 10 ++++++---- + src/libvpxencoder_p.h | 2 +- + src/libvpxvp9encoder.cpp | 10 ++++++---- + src/libvpxvp9encoder_p.h | 2 +- + src/libwebpencoder_p.h | 1 - + src/libx264encoder.cpp | 11 ++++++----- + src/libx264encoder_p.h | 2 +- + 15 files changed, 39 insertions(+), 39 deletions(-) + +diff --git a/src/encoder.cpp b/src/encoder.cpp +index 41e6ac58..33617850 100644 +--- a/src/encoder.cpp ++++ b/src/encoder.cpp +@@ -185,8 +185,10 @@ void Encoder::setEncodingPreference(PipeWireBaseEncodedStream::EncodingPreferenc + m_encodingPreference = preference; + } + +-void Encoder::applyEncodingPreference(AVDictionary *options) ++AVDictionary *Encoder::buildEncodingOptions() + { ++ AVDictionary *options = NULL; ++ + switch (m_encodingPreference) { + case PipeWireBaseEncodedStream::EncodingPreference::NoPreference: + av_dict_set(&options, "preset", "veryfast", 0); +@@ -205,6 +207,8 @@ void Encoder::applyEncodingPreference(AVDictionary *options) + av_dict_set(&options, "preset", "veryfast", 0); + break; + } ++ ++ return options; + } + + SoftwareEncoder::SoftwareEncoder(PipeWireProduce *produce) +diff --git a/src/encoder_p.h b/src/encoder_p.h +index 1acd2548..48d3a9ea 100644 +--- a/src/encoder_p.h ++++ b/src/encoder_p.h +@@ -102,6 +102,7 @@ public: + + protected: + virtual int percentageToAbsoluteQuality(const std::optional<quint8> &quality) = 0; ++ virtual AVDictionary *buildEncodingOptions(); + + PipeWireProduce *m_produce; + +@@ -114,7 +115,6 @@ protected: + + std::optional<quint8> m_quality; + PipeWireBaseEncodedStream::EncodingPreference m_encodingPreference; +- virtual void applyEncodingPreference(AVDictionary *options); + }; + + /** +diff --git a/src/gifencoder.cpp b/src/gifencoder.cpp +index 4e24dea4..e2d9802b 100644 +--- a/src/gifencoder.cpp ++++ b/src/gifencoder.cpp +@@ -54,9 +54,6 @@ bool GifEncoder::initialize(const QSize &size) + m_avCodecContext->time_base = AVRational{1, 1000}; + + AVDictionary *options = nullptr; +- +- applyEncodingPreference(options); +- + if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) { + qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result); + return false; +@@ -79,7 +76,3 @@ int GifEncoder::percentageToAbsoluteQuality([[maybe_unused]] const std::optional + { + return -1; // Not possible to set quality + } +- +-void GifEncoder::applyEncodingPreference([[maybe_unused]] AVDictionary *options) +-{ +-} +diff --git a/src/gifencoder_p.h b/src/gifencoder_p.h +index 9eceb0f2..5e2c0568 100644 +--- a/src/gifencoder_p.h ++++ b/src/gifencoder_p.h +@@ -18,5 +18,4 @@ public: + + protected: + int percentageToAbsoluteQuality(const std::optional<quint8> &quality) override; +- void applyEncodingPreference(AVDictionary *options) override; + }; +diff --git a/src/h264vaapiencoder.cpp b/src/h264vaapiencoder.cpp +index cf315f3c..26e7fba2 100644 +--- a/src/h264vaapiencoder.cpp ++++ b/src/h264vaapiencoder.cpp +@@ -140,9 +140,7 @@ bool H264VAAPIEncoder::initialize(const QSize &size) + break; + } + +- AVDictionary *options = nullptr; +- // av_dict_set_int(&options, "threads", qMin(16, QThread::idealThreadCount()), 0); +- applyEncodingPreference(options); ++ AVDictionary *options = buildEncodingOptions(); + + // Assign the right hardware context for encoding frames. + // We rely on FFmpeg for creating the VAAPI hardware context as part of +@@ -168,11 +166,13 @@ int H264VAAPIEncoder::percentageToAbsoluteQuality(const std::optional<quint8> &q + return std::max(1, int(MinQuality - (m_quality.value() / 100.0) * MinQuality)); + } + +-void H264VAAPIEncoder::applyEncodingPreference(AVDictionary *options) ++AVDictionary *H264VAAPIEncoder::buildEncodingOptions() + { +- HardwareEncoder::applyEncodingPreference(options); ++ AVDictionary *options = HardwareEncoder::buildEncodingOptions(); + // Disable motion estimation, not great while dragging windows but speeds up encoding by an order of magnitude + av_dict_set(&options, "flags", "+mv4", 0); + // Disable in-loop filtering + av_dict_set(&options, "-flags", "+loop", 0); ++ ++ return options; + } +diff --git a/src/h264vaapiencoder_p.h b/src/h264vaapiencoder_p.h +index 9a226508..3b02b335 100644 +--- a/src/h264vaapiencoder_p.h ++++ b/src/h264vaapiencoder_p.h +@@ -20,7 +20,7 @@ public: + + protected: + int percentageToAbsoluteQuality(const std::optional<quint8> &quality) override; +- void applyEncodingPreference(AVDictionary *options) override; ++ AVDictionary *buildEncodingOptions() override; + + private: + H264Profile m_profile = H264Profile::Main; +diff --git a/src/libopenh264encoder.cpp b/src/libopenh264encoder.cpp +index 6d4c6a18..7f374d25 100644 +--- a/src/libopenh264encoder.cpp ++++ b/src/libopenh264encoder.cpp +@@ -74,9 +74,7 @@ bool LibOpenH264Encoder::initialize(const QSize &size) + break; + } + +- AVDictionary *options = nullptr; +- av_dict_set_int(&options, "threads", qMin(16, QThread::idealThreadCount()), 0); +- applyEncodingPreference(options); ++ AVDictionary *options = buildEncodingOptions(); + + if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) { + qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result); +@@ -96,11 +94,13 @@ int LibOpenH264Encoder::percentageToAbsoluteQuality(const std::optional<quint8> + return 51 - (m_quality.value() / 100.0) * 50; + } + +-void LibOpenH264Encoder::applyEncodingPreference(AVDictionary *options) ++AVDictionary *LibOpenH264Encoder::buildEncodingOptions() + { +- SoftwareEncoder::applyEncodingPreference(options); ++ AVDictionary *options = SoftwareEncoder::buildEncodingOptions(); + // Disable motion estimation, not great while dragging windows but speeds up encoding by an order of magnitude + av_dict_set(&options, "flags", "+mv4", 0); + // Disable in-loop filtering + av_dict_set_int(&options, "loopfilter", 0, 0); ++ ++ return options; + } +diff --git a/src/libopenh264encoder_p.h b/src/libopenh264encoder_p.h +index fdacf147..64fb8848 100644 +--- a/src/libopenh264encoder_p.h ++++ b/src/libopenh264encoder_p.h +@@ -21,7 +21,7 @@ public: + + protected: + int percentageToAbsoluteQuality(const std::optional<quint8> &quality) override; +- void applyEncodingPreference(AVDictionary *options) override; ++ AVDictionary *buildEncodingOptions() override; + + private: + H264Profile m_profile = H264Profile::Main; +diff --git a/src/libvpxencoder.cpp b/src/libvpxencoder.cpp +index d0cc9ea7..2d696d6e 100644 +--- a/src/libvpxencoder.cpp ++++ b/src/libvpxencoder.cpp +@@ -57,8 +57,7 @@ bool LibVpxEncoder::initialize(const QSize &size) + m_avCodecContext->global_quality = 35; + } + +- AVDictionary *options = nullptr; +- applyEncodingPreference(options); ++ AVDictionary *options = buildEncodingOptions(); + + if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) { + qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result); +@@ -78,9 +77,10 @@ int LibVpxEncoder::percentageToAbsoluteQuality(const std::optional<quint8> &qual + return std::max(1, int(MinQuality - (m_quality.value() / 100.0) * MinQuality)); + } + +-void LibVpxEncoder::applyEncodingPreference(AVDictionary *options) ++AVDictionary *LibVpxEncoder::buildEncodingOptions() + { +- av_dict_set_int(&options, "threads", qMin(16, QThread::idealThreadCount()), 0); ++ AVDictionary *options = SoftwareEncoder::buildEncodingOptions(); ++ + av_dict_set(&options, "preset", "veryfast", 0); + av_dict_set(&options, "tune-content", "screen", 0); + av_dict_set(&options, "deadline", "realtime", 0); +@@ -91,4 +91,6 @@ void LibVpxEncoder::applyEncodingPreference(AVDictionary *options) + // Disable in-loop filtering + av_dict_set(&options, "-flags", "+loop", 0); + av_dict_set(&options, "crf", "45", 0); ++ ++ return options; + } +diff --git a/src/libvpxencoder_p.h b/src/libvpxencoder_p.h +index 22fcae87..419117ae 100644 +--- a/src/libvpxencoder_p.h ++++ b/src/libvpxencoder_p.h +@@ -20,5 +20,5 @@ public: + + protected: + int percentageToAbsoluteQuality(const std::optional<quint8> &quality) override; +- void applyEncodingPreference(AVDictionary *options) override; ++ AVDictionary *buildEncodingOptions() override; + }; +diff --git a/src/libvpxvp9encoder.cpp b/src/libvpxvp9encoder.cpp +index d3ce94b0..0b630155 100644 +--- a/src/libvpxvp9encoder.cpp ++++ b/src/libvpxvp9encoder.cpp +@@ -50,9 +50,7 @@ bool LibVpxVp9Encoder::initialize(const QSize &size) + m_avCodecContext->pix_fmt = AV_PIX_FMT_YUV420P; + m_avCodecContext->time_base = AVRational{1, 1000}; + +- AVDictionary *options = nullptr; +- +- applyEncodingPreference(options); ++ AVDictionary *options = buildEncodingOptions(); + + const auto area = size.width() * size.height(); + // m_avCodecContext->framerate is not set, so we use m_produce->maxFramerate() instead. +@@ -89,8 +87,10 @@ int LibVpxVp9Encoder::percentageToAbsoluteQuality(const std::optional<quint8> &q + return std::max(1, int(MinQuality - (m_quality.value() / 100.0) * MinQuality)); + } + +-void LibVpxVp9Encoder::applyEncodingPreference(AVDictionary *options) ++AVDictionary *LibVpxVp9Encoder::buildEncodingOptions() + { ++ AVDictionary *options = SoftwareEncoder::buildEncodingOptions(); ++ + // We're probably capturing a screen + av_dict_set(&options, "tune-content", "screen", 0); + +@@ -119,4 +119,6 @@ void LibVpxVp9Encoder::applyEncodingPreference(AVDictionary *options) + // This should make things faster, but it only seems to consume 100MB more RAM. + // av_dict_set(&options, "row-mt", "1", 0); + av_dict_set(&options, "frame-parallel", "1", 0); ++ ++ return options; + } +diff --git a/src/libvpxvp9encoder_p.h b/src/libvpxvp9encoder_p.h +index c2008273..863fda2d 100644 +--- a/src/libvpxvp9encoder_p.h ++++ b/src/libvpxvp9encoder_p.h +@@ -21,5 +21,5 @@ public: + + protected: + int percentageToAbsoluteQuality(const std::optional<quint8> &quality) override; +- void applyEncodingPreference(AVDictionary *options) override; ++ AVDictionary *buildEncodingOptions() override; + }; +diff --git a/src/libwebpencoder_p.h b/src/libwebpencoder_p.h +index a6d5782a..e4bfd125 100644 +--- a/src/libwebpencoder_p.h ++++ b/src/libwebpencoder_p.h +@@ -17,5 +17,4 @@ public: + + protected: + int percentageToAbsoluteQuality(const std::optional<quint8> &quality) override; +- void applyEncodingPreference(AVDictionary *options) override; + }; +diff --git a/src/libx264encoder.cpp b/src/libx264encoder.cpp +index 91011645..7d4f96b2 100644 +--- a/src/libx264encoder.cpp ++++ b/src/libx264encoder.cpp +@@ -78,9 +78,7 @@ bool LibX264Encoder::initialize(const QSize &size) + break; + } + +- AVDictionary *options = nullptr; +- av_dict_set_int(&options, "threads", qMin(16, QThread::idealThreadCount()), 0); +- applyEncodingPreference(options); ++ AVDictionary *options = buildEncodingOptions(); + + if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) { + qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result); +@@ -100,11 +98,14 @@ int LibX264Encoder::percentageToAbsoluteQuality(const std::optional<quint8> &qua + return std::max(1, int(MinQuality - (m_quality.value() / 100.0) * MinQuality)); + } + +-void LibX264Encoder::applyEncodingPreference(AVDictionary *options) ++AVDictionary *LibX264Encoder::buildEncodingOptions() + { +- SoftwareEncoder::applyEncodingPreference(options); ++ AVDictionary *options = SoftwareEncoder::buildEncodingOptions(); ++ + // Disable motion estimation, not great while dragging windows but speeds up encoding by an order of magnitude + av_dict_set(&options, "flags", "+mv4", 0); + // Disable in-loop filtering + av_dict_set(&options, "-flags", "+loop", 0); ++ ++ return options; + } +diff --git a/src/libx264encoder_p.h b/src/libx264encoder_p.h +index c8b877c9..0a800758 100644 +--- a/src/libx264encoder_p.h ++++ b/src/libx264encoder_p.h +@@ -20,7 +20,7 @@ public: + + protected: + int percentageToAbsoluteQuality(const std::optional<quint8> &quality) override; +- void applyEncodingPreference(AVDictionary *options) override; ++ AVDictionary *buildEncodingOptions() override; + + private: + H264Profile m_profile = H264Profile::Main; +-- +GitLab + diff -Nru kpipewire-6.3.4/debian/patches/upstream_5a223fe4_Port-Encoder-away-from-deprecated-avcodec-close.patch kpipewire-6.3.5/debian/patches/upstream_5a223fe4_Port-Encoder-away-from-deprecated-avcodec-close.patch --- kpipewire-6.3.4/debian/patches/upstream_5a223fe4_Port-Encoder-away-from-deprecated-avcodec-close.patch 1970-01-01 01:00:00.000000000 +0100 +++ kpipewire-6.3.5/debian/patches/upstream_5a223fe4_Port-Encoder-away-from-deprecated-avcodec-close.patch 2025-05-19 00:58:37.000000000 +0200 @@ -0,0 +1,26 @@ +From 5a223fe4e1489574fba28dcf65c8a4aa1387e0e0 Mon Sep 17 00:00:00 2001 +From: Arjen Hiemstra <ahiems...@heimr.nl> +Date: Thu, 20 Mar 2025 14:28:54 +0100 +Subject: [PATCH] Port Encoder away from deprecated avcodec_close + +--- + src/encoder.cpp | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/encoder.cpp b/src/encoder.cpp +index 874ac08..7aa1738 100644 +--- a/src/encoder.cpp ++++ b/src/encoder.cpp +@@ -73,8 +73,7 @@ Encoder::~Encoder() + } + + if (m_avCodecContext) { +- avcodec_close(m_avCodecContext); +- av_free(m_avCodecContext); ++ avcodec_free_context(&m_avCodecContext); + } + } + +-- +GitLab + diff -Nru kpipewire-6.3.4/debian/patches/upstream_686df1e3_Tweak-compiler-warning-flags-to-reduce-unneeded-output.patch kpipewire-6.3.5/debian/patches/upstream_686df1e3_Tweak-compiler-warning-flags-to-reduce-unneeded-output.patch --- kpipewire-6.3.4/debian/patches/upstream_686df1e3_Tweak-compiler-warning-flags-to-reduce-unneeded-output.patch 1970-01-01 01:00:00.000000000 +0100 +++ kpipewire-6.3.5/debian/patches/upstream_686df1e3_Tweak-compiler-warning-flags-to-reduce-unneeded-output.patch 2025-05-19 00:58:37.000000000 +0200 @@ -0,0 +1,54 @@ +From 686df1e3fb6a740281413ae0633003f8ffabcf6b Mon Sep 17 00:00:00 2001 +From: Arjen Hiemstra <ahiems...@heimr.nl> +Date: Thu, 20 Mar 2025 14:19:21 +0100 +Subject: [PATCH] Tweak compiler warning flags to reduce unneeded output + +-Wno-gnu-statement-expression-from-macro-expansion and +-Wno-c99-extensions are non-existent options that add more noise than +they fix. Additionally, -Wpedantic is enabled by default which causes a +lot of noise, so disable that. Finally, add +-Wno-missing-field-initializers to quiet down the final bits of PipeWire +API. +--- + src/CMakeLists.txt | 2 +- + src/libwebpencoder.cpp | 7 ------- + 2 files changed, 1 insertion(+), 8 deletions(-) + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index bf53693..05c06f0 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -73,7 +73,7 @@ target_sources(KPipeWire PRIVATE + ) + + # these are features pipewire use extensively and make it hard to look at compile logs +-target_compile_options(KPipeWire PUBLIC -Wno-gnu-statement-expression-from-macro-expansion -Wno-zero-as-null-pointer-constant -Wno-c99-extensions -Wno-cast-align) ++target_compile_options(KPipeWire PUBLIC -Wno-zero-as-null-pointer-constant -Wno-missing-field-initializers -Wno-cast-align -Wno-pedantic) + + target_link_libraries(KPipeWire PRIVATE Qt::Quick Qt::GuiPrivate KF6::I18n + KF6::CoreAddons PkgConfig::PipeWire epoxy::epoxy PkgConfig::GBM Libdrm::Libdrm PkgConfig::LIBVA PkgConfig::LIBVA-drm) +diff --git a/src/libwebpencoder.cpp b/src/libwebpencoder.cpp +index 0006441..c62cecb 100644 +--- a/src/libwebpencoder.cpp ++++ b/src/libwebpencoder.cpp +@@ -51,9 +51,6 @@ bool LibWebPEncoder::initialize(const QSize &size) + m_avCodecContext->time_base = AVRational{1, 1000}; + + AVDictionary *options = nullptr; +- +- applyEncodingPreference(options); +- + if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) { + qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result); + return false; +@@ -66,7 +63,3 @@ int LibWebPEncoder::percentageToAbsoluteQuality(const std::optional<quint8> &qua + { + return quality.value_or(-1); // Already 0-100. -1 resets to default. + } +- +-void LibWebPEncoder::applyEncodingPreference([[maybe_unused]] AVDictionary *options) +-{ +-} +-- +GitLab + diff -Nru kpipewire-6.3.4/debian/patches/upstream_8793ae86_encodedstream-Don-t-query-VAAPI-in-the-constructor.patch kpipewire-6.3.5/debian/patches/upstream_8793ae86_encodedstream-Don-t-query-VAAPI-in-the-constructor.patch --- kpipewire-6.3.4/debian/patches/upstream_8793ae86_encodedstream-Don-t-query-VAAPI-in-the-constructor.patch 1970-01-01 01:00:00.000000000 +0100 +++ kpipewire-6.3.5/debian/patches/upstream_8793ae86_encodedstream-Don-t-query-VAAPI-in-the-constructor.patch 2025-05-19 00:58:37.000000000 +0200 @@ -0,0 +1,49 @@ +From 8793ae866692dcc26faa4271e1dd3588a97d14aa Mon Sep 17 00:00:00 2001 +From: Arjen Hiemstra <ahiems...@heimr.nl> +Date: Tue, 8 Oct 2024 14:20:55 +0200 +Subject: [PATCH] encodedstream: Don't query VAAPI in the constructor + +Querying VAAPI is expensive, so we should only do that when necessary. +So rather than querying what encoder to use on construction, query it on +start and only if we don't already have an encoder set. This also avoids +duplicate lookups if the user already set the encoder. +--- + src/pipewirebaseencodedstream.cpp | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/pipewirebaseencodedstream.cpp b/src/pipewirebaseencodedstream.cpp +index 27ef198..de51a90 100644 +--- a/src/pipewirebaseencodedstream.cpp ++++ b/src/pipewirebaseencodedstream.cpp +@@ -28,7 +28,7 @@ struct PipeWireEncodedStreamPrivate { + Fraction m_maxFramerate; + int m_maxPendingFrames = 50; + bool m_active = false; +- PipeWireBaseEncodedStream::Encoder m_encoder; ++ PipeWireBaseEncodedStream::Encoder m_encoder = PipeWireBaseEncodedStream::NoEncoder; + std::optional<quint8> m_quality; + PipeWireBaseEncodedStream::EncodingPreference m_encodingPreference; + PipeWireBaseEncodedStream::State m_state = PipeWireBaseEncodedStream::Idle; +@@ -46,8 +46,6 @@ PipeWireBaseEncodedStream::PipeWireBaseEncodedStream(QObject *parent) + : QObject(parent) + , d(new PipeWireEncodedStreamPrivate) + { +- d->m_encoder = suggestedEncoders().value(0, NoEncoder); +- + const auto &category = PIPEWIRELIBAV_LOGGING(); + if (category.isDebugEnabled()) { + av_log_set_level(AV_LOG_DEBUG); +@@ -158,6 +156,10 @@ void PipeWireBaseEncodedStream::start() + return; + } + ++ if (d->m_encoder == PipeWireBaseEncodedStream::NoEncoder) { ++ d->m_encoder = suggestedEncoders().value(0, NoEncoder); ++ } ++ + d->m_produceThread = std::make_unique<QThread>(); + d->m_produceThread->setObjectName("PipeWireProduce::input"); + d->m_produce = makeProduce(); +-- +GitLab + diff -Nru kpipewire-6.3.4/debian/patches/upstream_c928ed5c_Add-logging-of-encoding-options-if-log-level-is-set-to-info.patch kpipewire-6.3.5/debian/patches/upstream_c928ed5c_Add-logging-of-encoding-options-if-log-level-is-set-to-info.patch --- kpipewire-6.3.4/debian/patches/upstream_c928ed5c_Add-logging-of-encoding-options-if-log-level-is-set-to-info.patch 1970-01-01 01:00:00.000000000 +0100 +++ kpipewire-6.3.5/debian/patches/upstream_c928ed5c_Add-logging-of-encoding-options-if-log-level-is-set-to-info.patch 2025-05-19 00:58:37.000000000 +0200 @@ -0,0 +1,112 @@ +From c928ed5ce37f08ead06ab1ae2d74cf1b67a42538 Mon Sep 17 00:00:00 2001 +From: Arjen Hiemstra <ahiems...@heimr.nl> +Date: Thu, 20 Mar 2025 14:27:41 +0100 +Subject: [PATCH] Add logging of encoding options if log level is set to info + +Allows inspecting what's actually sent to FFmpeg. +--- + src/encoder.cpp | 10 ++++++++++ + src/encoder_p.h | 1 + + src/h264vaapiencoder.cpp | 1 + + src/libopenh264encoder.cpp | 1 + + src/libvpxencoder.cpp | 1 + + src/libvpxvp9encoder.cpp | 1 + + src/libx264encoder.cpp | 1 + + 7 files changed, 16 insertions(+) + +diff --git a/src/encoder.cpp b/src/encoder.cpp +index 3361785..f8b3d67 100644 +--- a/src/encoder.cpp ++++ b/src/encoder.cpp +@@ -211,6 +211,16 @@ AVDictionary *Encoder::buildEncodingOptions() + return options; + } + ++void Encoder::maybeLogOptions(AVDictionary *options) ++{ ++ if (PIPEWIRERECORD_LOGGING().isInfoEnabled()) { ++ char *buffer = NULL; ++ av_dict_get_string(options, &buffer, '=', ','); ++ qCInfo(PIPEWIRERECORD_LOGGING) << "Using encoding options:" << buffer; ++ av_freep(&buffer); ++ } ++} ++ + SoftwareEncoder::SoftwareEncoder(PipeWireProduce *produce) + : Encoder(produce) + { +diff --git a/src/encoder_p.h b/src/encoder_p.h +index 48d3a9e..e565cc2 100644 +--- a/src/encoder_p.h ++++ b/src/encoder_p.h +@@ -103,6 +103,7 @@ public: + protected: + virtual int percentageToAbsoluteQuality(const std::optional<quint8> &quality) = 0; + virtual AVDictionary *buildEncodingOptions(); ++ void maybeLogOptions(AVDictionary *options); + + PipeWireProduce *m_produce; + +diff --git a/src/h264vaapiencoder.cpp b/src/h264vaapiencoder.cpp +index 26e7fba..0cf251b 100644 +--- a/src/h264vaapiencoder.cpp ++++ b/src/h264vaapiencoder.cpp +@@ -141,6 +141,7 @@ bool H264VAAPIEncoder::initialize(const QSize &size) + } + + AVDictionary *options = buildEncodingOptions(); ++ maybeLogOptions(options); + + // Assign the right hardware context for encoding frames. + // We rely on FFmpeg for creating the VAAPI hardware context as part of +diff --git a/src/libopenh264encoder.cpp b/src/libopenh264encoder.cpp +index 7f374d2..db6ed4d 100644 +--- a/src/libopenh264encoder.cpp ++++ b/src/libopenh264encoder.cpp +@@ -75,6 +75,7 @@ bool LibOpenH264Encoder::initialize(const QSize &size) + } + + AVDictionary *options = buildEncodingOptions(); ++ maybeLogOptions(options); + + if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) { + qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result); +diff --git a/src/libvpxencoder.cpp b/src/libvpxencoder.cpp +index 2d696d6..f81b048 100644 +--- a/src/libvpxencoder.cpp ++++ b/src/libvpxencoder.cpp +@@ -58,6 +58,7 @@ bool LibVpxEncoder::initialize(const QSize &size) + } + + AVDictionary *options = buildEncodingOptions(); ++ maybeLogOptions(options); + + if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) { + qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result); +diff --git a/src/libvpxvp9encoder.cpp b/src/libvpxvp9encoder.cpp +index 0b63015..d877023 100644 +--- a/src/libvpxvp9encoder.cpp ++++ b/src/libvpxvp9encoder.cpp +@@ -51,6 +51,7 @@ bool LibVpxVp9Encoder::initialize(const QSize &size) + m_avCodecContext->time_base = AVRational{1, 1000}; + + AVDictionary *options = buildEncodingOptions(); ++ maybeLogOptions(options); + + const auto area = size.width() * size.height(); + // m_avCodecContext->framerate is not set, so we use m_produce->maxFramerate() instead. +diff --git a/src/libx264encoder.cpp b/src/libx264encoder.cpp +index 7d4f96b..d9fe44f 100644 +--- a/src/libx264encoder.cpp ++++ b/src/libx264encoder.cpp +@@ -79,6 +79,7 @@ bool LibX264Encoder::initialize(const QSize &size) + } + + AVDictionary *options = buildEncodingOptions(); ++ maybeLogOptions(options); + + if (int result = avcodec_open2(m_avCodecContext, codec, &options); result < 0) { + qCWarning(PIPEWIRERECORD_LOGGING) << "Could not open codec" << av_err2str(result); +-- +GitLab + diff -Nru kpipewire-6.3.4/debian/patches/upstream_f127a2cc_Set-threads-option-by-default-in-Encoder.patch kpipewire-6.3.5/debian/patches/upstream_f127a2cc_Set-threads-option-by-default-in-Encoder.patch --- kpipewire-6.3.4/debian/patches/upstream_f127a2cc_Set-threads-option-by-default-in-Encoder.patch 1970-01-01 01:00:00.000000000 +0100 +++ kpipewire-6.3.5/debian/patches/upstream_f127a2cc_Set-threads-option-by-default-in-Encoder.patch 2025-05-19 00:58:37.000000000 +0200 @@ -0,0 +1,26 @@ +From f127a2cce7f34bfe213754b8756fb96e983f7d0b Mon Sep 17 00:00:00 2001 +From: Arjen Hiemstra <ahiems...@heimr.nl> +Date: Thu, 20 Mar 2025 14:28:29 +0100 +Subject: [PATCH] Set "threads" option by default in Encoder + +So we don't have to repeat this in other encoders. +--- + src/encoder.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/encoder.cpp b/src/encoder.cpp +index f8b3d67..874ac08 100644 +--- a/src/encoder.cpp ++++ b/src/encoder.cpp +@@ -189,6 +189,8 @@ AVDictionary *Encoder::buildEncodingOptions() + { + AVDictionary *options = NULL; + ++ av_dict_set_int(&options, "threads", qMin(16, QThread::idealThreadCount()), 0); ++ + switch (m_encodingPreference) { + case PipeWireBaseEncodedStream::EncodingPreference::NoPreference: + av_dict_set(&options, "preset", "veryfast", 0); +-- +GitLab + diff -Nru kpipewire-6.3.4/po/ru/kpipewire6.po kpipewire-6.3.5/po/ru/kpipewire6.po --- kpipewire-6.3.4/po/ru/kpipewire6.po 2025-04-02 05:36:16.000000000 +0200 +++ kpipewire-6.3.5/po/ru/kpipewire6.po 2025-05-06 19:56:52.000000000 +0200 @@ -1,13 +1,13 @@ -# Copyright (C) YEAR This file is copyright: +# Copyright (C) 2025 This file is copyright: # This file is distributed under the same license as the kpipewire package. # -# Olesya Gerasimenko <translation-t...@basealt.ru>, 2022. +# SPDX-FileCopyrightText: 2022, 2025 Olesya Gerasimenko <translation-t...@basealt.ru> msgid "" msgstr "" "Project-Id-Version: kpipewire\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2024-10-18 00:41+0000\n" -"PO-Revision-Date: 2022-10-31 15:53+0300\n" +"PO-Revision-Date: 2025-04-07 11:56+0300\n" "Last-Translator: Olesya Gerasimenko <translation-t...@basealt.ru>\n" "Language-Team: Basealt Translation Team\n" "Language: ru\n" @@ -16,7 +16,7 @@ "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" "%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Lokalize 22.04.3\n" +"X-Generator: Lokalize 23.08.5\n" #: pipewirecore.cpp:90 #, kde-format @@ -24,6 +24,8 @@ "Invalid PipeWire installation. See https://gitlab.freedesktop.org/pipewire/" "pipewire/-/issues/3296 for more details." msgstr "" +"Некорректная установка PipeWire. Дополнительные сведения: https://gitlab." +"freedesktop.org/pipewire/pipewire/-/issues/3296." #: pipewirecore.cpp:107 #, kde-format