From: Victor Toso <me@xxxxxxxxxxxxxx> On GST_MESSAGE_STREAM_START our stream is about to start and it seems a good moment to debug GStreamer pipeline if requested. That we can do with GST_DEBUG_BIN_TO_DOT_FILE() which iterates recursively in the whole pipeline and generates a dot file with all the information, the filename is 'spice-gtk-gst-pipeline-debug.dot'. One can generate png image out of this dot file with the command: dot -Tpng -oimage.png spice-gtk-gst-pipeline-debug.dot Not that GST_DEBUG_BIN_TO_DOT_FILE() will only work if Gstreamer was configured with --gst-enable-gst-debug and the environment variable GST_DEBUG_DUMP_DOT_DIR was properly set. Full example: 1) GST_DEBUG_DUMP_DOT_DIR=/tmp remote-viewer ... 2) dot -Tpng -oimage.png spice-gtk-gst-pipeline-debug.dot Signed-off-by: Victor Toso <victortoso@xxxxxxxxxx> --- src/channel-display-gst.c | 21 ++++++++++++++++++++- src/channel-display-priv.h | 1 + src/channel-display.c | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c index acea4a2..ef63078 100644 --- a/src/channel-display-gst.c +++ b/src/channel-display-gst.c @@ -265,7 +265,8 @@ static gboolean handle_pipeline_message(GstBus *bus, GstMessage *msg, gpointer v { SpiceGstDecoder *decoder = video_decoder; - if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) { + switch(GST_MESSAGE_TYPE(msg)) { + case GST_MESSAGE_ERROR: { GError *err = NULL; gchar *debug_info = NULL; gst_message_parse_error(msg, &err, &debug_info); @@ -279,6 +280,24 @@ static gboolean handle_pipeline_message(GstBus *bus, GstMessage *msg, gpointer v /* We won't be able to process any more frame anyway */ free_pipeline(decoder); + break; + } + case GST_MESSAGE_STREAM_START: { + gchar *filename = g_strdup_printf("spice-gtk-gst-pipeline-debug-%ld-%s", + get_stream_id_by_stream(decoder->base.stream->channel, + decoder->base.stream), + gst_opts[decoder->base.codec_type].name); + GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(decoder->pipeline), + GST_DEBUG_GRAPH_SHOW_ALL + | GST_DEBUG_GRAPH_SHOW_FULL_PARAMS + | GST_DEBUG_GRAPH_SHOW_STATES, + filename); + g_free(filename); + break; + } + default: + /* not being handled */ + break; } return TRUE; } diff --git a/src/channel-display-priv.h b/src/channel-display-priv.h index 00f71f8..407145f 100644 --- a/src/channel-display-priv.h +++ b/src/channel-display-priv.h @@ -196,6 +196,7 @@ G_STATIC_ASSERT(G_N_ELEMENTS(gst_opts) <= SPICE_VIDEO_CODEC_TYPE_ENUM_END); guint32 stream_get_time(display_stream *st); void stream_dropped_frame_on_playback(display_stream *st); void stream_display_frame(display_stream *st, SpiceFrame *frame, uint32_t width, uint32_t height, uint8_t* data); +gint64 get_stream_id_by_stream(SpiceChannel *channel, display_stream *st); G_END_DECLS diff --git a/src/channel-display.c b/src/channel-display.c index e51064a..f226988 100644 --- a/src/channel-display.c +++ b/src/channel-display.c @@ -1164,6 +1164,23 @@ static display_stream *get_stream_by_id(SpiceChannel *channel, uint32_t id) return NULL; } +G_GNUC_INTERNAL +gint64 get_stream_id_by_stream(SpiceChannel *channel, display_stream *st) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + guint i; + + g_return_val_if_fail(c->streams != NULL, -1); + g_return_val_if_fail(c->nstreams != 0, -1); + + for (i = 0; i < c->nstreams; i++) { + if (c->streams[i] == st) + return i; + } + + return -1; +} + /* coroutine context */ static display_stream *display_stream_create(SpiceChannel *channel, uint32_t surface_id, uint32_t flags, uint32_t codec_type, -- 2.13.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel