From 4543c26f8593e2b48ac6fa1c5b6fabd626d8632a Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Thu, 19 Dec 2019 17:25:28 +0200 Subject: bluez-alsa: update gst-helper to handle corking and use the Multimedia role on A2DP Bug-AGL: SPEC-2792 Change-Id: I2247550d6059c31596651e84fdd617f849722422 Signed-off-by: George Kiagiadakis (cherry picked from commit 40eb01c5c943509df2f4a52c3fe75a5d0cf0123b) --- ...-gstreamer-helper-application-for-interco.patch | 75 ++++++++++++++++++---- 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/0001-utils-add-a-gstreamer-helper-application-for-interco.patch b/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/0001-utils-add-a-gstreamer-helper-application-for-interco.patch index 37c03218..6c9a388c 100644 --- a/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/0001-utils-add-a-gstreamer-helper-application-for-interco.patch +++ b/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/0001-utils-add-a-gstreamer-helper-application-for-interco.patch @@ -1,4 +1,4 @@ -From 33555a493af67f3acc2129764a1b093aec6254d8 Mon Sep 17 00:00:00 2001 +From f2e6a0a324106b40195f88953e55a355875d2b1b Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Fri, 4 Oct 2019 20:51:24 +0300 Subject: [PATCH] utils: add a gstreamer helper application for interconnection @@ -24,8 +24,8 @@ Upstream-Status: Inappropriate --- configure.ac | 7 + utils/Makefile.am | 20 +++ - utils/gst-helper.c | 379 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 406 insertions(+) + utils/gst-helper.c | 432 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 459 insertions(+) create mode 100644 utils/gst-helper.c diff --git a/configure.ac b/configure.ac @@ -76,10 +76,10 @@ index 9057f2c..9790474 100644 +endif diff --git a/utils/gst-helper.c b/utils/gst-helper.c new file mode 100644 -index 0000000..1b021ee +index 0000000..de1d47c --- /dev/null +++ b/utils/gst-helper.c -@@ -0,0 +1,379 @@ +@@ -0,0 +1,432 @@ +/* Bluez-Alsa PipeWire integration GStreamer helper + * + * Copyright © 2016-2019 Arkadiusz Bokowy @@ -123,6 +123,9 @@ index 0000000..1b021ee + int ba_pcm_ctrl_fd; + /* the gstreamer pipelines (sink & source) */ + GstElement *pipeline[2]; ++ /* the queue & pwaudiosink of the sink pipeline */ ++ GstElement *queue; ++ GstElement *pwelem; +}; + +static struct ba_dbus_ctx dbus_ctx; @@ -141,11 +144,44 @@ index 0000000..1b021ee + main_loop_on = false; +} + ++static GstBusSyncReply ++bus_sync_handler(GstBus *bus, GstMessage *message, gpointer user_data) ++{ ++ struct worker *w = user_data; ++ GstState s; ++ ++ switch (GST_MESSAGE_TYPE (message)) { ++ case GST_MESSAGE_REQUEST_STATE: ++ gst_message_parse_request_state (message, &s); ++ ++ debug ("corked: %d", (s == GST_STATE_PAUSED)); ++ ++ /* drop queue data when corked */ ++ g_object_set (w->queue, ++ "leaky", (s == GST_STATE_PAUSED) ? 2 /* downstream */ : 0 /* no */, ++ NULL); ++ gst_element_set_state (w->pwelem, s); ++ ++ /* flush the queue when resuming */ ++ if (s == GST_STATE_PLAYING) { ++ gst_element_send_event (w->queue, gst_event_new_flush_start ()); ++ gst_element_send_event (w->queue, gst_event_new_flush_stop (FALSE)); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ gst_message_unref (message); ++ return GST_BUS_DROP; ++} ++ +static int +worker_start_pipeline(struct worker *w, int id, int mode, int profile) +{ + GError *gerr = NULL; + DBusError err = DBUS_ERROR_INIT; ++ const gchar * role = NULL; + + if (w->pipeline[id]) + return 0; @@ -172,9 +208,15 @@ index 0000000..1b021ee + "! rawaudioparse use-sink-caps=true ! m. " + /* take the mixer output, convert and push to pipewire */ + "m.src ! capsfilter name=capsf3 ! audioconvert ! audioresample " -+ "! audio/x-raw,format=F32LE,rate=48000 ! pwaudiosink name=pwelem", ++ "! audio/x-raw,format=F32LE,rate=48000 ! identity sync=true " ++ "! queue name=queue leaky=no max-size-time=0 max-size-buffers=0 max-size-bytes=192000 " ++ "! pwaudiosink name=pwelem", + &gerr); -+ } else if (mode == BA_PCM_FLAG_SOURCE && profile == BA_PCM_FLAG_PROFILE_SCO) { ++ ++ /* a2dp is for music, sco is for calls */ ++ role = (profile == BA_PCM_FLAG_PROFILE_A2DP) ? "Multimedia" : "Communication"; ++ } ++ else if (mode == BA_PCM_FLAG_SOURCE && profile == BA_PCM_FLAG_PROFILE_SCO) { + debug("source start"); + w->pipeline[id] = gst_parse_launch( + /* read from pipewire and put the buffers on a leaky queue, which @@ -183,9 +225,11 @@ index 0000000..1b021ee + 9600 bytes = 50ms @ F32LE/1ch/48000 + */ + "pwaudiosrc name=pwelem ! audio/x-raw,format=F32LE,rate=48000 " -+ "! queue leaky=downstream max-size-time=0 max-size-buffers=0 max-size-bytes=9600 " ++ "! queue name=queue leaky=downstream max-size-time=0 max-size-buffers=0 max-size-bytes=9600 " + "! audioconvert ! audioresample ! capsfilter name=capsf " + "! fdsink name=fdelem", &gerr); ++ ++ role = "Communication"; + } + + if (gerr) { @@ -198,6 +242,7 @@ index 0000000..1b021ee + g_autofree gchar *capsstr = NULL; + g_autoptr (GstElement) fdelem = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "fdelem"); + g_autoptr (GstElement) pwelem = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "pwelem"); ++ g_autoptr (GstElement) queue = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "queue"); + g_autoptr (GstElement) capsf = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "capsf"); + g_autoptr (GstElement) capsf2 = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "capsf2"); + g_autoptr (GstElement) capsf3 = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "capsf3"); @@ -208,8 +253,9 @@ index 0000000..1b021ee + "rate", G_TYPE_INT, w->ba_pcm.sampling, + NULL); + g_autoptr (GstStructure) stream_props = gst_structure_new("props", -+ "media.role", G_TYPE_STRING, "Communication", -+ "wireplumber.keep-linked", G_TYPE_STRING, "1", ++ "media.role", G_TYPE_STRING, role, ++ "bluealsa.profile", G_TYPE_STRING, ++ (profile == BA_PCM_FLAG_PROFILE_SCO) ? "sco" : "a2dp", + NULL); + + g_object_set(capsf, "caps", caps, NULL); @@ -224,6 +270,13 @@ index 0000000..1b021ee + g_object_set(fdelem, "fd", w->ba_pcm_fd, NULL); + g_object_set(pwelem, "stream-properties", stream_props, NULL); + ++ if (mode == BA_PCM_FLAG_SINK) { ++ g_autoptr (GstBus) bus = gst_pipeline_get_bus(GST_PIPELINE(w->pipeline[id])); ++ gst_bus_set_sync_handler(bus, bus_sync_handler, w, NULL); ++ w->queue = queue; ++ w->pwelem = pwelem; ++ } ++ + gst_element_set_state(w->pipeline[id], GST_STATE_PLAYING); + } + @@ -460,5 +513,5 @@ index 0000000..1b021ee + return ret; +} -- -2.23.0 +2.24.0 -- cgit 1.2.3-korg