Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kpipewire6 for openSUSE:Factory 
checked in at 2024-07-17 15:13:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kpipewire6 (Old)
 and      /work/SRC/openSUSE:Factory/.kpipewire6.new.17339 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kpipewire6"

Wed Jul 17 15:13:03 2024 rev:9 rq:1187987 version:6.1.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/kpipewire6/kpipewire6.changes    2024-07-04 
16:20:44.905975821 +0200
+++ /work/SRC/openSUSE:Factory/.kpipewire6.new.17339/kpipewire6.changes 
2024-07-17 15:13:13.329840645 +0200
@@ -1,0 +2,19 @@
+Tue Jul 16 13:35:56 UTC 2024 - Fabian Vogt <fab...@ritter-vogt.de>
+
+- Add patches to support libopenh264 for encoding
+  (boo#1227461, kde#476187):
+  * 0001-Simpler-yet-more-useful-handling-of-KPIPEWIRE_FORCE_.patch
+  * 0002-Add-encoder-using-libopenh264.patch
+
+-------------------------------------------------------------------
+Tue Jul 16 13:23:41 UTC 2024 - Fabian Vogt <fab...@ritter-vogt.de>
+
+- Update to 6.1.3:
+  * New bugfix release
+  * For more details see https://kde.org/announcements/plasma/6/6.1.3
+- Changes since 6.1.2:
+  * produce: Properly cleanup on deactivate in all cases (kde#488687)
+  * produce: Destroy PipeWireSourceStream on the right thread (kde#489434)
+  * update version for new release
+
+-------------------------------------------------------------------

Old:
----
  kpipewire-6.1.2.tar.xz
  kpipewire-6.1.2.tar.xz.sig

New:
----
  0001-Simpler-yet-more-useful-handling-of-KPIPEWIRE_FORCE_.patch
  0002-Add-encoder-using-libopenh264.patch
  kpipewire-6.1.3.tar.xz
  kpipewire-6.1.3.tar.xz.sig

BETA DEBUG BEGIN:
  New:  (boo#1227461, kde#476187):
  * 0001-Simpler-yet-more-useful-handling-of-KPIPEWIRE_FORCE_.patch
  * 0002-Add-encoder-using-libopenh264.patch
  New:  * 0001-Simpler-yet-more-useful-handling-of-KPIPEWIRE_FORCE_.patch
  * 0002-Add-encoder-using-libopenh264.patch
BETA DEBUG END:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kpipewire6.spec ++++++
--- /var/tmp/diff_new_pack.AWghcL/_old  2024-07-17 15:13:14.005865411 +0200
+++ /var/tmp/diff_new_pack.AWghcL/_new  2024-07-17 15:13:14.009865558 +0200
@@ -27,7 +27,7 @@
 %{!?_plasma6_version: %define _plasma6_version %(echo %{_plasma6_bugfix} | awk 
-F. '{print $1"."$2}')}
 %bcond_without released
 Name:           kpipewire6
-Version:        6.1.2
+Version:        6.1.3
 Release:        0
 Summary:        PipeWire integration for KDE Plasma
 License:        LGPL-2.0-only AND LGPL-3.0-only
@@ -37,6 +37,9 @@
 Source1:        
https://download.kde.org/stable/plasma/%{version}/%{rname}-%{version}.tar.xz.sig
 Source2:        plasma.keyring
 %endif
+# PATCH-FEATURE-UPSTREAM
+Patch1:         0001-Simpler-yet-more-useful-handling-of-KPIPEWIRE_FORCE_.patch
+Patch2:         0002-Add-encoder-using-libopenh264.patch
 BuildRequires:  kf6-extra-cmake-modules
 BuildRequires:  pkgconfig
 BuildRequires:  qt6-gui-private-devel >= %{qt6_version}

++++++ 0001-Simpler-yet-more-useful-handling-of-KPIPEWIRE_FORCE_.patch ++++++
>From a50c28da704fbf8b9e71ec92054f325a33b9765f Mon Sep 17 00:00:00 2001
From: Fabian Vogt <fab...@ritter-vogt.de>
Date: Sat, 6 Jul 2024 16:27:28 +0200
Subject: [PATCH 1/2] Simpler yet more useful handling of
 KPIPEWIRE_FORCE_ENCODER

Previously, it always overrode the encoder type and profile.

Now just force a specific encoder by inlining the encoder selection
in the switch cases.

This means it's no longer possible to force a different encoder type
than the application requested, but it's arguably not that useful to
e.g. force VP9 if the application expects H.264 packets.

(cherry picked from commit 0c3f8b4f9de7d4dcd24d952184dabdbda74b4c35)
---
 src/pipewireproduce.cpp | 45 +++++++++--------------------------------
 1 file changed, 9 insertions(+), 36 deletions(-)

diff --git a/src/pipewireproduce.cpp b/src/pipewireproduce.cpp
index 3452ce9..416bcd3 100644
--- a/src/pipewireproduce.cpp
+++ b/src/pipewireproduce.cpp
@@ -266,46 +266,19 @@ void PipeWireProduce::stateChanged(pw_stream_state state)
 
 std::unique_ptr<Encoder> PipeWireProduce::makeEncoder()
 {
-    auto encoderType = m_encoderType;
-    bool forceSoftware = false;
-    bool forceHardware = false;
-
-    if (qEnvironmentVariableIsSet("KPIPEWIRE_FORCE_ENCODER")) {
-        auto forcedEncoder = qEnvironmentVariable("KPIPEWIRE_FORCE_ENCODER");
-        if (forcedEncoder == u"libvpx") {
-            qCWarning(PIPEWIRERECORD_LOGGING) << "Forcing VP8 Software 
encoding";
-            encoderType = PipeWireBaseEncodedStream::VP8;
-            forceSoftware = true;
-        } else if (forcedEncoder == u"libvpx-vp9") {
-            qCWarning(PIPEWIRERECORD_LOGGING) << "Forcing VP9 Software 
encoding";
-            encoderType = PipeWireBaseEncodedStream::VP9;
-            forceSoftware = true;
-        } else if (forcedEncoder == u"libx264") {
-            qCWarning(PIPEWIRERECORD_LOGGING) << "Forcing H264 Software 
encoding, main profile";
-            encoderType = PipeWireBaseEncodedStream::H264Main;
-            forceSoftware = true;
-        } else if (forcedEncoder == u"h264_vaapi") {
-            qCWarning(PIPEWIRERECORD_LOGGING) << "Forcing H264 Hardware 
encoding, main profile";
-            encoderType = PipeWireBaseEncodedStream::H264Main;
-            forceHardware = true;
-        } else if (forcedEncoder == u"libx264_baseline") {
-            qCWarning(PIPEWIRERECORD_LOGGING) << "Forcing H264 Software 
encoding, baseline profile";
-            encoderType = PipeWireBaseEncodedStream::H264Baseline;
-            forceSoftware = true;
-        } else if (forcedEncoder == u"h264_vaapi_baseline") {
-            qCWarning(PIPEWIRERECORD_LOGGING) << "Forcing H264 Hardware 
encoding, baseline profile";
-            encoderType = PipeWireBaseEncodedStream::H264Baseline;
-            forceHardware = true;
-        }
+    auto forcedEncoder = qEnvironmentVariable("KPIPEWIRE_FORCE_ENCODER");
+    if (!forcedEncoder.isNull()) {
+        qCWarning(PIPEWIRERECORD_LOGGING) << "Forcing encoder to" << 
forcedEncoder;
     }
 
     auto size = m_stream->size();
 
-    switch (encoderType) {
+    switch (m_encoderType) {
     case PipeWireBaseEncodedStream::H264Baseline:
     case PipeWireBaseEncodedStream::H264Main: {
         auto profile = m_encoderType == 
PipeWireBaseEncodedStream::H264Baseline ? Encoder::H264Profile::Baseline : 
Encoder::H264Profile::Main;
-        if (!forceSoftware) {
+
+        if (forcedEncoder.isNull() || forcedEncoder == u"h264_vaapi") {
             auto hardwareEncoder = std::make_unique<H264VAAPIEncoder>(profile, 
this);
             hardwareEncoder->setQuality(m_quality);
             hardwareEncoder->setEncodingPreference(m_encodingPreference);
@@ -314,7 +287,7 @@ std::unique_ptr<Encoder> PipeWireProduce::makeEncoder()
             }
         }
 
-        if (!forceHardware) {
+        if (forcedEncoder.isNull() || forcedEncoder == u"libx264") {
             auto softwareEncoder = std::make_unique<LibX264Encoder>(profile, 
this);
             softwareEncoder->setQuality(m_quality);
             softwareEncoder->setEncodingPreference(m_encodingPreference);
@@ -325,7 +298,7 @@ std::unique_ptr<Encoder> PipeWireProduce::makeEncoder()
         break;
     }
     case PipeWireBaseEncodedStream::VP8: {
-        if (!forceHardware) {
+        if (forcedEncoder.isNull() || forcedEncoder == u"libvpx") {
             auto encoder = std::make_unique<LibVpxEncoder>(this);
             encoder->setQuality(m_quality);
             if (encoder->initialize(size)) {
@@ -335,7 +308,7 @@ std::unique_ptr<Encoder> PipeWireProduce::makeEncoder()
         break;
     }
     case PipeWireBaseEncodedStream::VP9: {
-        if (!forceHardware) {
+        if (forcedEncoder.isNull() || forcedEncoder == u"libvpx-vp9") {
             auto encoder = std::make_unique<LibVpxVp9Encoder>(this);
             encoder->setQuality(m_quality);
             if (encoder->initialize(size)) {
-- 
2.45.2


++++++ 0002-Add-encoder-using-libopenh264.patch ++++++
>From 43ab595c28e031f38bc92bea4cf475de64021958 Mon Sep 17 00:00:00 2001
From: Fabian Vogt <fab...@ritter-vogt.de>
Date: Sat, 6 Jul 2024 16:40:42 +0200
Subject: [PATCH 2/2] Add encoder using libopenh264

On some distributions, libopenh264 is the only encoder available OOTB.
Add support for it and use it as fallback.

BUG: 476187
(cherry picked from commit e17793a3b023f26411001093bb2d5934adf715c7)
---
 src/CMakeLists.txt                |   1 +
 src/libopenh264encoder.cpp        | 106 ++++++++++++++++++++++++++++++
 src/libopenh264encoder_p.h        |  28 ++++++++
 src/pipewirebaseencodedstream.cpp |   2 +-
 src/pipewireproduce.cpp           |  11 ++++
 5 files changed, 147 insertions(+), 1 deletion(-)
 create mode 100644 src/libopenh264encoder.cpp
 create mode 100644 src/libopenh264encoder_p.h

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e96f52b..3126528 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -135,6 +135,7 @@ add_library(KPipeWireRecord ${kpipewirerecord_SRCS}
                             encoder.cpp
                             h264vaapiencoder.cpp
                             libx264encoder.cpp
+                            libopenh264encoder.cpp
                             libvpxencoder.cpp
                             libvpxvp9encoder.cpp
 )
diff --git a/src/libopenh264encoder.cpp b/src/libopenh264encoder.cpp
new file mode 100644
index 0000000..6d4c6a1
--- /dev/null
+++ b/src/libopenh264encoder.cpp
@@ -0,0 +1,106 @@
+/*
+    SPDX-FileCopyrightText: 2023 Aleix Pol Gonzalez <aleix...@kde.org>
+    SPDX-FileCopyrightText: 2023 Marco Martin <m...@kde.org>
+    SPDX-FileCopyrightText: 2023 Arjen Hiemstra <ahiems...@heimr.nl>
+    SPDX-FileCopyrightText: 2024 Fabian Vogt <fab...@ritter-vogt.de>
+
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "libopenh264encoder_p.h"
+
+#include <QSize>
+#include <QThread>
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+#include <libavfilter/buffersink.h>
+#include <libavfilter/buffersrc.h>
+#include <libavutil/pixfmt.h>
+}
+
+#include "logging_record.h"
+
+LibOpenH264Encoder::LibOpenH264Encoder(H264Profile profile, PipeWireProduce 
*produce)
+    : SoftwareEncoder(produce)
+    , m_profile(profile)
+{
+}
+
+bool LibOpenH264Encoder::initialize(const QSize &size)
+{
+    createFilterGraph(size);
+
+    auto codec = avcodec_find_encoder_by_name("libopenh264");
+    if (!codec) {
+        qCWarning(PIPEWIRERECORD_LOGGING) << "libopenh264 codec not found";
+        return false;
+    }
+
+    m_avCodecContext = avcodec_alloc_context3(codec);
+    if (!m_avCodecContext) {
+        qCWarning(PIPEWIRERECORD_LOGGING) << "Could not allocate video codec 
context";
+        return false;
+    }
+
+    Q_ASSERT(!size.isEmpty());
+    m_avCodecContext->width = size.width();
+    m_avCodecContext->height = size.height();
+    m_avCodecContext->max_b_frames = 0;
+    m_avCodecContext->gop_size = 100;
+    m_avCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
+    m_avCodecContext->time_base = AVRational{1, 1000};
+
+    if (m_quality) {
+        // "q" here stands for "quantization", but that effectively impacts 
quality.
+        m_avCodecContext->qmin = m_avCodecContext->qmax = 
percentageToAbsoluteQuality(m_quality);
+    }
+
+    switch (m_profile) {
+    case H264Profile::Baseline:
+        // libopenh264 only does constrained baseline.
+        // There's a bug in the ffmpeg -> openh264 interface though:
+        // ffmpeg expects CONSTRAINED_BASELINE from the application and
+        // passes that through, but libopenh264 only allows BASELINE.
+        // Until that bug is fixed there'll always be a warning that the
+        // profile is not supported 
(https://github.com/cisco/openh264/issues/3613)
+        m_avCodecContext->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE;
+        break;
+    case H264Profile::Main:
+        m_avCodecContext->profile = FF_PROFILE_H264_MAIN;
+        break;
+    case H264Profile::High:
+        m_avCodecContext->profile = FF_PROFILE_H264_HIGH;
+        break;
+    }
+
+    AVDictionary *options = nullptr;
+    av_dict_set_int(&options, "threads", qMin(16, 
QThread::idealThreadCount()), 0);
+    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;
+    }
+
+    return true;
+}
+
+int LibOpenH264Encoder::percentageToAbsoluteQuality(const 
std::optional<quint8> &quality)
+{
+    if (!quality) {
+        return -1;
+    }
+
+    // 1-51 (incl.), lower is better
+    return 51 - (m_quality.value() / 100.0) * 50;
+}
+
+void LibOpenH264Encoder::applyEncodingPreference(AVDictionary *options)
+{
+    SoftwareEncoder::applyEncodingPreference(options);
+    // 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);
+}
diff --git a/src/libopenh264encoder_p.h b/src/libopenh264encoder_p.h
new file mode 100644
index 0000000..fdacf14
--- /dev/null
+++ b/src/libopenh264encoder_p.h
@@ -0,0 +1,28 @@
+/*
+    SPDX-FileCopyrightText: 2023 Aleix Pol Gonzalez <aleix...@kde.org>
+    SPDX-FileCopyrightText: 2023 Marco Martin <m...@kde.org>
+    SPDX-FileCopyrightText: 2023 Arjen Hiemstra <ahiems...@heimr.nl>
+    SPDX-FileCopyrightText: 2024 Fabian Vogt <fab...@ritter-vogt.de>
+
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "encoder_p.h"
+
+/**
+ * A software encoder that uses ffmpeg + libopenh264 to encode to H.264.
+ */
+class LibOpenH264Encoder : public SoftwareEncoder
+{
+public:
+    LibOpenH264Encoder(H264Profile profile, PipeWireProduce *produce);
+
+    bool initialize(const QSize &size) override;
+
+protected:
+    int percentageToAbsoluteQuality(const std::optional<quint8> &quality) 
override;
+    void applyEncodingPreference(AVDictionary *options) override;
+
+private:
+    H264Profile m_profile = H264Profile::Main;
+};
diff --git a/src/pipewirebaseencodedstream.cpp 
b/src/pipewirebaseencodedstream.cpp
index 553c334..814d8d9 100644
--- a/src/pipewirebaseencodedstream.cpp
+++ b/src/pipewirebaseencodedstream.cpp
@@ -225,7 +225,7 @@ QList<PipeWireBaseEncodedStream::Encoder> 
PipeWireBaseEncodedStream::suggestedEn
                 && avcodec_find_encoder_by_name("h264_vaapi")) {
                 return false;
             } else {
-                return !avcodec_find_encoder_by_name("libx264");
+                return !(avcodec_find_encoder_by_name("libx264") || 
avcodec_find_encoder_by_name("libopenh264"));
             }
         default:
             return true;
diff --git a/src/pipewireproduce.cpp b/src/pipewireproduce.cpp
index 416bcd3..52594e6 100644
--- a/src/pipewireproduce.cpp
+++ b/src/pipewireproduce.cpp
@@ -16,6 +16,7 @@
 #include <qstringliteral.h>
 
 #include "h264vaapiencoder_p.h"
+#include "libopenh264encoder_p.h"
 #include "libvpxencoder_p.h"
 #include "libvpxvp9encoder_p.h"
 #include "libx264encoder_p.h"
@@ -295,6 +296,16 @@ std::unique_ptr<Encoder> PipeWireProduce::makeEncoder()
                 return softwareEncoder;
             }
         }
+
+        // Try libopenh264 last, it's slower and has less features.
+        if (forcedEncoder.isNull() || forcedEncoder == u"libopenh264") {
+            auto softwareEncoder = 
std::make_unique<LibOpenH264Encoder>(profile, this);
+            softwareEncoder->setQuality(m_quality);
+            softwareEncoder->setEncodingPreference(m_encodingPreference);
+            if (softwareEncoder->initialize(size)) {
+                return softwareEncoder;
+            }
+        }
         break;
     }
     case PipeWireBaseEncodedStream::VP8: {
-- 
2.45.2


++++++ kpipewire-6.1.2.tar.xz -> kpipewire-6.1.3.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kpipewire-6.1.2/CMakeLists.txt 
new/kpipewire-6.1.3/CMakeLists.txt
--- old/kpipewire-6.1.2/CMakeLists.txt  2024-07-02 11:12:47.000000000 +0200
+++ new/kpipewire-6.1.3/CMakeLists.txt  2024-07-16 13:08:23.000000000 +0200
@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 3.16)
-project(KPipewire VERSION "6.1.2")
+project(KPipewire VERSION "6.1.3")
 
 set(KF6_MIN_VERSION "6.2.0")
 find_package(ECM ${KF6_MIN_VERSION} REQUIRED NO_MODULE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kpipewire-6.1.2/src/pipewireproduce.cpp 
new/kpipewire-6.1.3/src/pipewireproduce.cpp
--- old/kpipewire-6.1.2/src/pipewireproduce.cpp 2024-07-02 11:12:47.000000000 
+0200
+++ new/kpipewire-6.1.3/src/pipewireproduce.cpp 2024-07-16 13:08:23.000000000 
+0200
@@ -150,13 +150,44 @@
 void PipeWireProduce::deactivate()
 {
     m_deactivated = true;
+
+    auto streamState = m_stream->state();
+
     m_stream->setActive(false);
-    if (!m_encoder) {
-        cleanup();
-        QThread::currentThread()->quit();
+
+    // If we have not been initialized properly before, ensure we still run any
+    // cleanup code and exit the thread, otherwise we risk applications not 
closing
+    // properly.
+    if (!m_encoder || streamState != PW_STREAM_STATE_STREAMING) {
+        QMetaObject::invokeMethod(this, &PipeWireProduce::destroy, 
Qt::QueuedConnection);
     }
 }
 
+void PipeWireProduce::destroy()
+{
+    // Ensure we cleanup the PipeWireSourceStream while in the same thread we
+    // created it in.
+    Q_ASSERT_X(QThread::currentThread() == thread(), "PipeWireProduce", 
"destroy() called from a different thread than PipeWireProduce's thread");
+
+    if (m_passthroughThread.joinable()) {
+        m_passthroughRunning = false;
+        m_frameReceivedCondition.notify_all();
+        m_passthroughThread.join();
+    }
+
+    if (m_outputThread.joinable()) {
+        m_outputRunning = false;
+        m_frameReceivedCondition.notify_all();
+        m_outputThread.join();
+    }
+
+    m_stream.reset();
+
+    qCDebug(PIPEWIRERECORD_LOGGING) << "finished";
+    cleanup();
+    QThread::currentThread()->quit();
+}
+
 void PipeWireProduce::setQuality(const std::optional<quint8> &quality)
 {
     m_quality = quality;
@@ -227,21 +258,10 @@
 
     m_encoder->finish();
 
-    if (m_passthroughThread.joinable()) {
-        m_passthroughRunning = false;
-        m_frameReceivedCondition.notify_all();
-        m_passthroughThread.join();
-    }
-
-    if (m_outputThread.joinable()) {
-        m_outputRunning = false;
-        m_frameReceivedCondition.notify_all();
-        m_outputThread.join();
-    }
-
-    qCDebug(PIPEWIRERECORD_LOGGING) << "finished";
-    cleanup();
-    QThread::currentThread()->quit();
+    // We want to clean up the source stream while in the input thread, but we
+    // need to do so while not handling any PipeWire callback as that risks
+    // crashing because we're stil executing PipeWire handling code.
+    QMetaObject::invokeMethod(this, &PipeWireProduce::destroy, 
Qt::QueuedConnection);
 }
 
 std::unique_ptr<Encoder> PipeWireProduce::makeEncoder()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kpipewire-6.1.2/src/pipewireproduce_p.h 
new/kpipewire-6.1.3/src/pipewireproduce_p.h
--- old/kpipewire-6.1.2/src/pipewireproduce_p.h 2024-07-02 11:12:47.000000000 
+0200
+++ new/kpipewire-6.1.3/src/pipewireproduce_p.h 2024-07-16 13:08:23.000000000 
+0200
@@ -91,6 +91,8 @@
 
     void deactivate();
 
+    void destroy();
+
     void setQuality(const std::optional<quint8> &quality);
 
     void setEncodingPreference(const 
PipeWireBaseEncodedStream::EncodingPreference &encodingPreference);

Reply via email to