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@gentoo.org>
This commit is contained in:
Sam James
2025-05-27 07:26:43 +01:00
parent 600c47bf1d
commit 2e4ef773aa
6 changed files with 1007 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
From 483b59a9d95aa084dfcd1c17e13ee27bd106d4b0 Mon Sep 17 00:00:00 2001
Message-ID: <483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git.sam@gentoo.org>
From: Wim Taymans <wtaymans@redhat.com>
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

View File

@@ -0,0 +1,265 @@
From 76db05a0f8edb8b7d4d896d3860bc555934ad383 Mon Sep 17 00:00:00 2001
Message-ID: <76db05a0f8edb8b7d4d896d3860bc555934ad383.1748327071.git.sam@gentoo.org>
In-Reply-To: <483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git.sam@gentoo.org>
References: <483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git.sam@gentoo.org>
From: Wim Taymans <wtaymans@redhat.com>
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

View File

@@ -0,0 +1,451 @@
From 06941f7315c3ca814771cc8b6612c3d01a8bf968 Mon Sep 17 00:00:00 2001
Message-ID: <06941f7315c3ca814771cc8b6612c3d01a8bf968.1748327071.git.sam@gentoo.org>
In-Reply-To: <483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git.sam@gentoo.org>
References: <483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git.sam@gentoo.org>
From: Wim Taymans <wtaymans@redhat.com>
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

View File

@@ -0,0 +1,202 @@
From c507c4b0ffa094d92c76ad4589ad776b677d94d2 Mon Sep 17 00:00:00 2001
Message-ID: <c507c4b0ffa094d92c76ad4589ad776b677d94d2.1748327071.git.sam@gentoo.org>
In-Reply-To: <483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git.sam@gentoo.org>
References: <483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git.sam@gentoo.org>
From: Wim Taymans <wtaymans@redhat.com>
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

View File

@@ -0,0 +1,39 @@
From eda42ef2fc9eaa41dd7dc1582ae062d2ce727612 Mon Sep 17 00:00:00 2001
Message-ID: <eda42ef2fc9eaa41dd7dc1582ae062d2ce727612.1748327071.git.sam@gentoo.org>
In-Reply-To: <483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git.sam@gentoo.org>
References: <483b59a9d95aa084dfcd1c17e13ee27bd106d4b0.1748327071.git.sam@gentoo.org>
From: Robert Mader <robert.mader@collabora.com>
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