add message handler for audio pipeline bus

This commit is contained in:
F. Duncanh
2025-08-07 06:10:19 -04:00
parent 93b2612477
commit 532ac612f3
4 changed files with 69 additions and 15 deletions

View File

@@ -45,6 +45,7 @@ typedef struct audio_renderer_s {
GstElement *appsrc;
GstElement *pipeline;
GstElement *volume;
GstBus *bus;
unsigned char ct;
} audio_renderer_t ;
static audio_renderer_t *renderer_type[NFORMATS];
@@ -186,7 +187,7 @@ void audio_renderer_init(logger_t *render_logger, const char* audiosink, const b
g_assert (renderer_type[i]->pipeline);
gst_pipeline_use_clock(GST_PIPELINE_CAST(renderer_type[i]->pipeline), clock);
renderer_type[i]->bus = gst_element_get_bus(renderer_type[i]->pipeline);
renderer_type[i]->appsrc = gst_bin_get_by_name (GST_BIN (renderer_type[i]->pipeline), "audio_source");
renderer_type[i]->volume = gst_bin_get_by_name (GST_BIN (renderer_type[i]->pipeline), "volume");
switch (i) {
@@ -367,6 +368,8 @@ void audio_renderer_flush() {
void audio_renderer_destroy() {
audio_renderer_stop();
for (int i = 0; i < NFORMATS ; i++ ) {
gst_object_unref (renderer_type[i]->bus);
renderer_type[i]->bus = NULL;
gst_object_unref (renderer_type[i]->volume);
renderer_type[i]->volume = NULL;
gst_object_unref (renderer_type[i]->appsrc);
@@ -376,3 +379,41 @@ void audio_renderer_destroy() {
free(renderer_type[i]);
}
}
static gboolean gstreamer_audio_pipeline_bus_callback(GstBus *bus, GstMessage *message, void *loop) {
switch (GST_MESSAGE_TYPE(message)) {
case GST_MESSAGE_ERROR: {
GError *err;
gchar *debug;
gst_message_parse_error (message, &err, &debug);
logger_log(logger, LOGGER_INFO, "GStreamer error (audio): %s %s", GST_MESSAGE_SRC_NAME(message),err->message);
g_error_free(err);
g_free(debug);
if (renderer->appsrc) {
gst_app_src_end_of_stream (GST_APP_SRC(renderer->appsrc));
}
gst_bus_set_flushing(bus, TRUE);
gst_element_set_state (renderer->pipeline, GST_STATE_READY);
g_main_loop_quit( (GMainLoop *) loop);
break;
}
case GST_MESSAGE_EOS:
logger_log(logger, LOGGER_INFO, "GStreamer: End-Of-Stream (audio)");
break;
case GST_MESSAGE_ELEMENT:
// many "level" messages may be sent
break;
default:
/* unhandled message */
logger_log(logger, LOGGER_DEBUG,"GStreamer unhandled audio bus message: src = %s type = %s",
GST_MESSAGE_SRC_NAME(message), GST_MESSAGE_TYPE_NAME(message));
break;
}
return TRUE;
}
unsigned int audio_renderer_listen(void *loop, int id) {
g_assert(id >= 0 && id < NFORMATS);
return (unsigned int) gst_bus_add_watch(renderer_type[id]->bus,(GstBusFunc)
gstreamer_audio_pipeline_bus_callback, (gpointer) loop);
}

View File

@@ -40,7 +40,7 @@ void audio_renderer_render_buffer(unsigned char* data, int *data_len, unsigned s
void audio_renderer_set_volume(double volume);
void audio_renderer_flush();
void audio_renderer_destroy();
unsigned int audio_renderer_listen(void *loop, int id);
#ifdef __cplusplus
}
#endif

View File

@@ -647,7 +647,7 @@ static void get_stream_status_name(GstStreamStatusType type, char *name, size_t
}
}
gboolean gstreamer_pipeline_bus_callback(GstBus *bus, GstMessage *message, void *loop) {
static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *message, void *loop) {
GstState old_state, new_state;
const gchar no_state[] = "";
const gchar *old_state_name = no_state, *new_state_name = no_state;
@@ -756,7 +756,7 @@ gboolean gstreamer_pipeline_bus_callback(GstBus *bus, GstMessage *message, void
gchar *debug;
gboolean flushing;
gst_message_parse_error (message, &err, &debug);
logger_log(logger, LOGGER_INFO, "GStreamer error: %s %s", GST_MESSAGE_SRC_NAME(message),err->message);
logger_log(logger, LOGGER_INFO, "GStreamer error (video): %s %s", GST_MESSAGE_SRC_NAME(message),err->message);
if (!hls_video && strstr(err->message,"Internal data stream error")) {
logger_log(logger, LOGGER_INFO,
"*** This is a generic GStreamer error that usually means that GStreamer\n"
@@ -780,7 +780,7 @@ gboolean gstreamer_pipeline_bus_callback(GstBus *bus, GstMessage *message, void
}
case GST_MESSAGE_EOS:
/* end-of-stream */
logger_log(logger, LOGGER_INFO, "GStreamer: End-Of-Stream");
logger_log(logger, LOGGER_INFO, "GStreamer: End-Of-Stream (video)");
if (hls_video) {
gst_bus_set_flushing(bus, TRUE);
gst_element_set_state (renderer_type[type]->pipeline, GST_STATE_READY);
@@ -1007,5 +1007,5 @@ void video_renderer_seek(float position) {
unsigned int video_renderer_listen(void *loop, int id) {
g_assert(id >= 0 && id < n_renderers);
return (unsigned int) gst_bus_add_watch(renderer_type[id]->bus,(GstBusFunc)
gstreamer_pipeline_bus_callback, (gpointer) loop);
gstreamer_video_pipeline_bus_callback, (gpointer) loop);
}

View File

@@ -164,7 +164,8 @@ static double db_high = 0.0;
static bool taper_volume = false;
static double initial_volume = 0.0;
static bool h265_support = false;
static int n_renderers = 0;
static int n_video_renderers = 0;
static int n_audio_renderers = 0;
static bool hls_support = false;
static std::string url = "";
static guint gst_x11_window_id = 0;
@@ -464,8 +465,10 @@ static guint g_unix_signal_add(gint signum, GSourceFunc handler, gpointer user_d
#endif
static void main_loop() {
guint gst_bus_watch_id[3] = { 0 };
g_assert(n_renderers <= 3);
guint gst_video_bus_watch_id[3] = { 0 };
g_assert(n_video_renderers <= 3);
guint gst_audio_bus_watch_id[2] = { 0 };
g_assert(n_audio_renderers <= 2);
GMainLoop *loop = g_main_loop_new(NULL,FALSE);
relaunch_video = false;
reset_loop = false;
@@ -475,18 +478,25 @@ static void main_loop() {
relaunch_video = true;
if (url.empty()) {
/* renderer[0] : jpeg coverart; renderer[1] h264 video; renderer[2] h265 video (optional) */
n_renderers = h265_support ? 3 : 2;
n_video_renderers = h265_support ? 3 : 2;
gst_x11_window_id = 0;
} else {
/* hls video will be rendered: renderer[0] : hls */
n_renderers = 1;
n_video_renderers = 1;
url.erase();
gst_x11_window_id = g_timeout_add(100, (GSourceFunc) x11_window_callback, (gpointer) loop);
}
for (int i = 0; i < n_renderers; i++) {
gst_bus_watch_id[i] = (guint) video_renderer_listen((void *)loop, i);
for (int i = 0; i < n_video_renderers; i++) {
gst_video_bus_watch_id[i] = (guint) video_renderer_listen((void *)loop, i);
}
}
if (use_audio) {
n_audio_renderers = 2;
for (int i = 0; i < n_audio_renderers; i++) {
gst_audio_bus_watch_id[i] = (guint) audio_renderer_listen((void *)loop, i);
}
}
missed_feedback = 0;
guint feedback_watch_id = g_timeout_add_seconds(1, (GSourceFunc) feedback_callback, (gpointer) loop);
guint reset_watch_id = g_timeout_add(100, (GSourceFunc) reset_callback, (gpointer) loop);
@@ -495,8 +505,11 @@ static void main_loop() {
guint sigint_watch_id = g_unix_signal_add(SIGINT, (GSourceFunc) sigint_callback, (gpointer) loop);
g_main_loop_run(loop);
for (int i = 0; i < n_renderers; i++) {
if (gst_bus_watch_id[i] > 0) g_source_remove(gst_bus_watch_id[i]);
for (int i = 0; i < n_video_renderers; i++) {
if (gst_video_bus_watch_id[i] > 0) g_source_remove(gst_video_bus_watch_id[i]);
}
for (int i = 0; i < n_audio_renderers; i++) {
if (gst_audio_bus_watch_id[i] > 0) g_source_remove(gst_audio_bus_watch_id[i]);
}
if (gst_x11_window_id > 0) g_source_remove(gst_x11_window_id);
if (sigint_watch_id > 0) g_source_remove(sigint_watch_id);