commit:     2e4ef773aa0b1f5ce37a0650bbaf9e55dfc4c069
Author:     Sam James <sam <AT> gentoo <DOT> org>
AuthorDate: Tue May 27 06:26:43 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Tue May 27 06:27:10 2025 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=2e4ef773

media-video/pipewire: backport several patches to 1.4.3

Robert Mader (1):
      gst: src: Change DEFAULT_MIN_BUFFERS back to 1

Wim Taymans (4):
      pod: add bytes start/append/end functions
      Use "8 bit raw midi" for control ports again
      alsa: remove UMP flag from control format
      adapter: negotiate from target to follower

Closes: https://bugs.gentoo.org/956654
Signed-off-by: Sam James <sam <AT> gentoo.org>

 ...-pod-add-bytes-start-append-end-functions.patch |  50 +++
 ...se-8-bit-raw-midi-for-control-ports-again.patch | 265 ++++++++++++
 ...-alsa-remove-UMP-flag-from-control-format.patch | 451 +++++++++++++++++++++
 ...adapter-negotiate-from-target-to-follower.patch | 202 +++++++++
 ...-src-Change-DEFAULT_MIN_BUFFERS-back-to-1.patch |  39 ++
 ...ewire-1.4.3.ebuild => pipewire-1.4.3-r1.ebuild} |   0
 6 files changed, 1007 insertions(+)

diff --git 
a/media-video/pipewire/files/1.4.3/0001-pod-add-bytes-start-append-end-functions.patch
 
b/media-video/pipewire/files/1.4.3/0001-pod-add-bytes-start-append-end-functions.patch
new file mode 100644
index 000000000000..d0b413f6dc1b
--- /dev/null
+++ 
b/media-video/pipewire/files/1.4.3/0001-pod-add-bytes-start-append-end-functions.patch
@@ -0,0 +1,50 @@
+From 483b59a9d95aa084dfcd1c17e13ee27bd106d4b0 Mon Sep 17 00:00:00 2001
+Message-ID: 
<483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git....@gentoo.org>
+From: Wim Taymans <[email protected]>
+Date: Fri, 23 May 2025 16:41:00 +0200
+Subject: [PATCH 1/5] pod: add bytes start/append/end functions
+
+Add functions to dynamically start and build a bytes pod.
+---
+ spa/include/spa/pod/builder.h | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/spa/include/spa/pod/builder.h b/spa/include/spa/pod/builder.h
+index 553f75512..3dc4a4f1c 100644
+--- a/spa/include/spa/pod/builder.h
++++ b/spa/include/spa/pod/builder.h
+@@ -326,6 +326,31 @@ spa_pod_builder_reserve_bytes(struct spa_pod_builder 
*builder, uint32_t len)
+       return SPA_POD_BODY(spa_pod_builder_deref(builder, offset));
+ }
+ 
++SPA_API_POD_BUILDER uint32_t
++spa_pod_builder_bytes_start(struct spa_pod_builder *builder)
++{
++      uint32_t offset = builder->state.offset;
++      const struct spa_pod_bytes p = SPA_POD_INIT_Bytes(0);
++      spa_pod_builder_raw(builder, &p, sizeof(p));
++      return offset;
++}
++SPA_API_POD_BUILDER int
++spa_pod_builder_bytes_append(struct spa_pod_builder *builder, uint32_t offset,
++              const void *data, uint32_t size)
++{
++      int res = spa_pod_builder_raw(builder, data, size);
++      struct spa_pod *pod = spa_pod_builder_deref(builder, offset);
++      if (pod)
++              pod->size += size;
++      return res;
++}
++
++SPA_API_POD_BUILDER int
++spa_pod_builder_bytes_end(struct spa_pod_builder *builder, uint32_t offset)
++{
++      return spa_pod_builder_pad(builder, builder->state.offset);
++}
++
+ #define SPA_POD_INIT_Pointer(type,value) ((struct spa_pod_pointer){ { 
sizeof(struct spa_pod_pointer_body), SPA_TYPE_Pointer }, { (type), 0, (value) } 
})
+ 
+ SPA_API_POD_BUILDER int
+-- 
+2.49.0
+

diff --git 
a/media-video/pipewire/files/1.4.3/0002-Use-8-bit-raw-midi-for-control-ports-again.patch
 
