[Mesa-dev] [PATCH kmscube v2 06/10] gst-decoder.c: add bus watch

Carlos Rafael Giani dv at pseudoterminal.org
Tue Apr 11 08:27:47 UTC 2017


The bus watch is useful for logging state changes, printing out
info/warning/error messages and handling common GStreamer activities like
latency redistribution and state change requests (that are sent by
elements since they are not allowed to directly change the state).

State changes and error messages can also cause a dot graph of the
pipeline to be generated if the GST_DEBUG_DUMP_DOT_DIR environment
variable is set. See the GST_DEBUG_BIN_TO_DOT_FILE documentation for more.

Signed-off-by: Carlos Rafael Giani <dv at pseudoterminal.org>
---
 gst-decoder.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/gst-decoder.c b/gst-decoder.c
index 05d73b7..d1cb18c 100644
--- a/gst-decoder.c
+++ b/gst-decoder.c
@@ -136,11 +136,108 @@ element_added_cb(GstBin *bin, GstElement *element, gpointer user_data)
 	}
 }
 
+static gboolean
+bus_watch_cb(GstBus *bus, GstMessage *msg, gpointer user_data)
+{
+	struct decoder *dec = (struct decoder *)user_data;
+
+	(void)bus;
+
+	switch (GST_MESSAGE_TYPE(msg)) {
+	case GST_MESSAGE_STATE_CHANGED: {
+		gchar *dotfilename;
+		GstState old_gst_state, cur_gst_state, pending_gst_state;
+
+		/* Only consider state change messages coming from
+		 * the toplevel element. */
+		if (GST_MESSAGE_SRC(msg) != GST_OBJECT(dec->pipeline))
+			break;
+
+		gst_message_parse_state_changed(msg, &old_gst_state, &cur_gst_state, &pending_gst_state);
+
+		printf(
+			"GStreamer state change:  old: %s  current: %s  pending: %s\n",
+			gst_element_state_get_name(old_gst_state),
+			gst_element_state_get_name(cur_gst_state),
+			gst_element_state_get_name(pending_gst_state)
+		);
+
+		dotfilename = g_strdup_printf(
+			"statechange__old-%s__cur-%s__pending-%s",
+			gst_element_state_get_name(old_gst_state),
+			gst_element_state_get_name(cur_gst_state),
+			gst_element_state_get_name(pending_gst_state)
+		);
+		GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(dec->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, dotfilename);
+		g_free(dotfilename);
+
+		break;
+	}
+	case GST_MESSAGE_REQUEST_STATE: {
+		GstState requested_state;
+		gst_message_parse_request_state(msg, &requested_state);
+		printf(
+			"state change to %s was requested by %s\n",
+			gst_element_state_get_name(requested_state),
+			GST_MESSAGE_SRC_NAME(msg)
+		);
+		gst_element_set_state(GST_ELEMENT(dec->pipeline), requested_state);
+		break;
+	}
+	case GST_MESSAGE_LATENCY: {
+		printf("redistributing latency\n");
+		gst_bin_recalculate_latency(GST_BIN(dec->pipeline));
+		break;
+	}
+	case GST_MESSAGE_INFO:
+	case GST_MESSAGE_WARNING:
+	case GST_MESSAGE_ERROR: {
+		GError *error = NULL;
+		gchar *debug_info = NULL;
+		gchar const *prefix;
+
+		switch (GST_MESSAGE_TYPE(msg)) {
+			case GST_MESSAGE_INFO:
+				gst_message_parse_info(msg, &error, &debug_info);
+				prefix = "INFO";
+				break;
+			case GST_MESSAGE_WARNING:
+				gst_message_parse_warning(msg, &error, &debug_info);
+				prefix = "WARNING";
+				break;
+			case GST_MESSAGE_ERROR:
+				gst_message_parse_error(msg, &error, &debug_info);
+				prefix = "ERROR";
+				break;
+			default:
+				g_assert_not_reached();
+		}
+		printf("GStreamer %s: %s; debug info: %s", prefix, error->message, debug_info);
+
+		g_clear_error(&error);
+		g_free(debug_info);
+
+		if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
+			GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(dec->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "error");
+		}
+
+		// TODO: stop mainloop in case of an error
+
+		break;
+	}
+	default:
+		break;
+	}
+
+	return TRUE;
+}
+
 struct decoder *
 video_init(const struct egl *egl, const struct gbm *gbm, const char *filename)
 {
 	struct decoder *dec;
 	GstElement *src, *decodebin;
+	GstBus *bus;
 
 	dec = calloc(1, sizeof(*dec));
 	dec->loop = g_main_loop_new(NULL, FALSE);
@@ -171,6 +268,12 @@ video_init(const struct egl *egl, const struct gbm *gbm, const char *filename)
 	decodebin = gst_bin_get_by_name(GST_BIN(dec->pipeline), "decode");
 	g_signal_connect(decodebin, "element-added", G_CALLBACK(element_added_cb), dec);
 
+	/* add bus to be able to receive error message, handle latency
+	 * requests, produce pipeline dumps, etc. */
+	bus = gst_pipeline_get_bus(GST_PIPELINE(dec->pipeline));
+	gst_bus_add_watch(bus, bus_watch_cb, dec);
+	gst_object_unref(GST_OBJECT(bus));
+
 	/* let 'er rip! */
 	gst_element_set_state(dec->pipeline, GST_STATE_PLAYING);
 
-- 
2.7.4



More information about the mesa-dev mailing list