b/media-video/pipewire/files/1.4.3/0002-Use-8-bit-raw-midi-for-control-ports-again.patch
new file mode 100644
index 000000000000..54361ee977b3
--- /dev/null
+++ 
b/media-video/pipewire/files/1.4.3/0002-Use-8-bit-raw-midi-for-control-ports-again.patch
@@ -0,0 +1,265 @@
+From 76db05a0f8edb8b7d4d896d3860bc555934ad383 Mon Sep 17 00:00:00 2001
+Message-ID: 
<76db05a0f8edb8b7d4d896d3860bc555934ad383.1748327071.git....@gentoo.org>
+In-Reply-To: 
<483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git....@gentoo.org>
+References: 
<483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git....@gentoo.org>
+From: Wim Taymans <[email protected]>
+Date: Fri, 23 May 2025 16:46:13 +0200
+Subject: [PATCH 2/5] Use "8 bit raw midi" for control ports again
+
+There is no need to encode the potential format in the format.dsp of
+control ports, this is just for legacy compatibility with JACK apps. The
+actual format can be negotiated with the types field.
+
+Fixes midi port visibility with apps compiled against 1.2, such as JACK
+apps in flatpaks.
+---
+ pipewire-jack/src/pipewire-jack.c             | 20 +------------------
+ spa/plugins/alsa/alsa-seq-bridge.c            |  2 +-
+ spa/plugins/audioconvert/audioconvert.c       |  2 +-
+ spa/plugins/bluez5/midi-node.c                |  4 ++--
+ .../videoconvert/videoconvert-ffmpeg.c        |  2 +-
+ src/examples/midi-src.c                       |  2 +-
+ src/modules/module-ffado-driver.c             |  2 +-
+ src/modules/module-jack-tunnel.c              |  2 +-
+ src/modules/module-netjack2-driver.c          |  2 +-
+ src/modules/module-netjack2-manager.c         |  2 +-
+ src/modules/module-rtp/stream.c               |  2 +-
+ src/modules/module-vban/stream.c              |  2 +-
+ src/pipewire/filter.c                         |  4 +++-
+ src/pipewire/stream.c                         |  2 +-
+ src/tools/pw-cat.c                            |  2 +-
+ 15 files changed, 18 insertions(+), 34 deletions(-)
+
+diff --git a/pipewire-jack/src/pipewire-jack.c 
b/pipewire-jack/src/pipewire-jack.c
+index 14c062a21..b859b64b0 100644
+--- a/pipewire-jack/src/pipewire-jack.c
++++ b/pipewire-jack/src/pipewire-jack.c
+@@ -3466,24 +3466,6 @@ static const char* type_to_string(jack_port_type_id_t 
type_id)
+       }
+ }
+ 
+-static const char* type_to_format_dsp(jack_port_type_id_t type_id)
+-{
+-      switch(type_id) {
+-      case TYPE_ID_AUDIO:
+-              return JACK_DEFAULT_AUDIO_TYPE;
+-      case TYPE_ID_VIDEO:
+-              return JACK_DEFAULT_VIDEO_TYPE;
+-      case TYPE_ID_OSC:
+-              return JACK_DEFAULT_OSC_TYPE;
+-      case TYPE_ID_MIDI:
+-              return JACK_DEFAULT_MIDI_TYPE;
+-      case TYPE_ID_UMP:
+-              return JACK_DEFAULT_UMP_TYPE;
+-      default:
+-              return NULL;
+-      }
+-}
+-
+ static bool type_is_dsp(jack_port_type_id_t type_id)
+ {
+       switch(type_id) {
+@@ -5544,7 +5526,7 @@ jack_port_t * jack_port_register (jack_client_t *client,
+ 
+       spa_list_init(&p->mix);
+ 
+-      pw_properties_set(p->props, PW_KEY_FORMAT_DSP, 
type_to_format_dsp(type_id));
++      pw_properties_set(p->props, PW_KEY_FORMAT_DSP, type_to_string(type_id));
+       pw_properties_set(p->props, PW_KEY_PORT_NAME, port_name);
+       if (flags > 0x1f) {
+               pw_properties_setf(p->props, PW_KEY_PORT_EXTRA,
+diff --git a/spa/plugins/alsa/alsa-seq-bridge.c 
b/spa/plugins/alsa/alsa-seq-bridge.c
+index 7ec39321c..68e6c91a8 100644
+--- a/spa/plugins/alsa/alsa-seq-bridge.c
++++ b/spa/plugins/alsa/alsa-seq-bridge.c
+@@ -275,7 +275,7 @@ static void emit_port_info(struct seq_state *this, struct 
seq_port *port, bool f
+               snprintf(alias, sizeof(alias), "%s:%s", client_name, port_name);
+               clean_name(alias);
+ 
+-              items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "32 
bit raw UMP");
++              items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "8 
bit raw midi");
+               items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_OBJECT_PATH, 
path);
+               items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, name);
+               items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_PORT_ALIAS, 
alias);
+diff --git a/spa/plugins/audioconvert/audioconvert.c 
b/spa/plugins/audioconvert/audioconvert.c
+index c1fa022d1..c36028bcd 100644
+--- a/spa/plugins/audioconvert/audioconvert.c
++++ b/spa/plugins/audioconvert/audioconvert.c
+@@ -362,7 +362,7 @@ static void emit_port_info(struct impl *this, struct port 
*port, bool full)
+                               items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_IGNORE_LATENCY, "true");
+               } else if (PORT_IS_CONTROL(this, port->direction, port->id)) {
+                       items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, "control");
+-                      items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "32 bit raw UMP");
++                      items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "8 bit raw midi");
+               }
+               if (this->group_name[0] != '\0')
+                       items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_GROUP, this->group_name);
+diff --git a/spa/plugins/bluez5/midi-node.c b/spa/plugins/bluez5/midi-node.c
+index b5fd179ea..cfba2bfcf 100644
+--- a/spa/plugins/bluez5/midi-node.c
++++ b/spa/plugins/bluez5/midi-node.c
+@@ -2024,13 +2024,13 @@ impl_init(const struct spa_handle_factory *factory,
+       for (i = 0; i < N_PORTS; ++i) {
+               struct port *port = &this->ports[i];
+               static const struct spa_dict_item in_port_items[] = {
+-                      SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "32 bit raw 
UMP"),
++                      SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "8 bit raw 
midi"),
+                       SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, "in"),
+                       SPA_DICT_ITEM_INIT(SPA_KEY_PORT_ALIAS, "in"),
+                       SPA_DICT_ITEM_INIT(SPA_KEY_PORT_GROUP, "group.0"),
+               };
+               static const struct spa_dict_item out_port_items[] = {
+-                      SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "32 bit raw 
UMP"),
++                      SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "8 bit raw 
midi"),
+                       SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, "out"),
+                       SPA_DICT_ITEM_INIT(SPA_KEY_PORT_ALIAS, "out"),
+                       SPA_DICT_ITEM_INIT(SPA_KEY_PORT_GROUP, "group.0"),
+diff --git a/spa/plugins/videoconvert/videoconvert-ffmpeg.c 
b/spa/plugins/videoconvert/videoconvert-ffmpeg.c
+index ddb810be5..3da0e5677 100644
+--- a/spa/plugins/videoconvert/videoconvert-ffmpeg.c
++++ b/spa/plugins/videoconvert/videoconvert-ffmpeg.c
+@@ -228,7 +228,7 @@ static void emit_port_info(struct impl *this, struct port 
*port, bool full)
+                               items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_IGNORE_LATENCY, "true");
+               } else if (PORT_IS_CONTROL(this, port->direction, port->id)) {
+                       items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, "control");
+-                      items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "32 bit raw UMP");
++                      items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "8 bit raw midi");
+               }
+               if (this->group_name[0] != '\0')
+                       items[n_items++] = 
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_GROUP, this->group_name);
+diff --git a/src/examples/midi-src.c b/src/examples/midi-src.c
+index edcaa0f08..12f86d6f2 100644
+--- a/src/examples/midi-src.c
++++ b/src/examples/midi-src.c
+@@ -213,7 +213,7 @@ int main(int argc, char *argv[])
+                       PW_FILTER_PORT_FLAG_MAP_BUFFERS,
+                       sizeof(struct port),
+                       pw_properties_new(
+-                              PW_KEY_FORMAT_DSP, "32 bit raw UMP",
++                              PW_KEY_FORMAT_DSP, "8 bit raw midi",
+                               PW_KEY_PORT_NAME, "output",
+                               NULL),
+                       NULL, 0);
+diff --git a/src/modules/module-ffado-driver.c 
b/src/modules/module-ffado-driver.c
+index 4345e5a19..1c9c7c590 100644
+--- a/src/modules/module-ffado-driver.c
++++ b/src/modules/module-ffado-driver.c
+@@ -772,7 +772,7 @@ static int make_stream_ports(struct stream *s)
+                       break;
+               case ffado_stream_type_midi:
+                       props = pw_properties_new(
+-                                      PW_KEY_FORMAT_DSP, "32 bit raw UMP",
++                                      PW_KEY_FORMAT_DSP, "8 bit raw midi",
+                                       PW_KEY_PORT_NAME, port->name,
+                                       PW_KEY_PORT_PHYSICAL, "true",
+                                       PW_KEY_PORT_TERMINAL, "true",
+diff --git a/src/modules/module-jack-tunnel.c 
b/src/modules/module-jack-tunnel.c
+index 7ab4c9faf..76ac73c8d 100644
+--- a/src/modules/module-jack-tunnel.c
++++ b/src/modules/module-jack-tunnel.c
+@@ -515,7 +515,7 @@ static void make_stream_ports(struct stream *s)
+               } else {
+                       snprintf(name, sizeof(name), "%s_%d", prefix, i - 
s->info.channels);
+                       props = pw_properties_new(
+-                                      PW_KEY_FORMAT_DSP, "32 bit raw UMP",
++                                      PW_KEY_FORMAT_DSP, "8 bit raw midi",
+                                       PW_KEY_PORT_NAME, name,
+                                       PW_KEY_PORT_PHYSICAL, "true",
+                                       NULL);
+diff --git a/src/modules/module-netjack2-driver.c 
b/src/modules/module-netjack2-driver.c
+index 0aa9a85cd..011052e7b 100644
+--- a/src/modules/module-netjack2-driver.c
++++ b/src/modules/module-netjack2-driver.c
+@@ -452,7 +452,7 @@ static void make_stream_ports(struct stream *s)
+               } else {
+                       snprintf(name, sizeof(name), "midi%d", i - 
s->info.channels);
+                       props = pw_properties_new(
+-                                      PW_KEY_FORMAT_DSP, "32 bit raw UMP",
++                                      PW_KEY_FORMAT_DSP, "8 bit raw midi",
+                                       PW_KEY_AUDIO_CHANNEL, name,
+                                       PW_KEY_PORT_PHYSICAL, "true",
+                                       NULL);
+diff --git a/src/modules/module-netjack2-manager.c 
b/src/modules/module-netjack2-manager.c
+index 2cef87218..fe482fd94 100644
+--- a/src/modules/module-netjack2-manager.c
++++ b/src/modules/module-netjack2-manager.c
+@@ -614,7 +614,7 @@ static void make_stream_ports(struct stream *s)
+               } else {
+                       snprintf(name, sizeof(name), "midi%d", i - 
s->info.channels);
+                       props = pw_properties_new(
+-                                      PW_KEY_FORMAT_DSP, "32 bit raw UMP",
++                                      PW_KEY_FORMAT_DSP, "8 bit raw midi",
+                                       PW_KEY_PORT_PHYSICAL, "true",
+                                       PW_KEY_AUDIO_CHANNEL, name,
+                                       NULL);
+diff --git a/src/modules/module-rtp/stream.c b/src/modules/module-rtp/stream.c
+index f4d3fa3b8..cbd3ee994 100644
+--- a/src/modules/module-rtp/stream.c
++++ b/src/modules/module-rtp/stream.c
+@@ -390,7 +390,7 @@ struct rtp_stream *rtp_stream_new(struct pw_core *core,
+                       res = -EINVAL;
+                       goto out;
+               }
+-              pw_properties_set(props, PW_KEY_FORMAT_DSP, "32 bit raw UMP");
++              pw_properties_set(props, PW_KEY_FORMAT_DSP, "8 bit raw midi");
+               impl->stride = impl->format_info->size;
+               impl->rate = pw_properties_get_uint32(props, "midi.rate", 
10000);
+               if (impl->rate == 0)
+diff --git a/src/modules/module-vban/stream.c 
b/src/modules/module-vban/stream.c
+index efa5af370..10eb34a82 100644
+--- a/src/modules/module-vban/stream.c
++++ b/src/modules/module-vban/stream.c
+@@ -307,7 +307,7 @@ struct vban_stream *vban_stream_new(struct pw_core *core,
+                       res = -EINVAL;
+                       goto out;
+               }
+-              pw_properties_set(props, PW_KEY_FORMAT_DSP, "32 bit raw UMP");
++              pw_properties_set(props, PW_KEY_FORMAT_DSP, "8 bit raw midi");
+               impl->stride = impl->format_info->size;
+               impl->rate = pw_properties_get_uint32(props, "midi.rate", 
10000);
+               if (impl->rate == 0)
+diff --git a/src/pipewire/filter.c b/src/pipewire/filter.c
+index 519c1e2f7..03706e98a 100644
+--- a/src/pipewire/filter.c
++++ b/src/pipewire/filter.c
+@@ -1855,8 +1855,10 @@ void *pw_filter_add_port(struct pw_filter *filter,
+                       add_control_dsp_port_params(impl, p, 1u << 
SPA_CONTROL_Midi);
+               else if (spa_streq(str, "8 bit raw control"))
+                       add_control_dsp_port_params(impl, p, 0);
+-              else if (spa_streq(str, "32 bit raw UMP"))
++              else if (spa_streq(str, "32 bit raw UMP")) {
+                       add_control_dsp_port_params(impl, p, 1u << 
SPA_CONTROL_UMP);
++                      pw_properties_set(props, PW_KEY_FORMAT_DSP, "8 bit raw 
midi");
++              }
+       }
+       /* then override with user provided if any */
+       if (update_params(impl, p, SPA_ID_INVALID, params, n_params) < 0)
+diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c
+index 4af3a3afa..f5684d5e7 100644
+--- a/src/pipewire/stream.c
++++ b/src/pipewire/stream.c
+@@ -2053,7 +2053,7 @@ pw_stream_connect(struct pw_stream *stream,
+               pw_properties_set(impl->port_props, PW_KEY_FORMAT_DSP, str);
+       else if (impl->media_type == SPA_MEDIA_TYPE_application &&
+           impl->media_subtype == SPA_MEDIA_SUBTYPE_control)
+-              pw_properties_set(impl->port_props, PW_KEY_FORMAT_DSP, "32 bit 
raw UMP");
++              pw_properties_set(impl->port_props, PW_KEY_FORMAT_DSP, "8 bit 
raw midi");
+       if (pw_properties_get(impl->port_props, PW_KEY_PORT_GROUP) == NULL)
+               pw_properties_set(impl->port_props, PW_KEY_PORT_GROUP, 
"stream.0");
+ 
+diff --git a/src/tools/pw-cat.c b/src/tools/pw-cat.c
+index 36a78981e..928afed0e 100644
+--- a/src/tools/pw-cat.c
++++ b/src/tools/pw-cat.c
+@@ -1985,7 +1985,7 @@ int main(int argc, char *argv[])
+                               SPA_FORMAT_mediaType,           
SPA_POD_Id(SPA_MEDIA_TYPE_application),
+                               SPA_FORMAT_mediaSubtype,        
SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
+ 
+-              pw_properties_set(data.props, PW_KEY_FORMAT_DSP, "32 bit raw 
UMP");
++              pw_properties_set(data.props, PW_KEY_FORMAT_DSP, "8 bit raw 
midi");
+               break;
+       case TYPE_DSD:
+       {
+-- 
+2.49.0
+

diff --git 
a/media-video/pipewire/files/1.4.3/0003-alsa-remove-UMP-flag-from-control-format.patch
 
b/media-video/pipewire/files/1.4.3/0003-alsa-remove-UMP-flag-from-control-format.patch
new file mode 100644
index 000000000000..f29487147a3b
--- /dev/null
+++ 
b/media-video/pipewire/files/1.4.3/0003-alsa-remove-UMP-flag-from-control-format.patch
@@ -0,0 +1,451 @@
+From 06941f7315c3ca814771cc8b6612c3d01a8bf968 Mon Sep 17 00:00:00 2001
+Message-ID: 
<06941f7315c3ca814771cc8b6612c3d01a8bf968.1748327071.git....@gentoo.org>
+In-Reply-To: 
<483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git....@gentoo.org>
+References: 
<483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git....@gentoo.org>
+From: Wim Taymans <[email protected]>
+Date: Fri, 23 May 2025 16:53:42 +0200
+Subject: [PATCH 3/5] alsa: remove UMP flag from control format
+
+Don't set the UMP type flag on the format. Use the negotiated types flag
+to decide what format to output. Add support for output to old style
+midi.
+
+Set the UMP type flag only on the new mixer and JACK when UMP is
+enabled.
+
+This ensures that only new (or explicitly requesting) apps get UMP and
+old apps receive old midi.
+
+This makes JACK running on 1.2 in flatpaks work with midi again.
+---
+ pipewire-jack/src/pipewire-jack.c  |  23 ++++-
+ spa/plugins/alsa/alsa-seq-bridge.c |  13 +--
+ spa/plugins/alsa/alsa-seq.c        | 159 ++++++++++++++++++++---------
+ spa/plugins/alsa/alsa-seq.h        |   3 +
+ spa/plugins/control/mixer.c        |   3 +-
+ src/modules/module-jack-tunnel.c   |  33 +++---
+ 6 files changed, 157 insertions(+), 77 deletions(-)
+
+diff --git a/pipewire-jack/src/pipewire-jack.c 
b/pipewire-jack/src/pipewire-jack.c
+index b859b64b0..695938f90 100644
+--- a/pipewire-jack/src/pipewire-jack.c
++++ b/pipewire-jack/src/pipewire-jack.c
+@@ -2549,11 +2549,28 @@ static int param_enum_format(struct client *c, struct 
port *p,
+       case TYPE_ID_UMP:
+       case TYPE_ID_OSC:
+       case TYPE_ID_MIDI:
+-              *param = spa_pod_builder_add_object(b,
+-                      SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
++      {
++              struct spa_pod_frame f;
++              int32_t types = 0;
++
++              spa_pod_builder_push_object(b, &f,
++                      SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
++              spa_pod_builder_add(b,
+                       SPA_FORMAT_mediaType,      
SPA_POD_Id(SPA_MEDIA_TYPE_application),
+-                      SPA_FORMAT_mediaSubtype,   
SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
++                      SPA_FORMAT_mediaSubtype,   
SPA_POD_Id(SPA_MEDIA_SUBTYPE_control),
++                      0);
++              if (p->object->port.type_id == TYPE_ID_UMP)
++                      types |= 1u<<SPA_CONTROL_UMP;
++              if (p->object->port.type_id == TYPE_ID_OSC)
++                      types |= 1u<<SPA_CONTROL_OSC;
++              if (types != 0)
++                      spa_pod_builder_add(b,
++                              SPA_FORMAT_CONTROL_types,  
SPA_POD_CHOICE_FLAGS_Int(types),
++                              0);
++
++              *param = spa_pod_builder_pop(b, &f);
+               break;
++      }
+       case TYPE_ID_VIDEO:
+               *param = spa_pod_builder_add_object(b,
+                       SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
+diff --git a/spa/plugins/alsa/alsa-seq-bridge.c 
b/spa/plugins/alsa/alsa-seq-bridge.c
+index 68e6c91a8..445808017 100644
+--- a/spa/plugins/alsa/alsa-seq-bridge.c
++++ b/spa/plugins/alsa/alsa-seq-bridge.c
+@@ -529,8 +529,7 @@ impl_node_port_enum_params(void *object, int seq,
+               param = spa_pod_builder_add_object(&b,
+                       SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
+                       SPA_FORMAT_mediaType,      
SPA_POD_Id(SPA_MEDIA_TYPE_application),
+-                      SPA_FORMAT_mediaSubtype,   
SPA_POD_Id(SPA_MEDIA_SUBTYPE_control),
+-                      SPA_FORMAT_CONTROL_types,  
SPA_POD_CHOICE_FLAGS_Int(1u<<SPA_CONTROL_UMP));
++                      SPA_FORMAT_mediaSubtype,   
SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
+               break;
+ 
+       case SPA_PARAM_Format:
+@@ -541,8 +540,7 @@ impl_node_port_enum_params(void *object, int seq,
+               param = spa_pod_builder_add_object(&b,
+                       SPA_TYPE_OBJECT_Format, SPA_PARAM_Format,
+                       SPA_FORMAT_mediaType,      
SPA_POD_Id(SPA_MEDIA_TYPE_application),
+-                      SPA_FORMAT_mediaSubtype,   
SPA_POD_Id(SPA_MEDIA_SUBTYPE_control),
+-                      SPA_FORMAT_CONTROL_types,  
SPA_POD_Int(1u<<SPA_CONTROL_UMP));
++                      SPA_FORMAT_mediaSubtype,   
SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
+               break;
+ 
+       case SPA_PARAM_Buffers:
+@@ -635,7 +633,7 @@ static int port_set_format(void *object, struct seq_port 
*port,
+               port->have_format = false;
+       } else {
+               struct spa_audio_info info = { 0 };
+-              uint32_t types;
++              uint32_t types = 0;
+ 
+               if ((err = spa_format_parse(format, &info.media_type, 
&info.media_subtype)) < 0)
+                       return err;
+@@ -646,13 +644,12 @@ static int port_set_format(void *object, struct seq_port 
*port,
+ 
+               if ((err = spa_pod_parse_object(format,
+                               SPA_TYPE_OBJECT_Format, NULL,
+-                              SPA_FORMAT_CONTROL_types,  
SPA_POD_Int(&types))) < 0)
++                              SPA_FORMAT_CONTROL_types,  
SPA_POD_OPT_Int(&types))) < 0)
+                       return err;
+-              if (types != 1u << SPA_CONTROL_UMP)
+-                      return -EINVAL;
+ 
+               port->current_format = info;
+               port->have_format = true;
++              port->control_types = types;
+       }
+ 
+       port->info.change_mask |= SPA_PORT_CHANGE_MASK_RATE;
+diff --git a/spa/plugins/alsa/alsa-seq.c b/spa/plugins/alsa/alsa-seq.c
+index 04280f291..75d9c604a 100644
+--- a/spa/plugins/alsa/alsa-seq.c
++++ b/spa/plugins/alsa/alsa-seq.c
+@@ -586,7 +586,8 @@ static int prepare_buffer(struct seq_state *state, struct 
seq_port *port)
+       spa_pod_builder_init(&port->builder,
+                       port->buffer->buf->datas[0].data,
+                       port->buffer->buf->datas[0].maxsize);
+-        spa_pod_builder_push_sequence(&port->builder, &port->frame, 0);
++      spa_pod_builder_push_sequence(&port->builder, &port->frame, 0);
++      port->ev_offset = SPA_IDX_INVALID;
+ 
+       return 0;
+ }
+@@ -620,10 +621,8 @@ static int process_read(struct seq_state *state)
+       struct seq_stream *stream = &state->streams[SPA_DIRECTION_OUTPUT];
+       const bool ump = state->ump;
+       uint32_t i;
+-      uint32_t *data;
+       uint8_t midi1_data[MAX_EVENT_SIZE];
+       uint32_t ump_data[MAX_EVENT_SIZE];
+-      long size;
+       int res = -1;
+ 
+       /* copy all new midi events into their port buffers */
+@@ -631,10 +630,11 @@ static int process_read(struct seq_state *state)
+               const snd_seq_addr_t *addr;
+               struct seq_port *port;
+               uint64_t ev_time, diff;
+-              uint32_t offset;
++              uint32_t offset, ev_type;
+               void *event;
+-              uint8_t *midi1_ptr;
+-              size_t midi1_size = 0;
++              uint8_t *data_ptr;
++              size_t data_size = 0;
++              long size;
+               uint64_t ump_state = 0;
+               snd_seq_event_type_t SPA_UNUSED type;
+ 
+@@ -679,7 +679,7 @@ static int process_read(struct seq_state *state)
+                       continue;
+ 
+               if ((res = prepare_buffer(state, port)) < 0) {
+-                      spa_log_debug(state->log, "can't prepare buffer port:%p 
%d.%d: %s",
++                      spa_log_warn(state->log, "can't prepare buffer port:%p 
%d.%d: %s",
+                                       port, addr->client, addr->port, 
spa_strerror(res));
+                       continue;
+               }
+@@ -702,8 +702,8 @@ static int process_read(struct seq_state *state)
+ #ifdef HAVE_ALSA_UMP
+                       snd_seq_ump_event_t *ev = event;
+ 
+-                      data = (uint32_t*)&ev->ump[0];
+-                      size = 
spa_ump_message_size(snd_ump_msg_hdr_type(ev->ump[0])) * 4;
++                      data_ptr = (uint8_t*)&ev->ump[0];
++                      data_size = 
spa_ump_message_size(snd_ump_msg_hdr_type(ev->ump[0])) * 4;
+ #else
+                       spa_assert_not_reached();
+ #endif
+@@ -712,40 +712,69 @@ static int process_read(struct seq_state *state)
+ 
+                       snd_midi_event_reset_decode(stream->codec);
+                       if ((size = snd_midi_event_decode(stream->codec, 
midi1_data, sizeof(midi1_data), ev)) < 0) {
+-                              spa_log_warn(state->log, "decode failed: %s", 
snd_strerror(size));
++                              spa_log_warn(state->log, "decode failed: %s", 
snd_strerror(data_size));
+                               continue;
+                       }
++                      data_ptr = midi1_data;
++                      data_size = size;
++              }
++
++              ev_type = (port->control_types & (1u << SPA_CONTROL_UMP)) ?
++                      SPA_CONTROL_UMP : SPA_CONTROL_Midi;
+ 
+-                      midi1_ptr = midi1_data;
+-                      midi1_size = size;
++              spa_log_trace_fp(state->log, "event %d time:%"PRIu64" offset:%d 
size:%ld port:%d.%d",
++                              type, ev_time, offset, data_size, addr->client, 
addr->port);
++
++              if ((ump && ev_type == SPA_CONTROL_UMP) ||
++                  (!ump && ev_type == SPA_CONTROL_Midi)) {
++                      /* no conversion needed */
++                      spa_pod_builder_control(&port->builder, offset, 
ev_type);
++                      spa_pod_builder_bytes(&port->builder, data_ptr, 
data_size);
+               }
++              else if (ump) {
++                        bool continued = port->ev_offset != SPA_IDX_INVALID;
++
++                      /* UMP -> MIDI */
++                      size = spa_ump_to_midi((uint32_t*)data_ptr, data_size,
++                                      midi1_data, sizeof(midi1_data));
++                      if (size < 0)
++                              continue;
++
++                      if (!continued) {
++                              spa_pod_builder_control(&port->builder, offset, 
ev_type);
++                              port->ev_offset = 
spa_pod_builder_bytes_start(&port->builder);
++                              if (midi1_data[0] == 0xf0)
++                                      continued = true;
++                      } else {
++                              if (midi1_data[size-1] == 0xf7)
++                                      continued = false;
++                      }
++                      spa_pod_builder_bytes_append(&port->builder, 
port->ev_offset, midi1_data, size);
+ 
+-              do {
+-                      if (!ump) {
+-                              data = ump_data;
+-                              size = spa_ump_from_midi(&midi1_ptr, 
&midi1_size,
++                      if (!continued) {
++                              spa_pod_builder_bytes_end(&port->builder, 
port->ev_offset);
++                              port->ev_offset = SPA_IDX_INVALID;
++                      }
++              } else {
++                      /* MIDI -> UMP */
++                      while (data_size > 0) {
++                              size = spa_ump_from_midi(&data_ptr, &data_size,
+                                               ump_data, sizeof(ump_data), 0, 
&ump_state);
+                               if (size <= 0)
+                                       break;
+-                      }
+-
+-                      spa_log_trace_fp(state->log, "event %d time:%"PRIu64" 
offset:%d size:%ld port:%d.%d",
+-                                      type, ev_time, offset, size, 
addr->client, addr->port);
+ 
+-                      spa_pod_builder_control(&port->builder, offset, 
SPA_CONTROL_UMP);
+-                      spa_pod_builder_bytes(&port->builder, data, size);
+-
+-                      /* make sure we can fit at least one control event of 
max size otherwise
+-                       * we keep the event in the queue and try to copy it in 
the next cycle */
+-                      if (port->builder.state.offset +
+-                                      sizeof(struct spa_pod_control) +
+-                                      MAX_EVENT_SIZE > 
port->buffer->buf->datas[0].maxsize)
+-                              goto done;
++                              spa_pod_builder_control(&port->builder, offset, 
ev_type);
++                              spa_pod_builder_bytes(&port->builder, ump_data, 
size);
++                      }
++              }
+ 
+-              } while (!ump);
++              /* make sure we can fit at least one control event of max size 
otherwise
++               * we keep the event in the queue and try to copy it in the 
next cycle */
++              if (port->builder.state.offset +
++                              sizeof(struct spa_pod_control) +
++                              MAX_EVENT_SIZE > 
port->buffer->buf->datas[0].maxsize)
++                      break;
+         }
+-
+-done:
+       if (res < 0 && res != -EAGAIN)
+               spa_log_warn(state->log, "event read failed: %s", 
snd_strerror(res));
+ 
+@@ -760,6 +789,8 @@ done:
+                       continue;
+ 
+               if (prepare_buffer(state, port) >= 0) {
++                      if (port->ev_offset != SPA_IDX_INVALID)
++                              spa_pod_builder_bytes_end(&port->builder, 
port->ev_offset);
+                       spa_pod_builder_pop(&port->builder, &port->frame);
+ 
+                       port->buffer->buf->datas[0].chunk->offset = 0;
+@@ -846,9 +877,7 @@ static int process_write(struct seq_state *state)
+               SPA_POD_SEQUENCE_FOREACH(pod, c) {
+                       size_t body_size;
+                       uint8_t *body;
+-
+-                      if (c->type != SPA_CONTROL_UMP)
+-                              continue;
++                      int size;
+ 
+                       body = SPA_POD_BODY(&c->value);
+                       body_size = SPA_POD_BODY_SIZE(&c->value);
+@@ -862,33 +891,67 @@ static int process_write(struct seq_state *state)
+ 
+                       if (ump) {
+ #ifdef HAVE_ALSA_UMP
++                              uint8_t *ump_data;
++                              uint32_t data[MAX_EVENT_SIZE];
+                               snd_seq_ump_event_t ev;
+ 
+-                              snd_seq_ump_ev_clear(&ev);
+-                              snd_seq_ev_set_ump_data(&ev, body, 
SPA_MIN(sizeof(ev.ump), (size_t)body_size));
+-                              snd_seq_ev_set_source(&ev, 
state->event.addr.port);
+-                              snd_seq_ev_set_dest(&ev, port->addr.client, 
port->addr.port);
+-                              snd_seq_ev_schedule_real(&ev, 
state->event.queue_id, 0, &out_rt);
+-
+-                              if ((err = 
snd_seq_ump_event_output(state->event.hndl, &ev)) < 0) {
+-                                      spa_log_warn(state->log, "failed to 
output event: %s",
+-                                                      snd_strerror(err));
+-                              }
++                              do {
++                                      switch (c->type) {
++                                      case SPA_CONTROL_UMP:
++                                              ump_data = body;
++                                              size = body_size;
++                                              body_size = 0;
++                                              break;
++                                      case SPA_CONTROL_Midi:
++                                              size = spa_ump_from_midi(&body, 
&body_size,
++                                                              data, 
sizeof(data), 0, &port->ump_state);
++                                              ump_data = (uint8_t*)data;
++                                              break;
++                                      default:
++                                              size = 0;
++                                              body_size = 0;
++                                              continue;
++                                      }
++                                      if (size <= 0)
++                                              break;
++
++                                      snd_seq_ump_ev_clear(&ev);
++                                      snd_seq_ev_set_ump_data(&ev, ump_data, 
SPA_MIN(sizeof(ev.ump), (size_t)size));
++                                      snd_seq_ev_set_source(&ev, 
state->event.addr.port);
++                                      snd_seq_ev_set_dest(&ev, 
port->addr.client, port->addr.port);
++                                      snd_seq_ev_schedule_real(&ev, 
state->event.queue_id, 0, &out_rt);
++
++                                      if ((err = 
snd_seq_ump_event_output(state->event.hndl, &ev)) < 0) {
++                                              spa_log_warn(state->log, 
"failed to output event: %s",
++                                                              
snd_strerror(err));
++                                      }
++                              } while (body_size > 0);
+ #else
+                               spa_assert_not_reached();
+ #endif
+                       } else {
+                               snd_seq_event_t ev;
+                               uint8_t data[MAX_EVENT_SIZE];
+-                              int size;
++                              uint8_t *midi_data;
+ 
+-                              if ((size = spa_ump_to_midi((uint32_t *)body, 
body_size, data, sizeof(data))) <= 0)
++                              switch (c->type) {
++                              case SPA_CONTROL_UMP:
++                                      if ((size = spa_ump_to_midi((uint32_t 
*)body, body_size, data, sizeof(data))) <= 0)
++                                              continue;
++                                      midi_data = data;
++                                      break;
++                              case SPA_CONTROL_Midi:
++                                      midi_data = body;
++                                      size = body_size;
++                                      break;
++                              default:
+                                       continue;
++                              }
+ 
+                               if (first)
+                                       snd_seq_ev_clear(&ev);
+ 
+-                              if ((size = 
snd_midi_event_encode(stream->codec, data, size, &ev)) < 0) {
++                              if ((size = 
snd_midi_event_encode(stream->codec, midi_data, size, &ev)) < 0) {
+                                       spa_log_warn(state->log, "failed to 
encode event: %s", snd_strerror(size));
+                                       
snd_midi_event_reset_encode(stream->codec);
+                                       first = true;
+diff --git a/spa/plugins/alsa/alsa-seq.h b/spa/plugins/alsa/alsa-seq.h
+index 274311c70..7e9fc4297 100644
+--- a/spa/plugins/alsa/alsa-seq.h
++++ b/spa/plugins/alsa/alsa-seq.h
+@@ -80,7 +80,10 @@ struct seq_port {
+       struct buffer *buffer;
+       struct spa_pod_builder builder;
+       struct spa_pod_frame frame;
++      uint32_t ev_offset;
++      uint64_t ump_state;
+ 
++      uint32_t control_types;
+       struct spa_audio_info current_format;
+       unsigned int have_format:1;
+       unsigned int valid:1;
+diff --git a/spa/plugins/control/mixer.c b/spa/plugins/control/mixer.c
+index e97072d45..cfe3c394b 100644
+--- a/spa/plugins/control/mixer.c
++++ b/spa/plugins/control/mixer.c
+@@ -298,7 +298,8 @@ static int port_enum_formats(void *object, struct port 
*port,
+               *param = spa_pod_builder_add_object(builder,
+                       SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
+                       SPA_FORMAT_mediaType,      
SPA_POD_Id(SPA_MEDIA_TYPE_application),
+-                      SPA_FORMAT_mediaSubtype,   
SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
++                      SPA_FORMAT_mediaSubtype,   
SPA_POD_Id(SPA_MEDIA_SUBTYPE_control),
++                      SPA_FORMAT_CONTROL_types,  
SPA_POD_CHOICE_FLAGS_Int(SPA_ID_INVALID));
+               break;
+       default:
+               return 0;
+diff --git a/src/modules/module-jack-tunnel.c 
b/src/modules/module-jack-tunnel.c
+index 76ac73c8d..7cce66b0b 100644
+--- a/src/modules/module-jack-tunnel.c
++++ b/src/modules/module-jack-tunnel.c
+@@ -247,7 +247,6 @@ static void midi_to_jack(struct impl *impl, float *dst, 
float *src, uint32_t n_s
+       struct spa_pod_sequence *seq;
+       struct spa_pod_control *c;
+       int res;
+-      bool in_sysex = false;
+       uint8_t tmp[n_samples * 4];
+       size_t tmp_size = 0;
+ 
+@@ -267,23 +266,23 @@ static void midi_to_jack(struct impl *impl, float *dst, 
float *src, uint32_t n_s
+ 
+               if (c->type != SPA_CONTROL_UMP)
+                       continue;
++              switch (c->type) {
++              case SPA_CONTROL_UMP:
++                      size = spa_ump_to_midi(SPA_POD_BODY(&c->value),
++                                      SPA_POD_BODY_SIZE(&c->value), 
&tmp[tmp_size], sizeof(tmp) - tmp_size);
++                      if (size <= 0)
++                              continue;
++                      tmp_size += size;
++                      break;
++              case SPA_CONTROL_Midi:
++                      tmp_size = SPA_POD_BODY_SIZE(&c->value);
++                      memcpy(tmp, SPA_POD_BODY(&c->value), 
SPA_MIN(sizeof(tmp), tmp_size));
++                      break;
++              }
+ 
+-              size = spa_ump_to_midi(SPA_POD_BODY(&c->value),
+-                              SPA_POD_BODY_SIZE(&c->value), &tmp[tmp_size], 
sizeof(tmp) - tmp_size);
+-              if (size <= 0)
+-                      continue;
+-
+-              if (impl->fix_midi)
+-                      fix_midi_event(&tmp[tmp_size], size);
+-
+-              if (!in_sysex && tmp[tmp_size] == 0xf0)
+-                      in_sysex = true;
+-
+-              tmp_size += size;
+-              if (in_sysex && tmp[tmp_size-1] == 0xf7)
+-                      in_sysex = false;
+-
+-              if (!in_sysex) {
++              if (tmp[0] != 0xf0 || tmp[tmp_size-1] == 0xf7) {
++                      if (impl->fix_midi)
++                              fix_midi_event(tmp, tmp_size);
+                       if ((res = jack.midi_event_write(dst, c->offset, tmp, 
tmp_size)) < 0)
+                               pw_log_warn("midi %p: can't write event: %s", 
dst,
+                                               spa_strerror(res));
+-- 
+2.49.0
+

diff --git 
a/media-video/pipewire/files/1.4.3/0004-adapter-negotiate-from-target-to-follower.patch
 
b/media-video/pipewire/files/1.4.3/0004-adapter-negotiate-from-target-to-follower.patch
new file mode 100644
index 000000000000..81577ad1a0d2
--- /dev/null
+++ 
b/media-video/pipewire/files/1.4.3/0004-adapter-negotiate-from-target-to-follower.patch
@@ -0,0 +1,202 @@
+From c507c4b0ffa094d92c76ad4589ad776b677d94d2 Mon Sep 17 00:00:00 2001
+Message-ID: 
<c507c4b0ffa094d92c76ad4589ad776b677d94d2.1748327071.git....@gentoo.org>
+In-Reply-To: 
<483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git....@gentoo.org>
+References: 
<483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git....@gentoo.org>
+From: Wim Taymans <[email protected]>
+Date: Mon, 26 May 2025 15:44:51 +0200
+Subject: [PATCH 4/5] adapter: negotiate from target to follower
+
+Since 3abda54d80cb02cacb25b9a66ce2808dc4615b34 we prefer the format
+of the filter. This reverses the selection of the default value when
+negotiating buffers from the target to the follower.
+
+If the follower does not select a reasonable value for the buffer size,
+for example, this then results in wrongly sized buffers.
+
+Fix this by reversing the order of allocation from target to follower
+where we let the target (converter) select a default value, which is
+more likely to be correct.
+
+See #4713, #4619
+---
+ spa/plugins/audioconvert/audioadapter.c | 39 ++++++++-----------------
+ spa/plugins/videoconvert/videoadapter.c | 39 ++++++++-----------------
+ 2 files changed, 24 insertions(+), 54 deletions(-)
+
+diff --git a/spa/plugins/audioconvert/audioadapter.c 
b/spa/plugins/audioconvert/audioadapter.c
+index 43a47e25c..f15d5a4ca 100644
+--- a/spa/plugins/audioconvert/audioadapter.c
++++ b/spa/plugins/audioconvert/audioadapter.c
+@@ -442,8 +442,8 @@ static int negotiate_buffers(struct impl *this)
+ 
+       state = 0;
+       param = NULL;
+-      if ((res = node_port_enum_params_sync(this, this->follower,
+-                              this->direction, 0,
++      if ((res = node_port_enum_params_sync(this, this->target,
++                              SPA_DIRECTION_REVERSE(this->direction), 0,
+                               SPA_PARAM_Buffers, &state,
+                               param, &param, &b)) < 0) {
+               if (res == -ENOENT)
+@@ -456,8 +456,8 @@ static int negotiate_buffers(struct impl *this)
+       }
+ 
+       state = 0;
+-      if ((res = node_port_enum_params_sync(this, this->target,
+-                              SPA_DIRECTION_REVERSE(this->direction), 0,
++      if ((res = node_port_enum_params_sync(this, this->follower,
++                              this->direction, 0,
+                               SPA_PARAM_Buffers, &state,
+                               param, &param, &b)) != 1) {
+               debug_params(this, this->target,
+@@ -497,7 +497,7 @@ static int negotiate_buffers(struct impl *this)
+       if (this->async)
+               buffers = SPA_MAX(2u, buffers);
+ 
+-      spa_log_debug(this->log, "%p: buffers:%d, blocks:%d, size:%d, stride:%d 
align:%d %d:%d",
++      spa_log_info(this->log, "%p: buffers:%d, blocks:%d, size:%d, stride:%d 
align:%d %d:%d",
+                       this, buffers, blocks, size, stride, align, 
follower_alloc, conv_alloc);
+ 
+       align = SPA_MAX(align, this->max_align);
+@@ -941,27 +941,13 @@ static int negotiate_format(struct impl *this)
+       spa_node_send_command(this->follower,
+                       &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_ParamBegin));
+ 
+-      /* first try the ideal converter format, which is likely passthrough */
+-      tstate = 0;
+-      fres = node_port_enum_params_sync(this, this->target,
+-                              SPA_DIRECTION_REVERSE(this->direction), 0,
+-                              SPA_PARAM_EnumFormat, &tstate,
+-                              NULL, &format, &b);
+-      if (fres == 1) {
+-              fstate = 0;
+-              res = node_port_enum_params_sync(this, this->follower,
+-                                      this->direction, 0,
+-                                      SPA_PARAM_EnumFormat, &fstate,
+-                                      format, &format, &b);
+-              if (res == 1)
+-                      goto found;
+-      }
+-
+-      /* then try something the follower can accept */
++      /* The target has been negotiated on its other ports and so it can 
propose
++       * a passthrough format or an ideal conversion. We use the suggestions 
of the
++       * target to find the best follower format */
+       for (fstate = 0;;) {
+               format = NULL;
+-              res = node_port_enum_params_sync(this, this->follower,
+-                                      this->direction, 0,
++              res = node_port_enum_params_sync(this, this->target,
++                                      SPA_DIRECTION_REVERSE(this->direction), 
0,
+                                       SPA_PARAM_EnumFormat, &fstate,
+                                       NULL, &format, &b);
+ 
+@@ -971,8 +957,8 @@ static int negotiate_format(struct impl *this)
+                       break;
+ 
+               tstate = 0;
+-              fres = node_port_enum_params_sync(this, this->target,
+-                                      SPA_DIRECTION_REVERSE(this->direction), 
0,
++              fres = node_port_enum_params_sync(this, this->follower,
++                                      this->direction, 0,
+                                       SPA_PARAM_EnumFormat, &tstate,
+                                       format, &format, &b);
+               if (fres == 0 && res == 1)
+@@ -981,7 +967,6 @@ static int negotiate_format(struct impl *this)
+               res = fres;
+               break;
+       }
+-found:
+       if (format == NULL) {
+               debug_params(this, this->follower, this->direction, 0,
+                               SPA_PARAM_EnumFormat, format, "follower 
format", res);
+diff --git a/spa/plugins/videoconvert/videoadapter.c 
b/spa/plugins/videoconvert/videoadapter.c
+index 078c90553..e10a8adf5 100644
+--- a/spa/plugins/videoconvert/videoadapter.c
++++ b/spa/plugins/videoconvert/videoadapter.c
+@@ -416,8 +416,8 @@ static int negotiate_buffers(struct impl *this)
+ 
+       state = 0;
+       param = NULL;
+-      if ((res = spa_node_port_enum_params_sync(this->follower,
+-                              this->direction, 0,
++      if ((res = spa_node_port_enum_params_sync(this->target,
++                              SPA_DIRECTION_REVERSE(this->direction), 0,
+                               SPA_PARAM_Buffers, &state,
+                               param, &param, &b)) < 0) {
+               if (res == -ENOENT)
+@@ -430,8 +430,8 @@ static int negotiate_buffers(struct impl *this)
+       }
+ 
+       state = 0;
+-      if ((res = spa_node_port_enum_params_sync(this->target,
+-                              SPA_DIRECTION_REVERSE(this->direction), 0,
++      if ((res = spa_node_port_enum_params_sync(this->follower,
++                              this->direction, 0,
+                               SPA_PARAM_Buffers, &state,
+                               param, &param, &b)) != 1) {
+               debug_params(this, this->target,
+@@ -471,7 +471,7 @@ static int negotiate_buffers(struct impl *this)
+       if (this->async)
+               buffers = SPA_MAX(2u, buffers);
+ 
+-      spa_log_debug(this->log, "%p: buffers:%d, blocks:%d, size:%d, stride:%d 
align:%d %d:%d",
++      spa_log_info(this->log, "%p: buffers:%d, blocks:%d, size:%d, stride:%d 
align:%d %d:%d",
+                       this, buffers, blocks, size, stride, align, 
follower_alloc, conv_alloc);
+ 
+       align = SPA_MAX(align, this->max_align);
+@@ -908,27 +908,13 @@ static int negotiate_format(struct impl *this)
+       spa_node_send_command(this->follower,
+                       &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_ParamBegin));
+ 
+-      /* first try the ideal converter format, which is likely passthrough */
+-      tstate = 0;
+-      fres = spa_node_port_enum_params_sync(this->target,
+-                              SPA_DIRECTION_REVERSE(this->direction), 0,
+-                              SPA_PARAM_EnumFormat, &tstate,
+-                              NULL, &format, &b);
+-      if (fres == 1) {
+-              fstate = 0;
+-              res = spa_node_port_enum_params_sync(this->follower,
+-                                      this->direction, 0,
+-                                      SPA_PARAM_EnumFormat, &fstate,
+-                                      format, &format, &b);
+-              if (res == 1)
+-                      goto found;
+-      }
+-
+-      /* then try something the follower can accept */
++      /* The target has been negotiated on its other ports and so it can 
propose
++       * a passthrough format or an ideal conversion. We use the suggestions 
of the
++       * target to find the best follower format */
+       for (fstate = 0;;) {
+               format = NULL;
+-              res = spa_node_port_enum_params_sync(this->follower,
+-                                      this->direction, 0,
++              res = spa_node_port_enum_params_sync(this->target,
++                                      SPA_DIRECTION_REVERSE(this->direction), 
0,
+                                       SPA_PARAM_EnumFormat, &fstate,
+                                       NULL, &format, &b);
+ 
+@@ -938,8 +924,8 @@ static int negotiate_format(struct impl *this)
+                       break;
+ 
+               tstate = 0;
+-              fres = spa_node_port_enum_params_sync(this->target,
+-                                      SPA_DIRECTION_REVERSE(this->direction), 
0,
++              fres = spa_node_port_enum_params_sync(this->follower,
++                                      this->direction, 0,
+                                       SPA_PARAM_EnumFormat, &tstate,
+                                       format, &format, &b);
+               if (fres == 0 && res == 1)
+@@ -948,7 +934,6 @@ static int negotiate_format(struct impl *this)
+               res = fres;
+               break;
+       }
+-found:
+       if (format == NULL) {
+               debug_params(this, this->follower, this->direction, 0,
+                               SPA_PARAM_EnumFormat, format, "follower 
format", res);
+-- 
+2.49.0
+

diff --git 
a/media-video/pipewire/files/1.4.3/0005-gst-src-Change-DEFAULT_MIN_BUFFERS-back-to-1.patch
 
b/media-video/pipewire/files/1.4.3/0005-gst-src-Change-DEFAULT_MIN_BUFFERS-back-to-1.patch
new file mode 100644
index 000000000000..c6b4ee66dafb
--- /dev/null
+++ 
b/media-video/pipewire/files/1.4.3/0005-gst-src-Change-DEFAULT_MIN_BUFFERS-back-to-1.patch
@@ -0,0 +1,39 @@
+From eda42ef2fc9eaa41dd7dc1582ae062d2ce727612 Mon Sep 17 00:00:00 2001
+Message-ID: 
<eda42ef2fc9eaa41dd7dc1582ae062d2ce727612.1748327071.git....@gentoo.org>
+In-Reply-To: 
<483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git....@gentoo.org>
+References: 
<483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git....@gentoo.org>
+From: Robert Mader <[email protected]>
+Date: Sun, 25 May 2025 03:57:38 +0200
+Subject: [PATCH 5/5] gst: src: Change DEFAULT_MIN_BUFFERS back to 1
+
+The change from 1 to 8 was done without justification in the commit
+message and possibly for debug purposes. Unfortunately it breaks
+negotiation with the libcamera virtual pipeline, which defaults to
+4 buffers.
+
+Set the the value to 1 again as successful negotiation - even with an
+unusually low number of buffers - is usually more desirable than an
+error.
+
+Fixes: 98b7dc7c0 ("gst: don't do set_caps from the pipewire callback")
+(cherry picked from commit e81fb773224fb5cd4b9399393ca2d2bfab7f4273)
+---
+ src/gst/gstpipewiresrc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/gst/gstpipewiresrc.c b/src/gst/gstpipewiresrc.c
+index 694cbea0e..994534c60 100644
+--- a/src/gst/gstpipewiresrc.c
++++ b/src/gst/gstpipewiresrc.c
+@@ -41,7 +41,7 @@ GST_DEBUG_CATEGORY_STATIC (pipewire_src_debug);
+ #define GST_CAT_DEFAULT pipewire_src_debug
+ 
+ #define DEFAULT_ALWAYS_COPY     false
+-#define DEFAULT_MIN_BUFFERS     8
++#define DEFAULT_MIN_BUFFERS     1
+ #define DEFAULT_MAX_BUFFERS     INT32_MAX
+ #define DEFAULT_RESEND_LAST     false
+ #define DEFAULT_KEEPALIVE_TIME  0
+-- 
+2.49.0
+

diff --git a/media-video/pipewire/pipewire-1.4.3.ebuild 
b/media-video/pipewire/pipewire-1.4.3-r1.ebuild
similarity index 100%
rename from media-video/pipewire/pipewire-1.4.3.ebuild
rename to media-video/pipewire/pipewire-1.4.3-r1.ebuild


Reply via email to