3 * Copyright (C) 2014 Thibault Saunier <tsaunier@gnome.org>
5 * gst-validate-pipeline-monitor.c - Validate PipelineMonitor class
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
27 #include "gst-validate-internal.h"
28 #include "gst-validate-pipeline-monitor.h"
29 #include "gst-validate-pad-monitor.h"
30 #include "gst-validate-monitor-factory.h"
31 #include "gst-validate-report.h"
32 #include "gst-validate-utils.h"
35 #define PRINT_POSITION_TIMEOUT 250
48 * SECTION:gst-validate-pipeline-monitor
49 * @title: GstValidatePipelineMonitor
50 * @short_description: Class that wraps a #GstPipeline for Validate checks
58 gint filter_caps_struct_num;
62 } StructureIncompatibleFieldsInfo;
69 #define gst_validate_pipeline_monitor_parent_class parent_class
70 G_DEFINE_TYPE (GstValidatePipelineMonitor, gst_validate_pipeline_monitor,
71 GST_TYPE_VALIDATE_BIN_MONITOR);
74 gst_validate_pipeline_monitor_dispose (GObject * object)
76 GstValidatePipelineMonitor *self = (GstValidatePipelineMonitor *) object;
78 g_clear_object (&self->stream_collection);
79 if (self->streams_selected) {
80 g_list_free_full (self->streams_selected, gst_object_unref);
81 self->streams_selected = NULL;
84 G_OBJECT_CLASS (gst_validate_pipeline_monitor_parent_class)->dispose (object);
88 gst_validate_pipeline_monitor_set_property (GObject * object, guint prop_id,
89 const GValue * value, GParamSpec * pspec)
91 GstElement *pipeline = NULL;
92 GstValidateMonitor *monitor = GST_VALIDATE_MONITOR_CAST (object);
93 GstValidatePipelineMonitor *self = GST_VALIDATE_PIPELINE_MONITOR (object);
97 pipeline = GST_ELEMENT (gst_validate_monitor_get_pipeline (monitor));
98 monitor->verbosity = g_value_get_flags (value);
99 if (monitor->verbosity & GST_VALIDATE_VERBOSITY_PROPS_CHANGES) {
100 if (pipeline && !self->deep_notify_id) {
101 self->deep_notify_id =
102 gst_element_add_property_deep_notify_watch (pipeline, NULL, TRUE);
104 } else if (pipeline && self->deep_notify_id) {
105 gst_element_remove_property_notify_watch (pipeline,
106 self->deep_notify_id);
107 self->deep_notify_id = 0;
111 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
115 gst_clear_object (&pipeline);
119 gst_validate_pipeline_monitor_get_property (GObject * object, guint prop_id,
120 GValue * value, GParamSpec * pspec)
122 GstValidateMonitor *monitor = GST_VALIDATE_MONITOR_CAST (object);
126 g_value_set_flags (value, monitor->verbosity);
129 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
136 gst_validate_pipeline_monitor_class_init (GstValidatePipelineMonitorClass *
139 GObjectClass *object_class = G_OBJECT_CLASS (klass);
141 object_class->dispose = gst_validate_pipeline_monitor_dispose;
142 object_class->set_property = gst_validate_pipeline_monitor_set_property;
143 object_class->get_property = gst_validate_pipeline_monitor_get_property;
145 g_object_class_override_property (object_class, PROP_VERBOSITY, "verbosity");
149 gst_validate_pipeline_monitor_init (GstValidatePipelineMonitor *
155 print_position (GstValidateMonitor * monitor)
158 gint64 position, duration;
159 GstElement *pipeline =
160 GST_ELEMENT (gst_validate_monitor_get_pipeline (monitor));
163 GstFormat format = GST_FORMAT_TIME;
165 if (!(GST_VALIDATE_MONITOR_CAST (monitor)->verbosity &
166 GST_VALIDATE_VERBOSITY_POSITION))
169 if (!gst_element_query_position (pipeline, format, &position)) {
170 GST_DEBUG_OBJECT (monitor, "Could not query position");
175 format = GST_FORMAT_TIME;
176 if (!gst_element_query_duration (pipeline, format, &duration)) {
177 GST_DEBUG_OBJECT (monitor, "Could not query duration");
182 if (GST_CLOCK_TIME_IS_VALID (duration) && GST_CLOCK_TIME_IS_VALID (position)
183 && position > duration) {
184 GST_VALIDATE_REPORT (monitor, QUERY_POSITION_SUPERIOR_DURATION,
185 "Reported position %" GST_TIME_FORMAT " > reported duration %"
186 GST_TIME_FORMAT, GST_TIME_ARGS (position), GST_TIME_ARGS (duration));
189 query = gst_query_new_segment (GST_FORMAT_DEFAULT);
190 if (gst_element_query (pipeline, query))
191 gst_query_parse_segment (query, &rate, NULL, NULL, NULL);
192 gst_query_unref (query);
194 gst_validate_print_position (position, duration, rate, NULL);
197 gst_object_unref (pipeline);
203 _check_pad_query_failures (GstPad * pad, GString * str,
204 GstValidatePadMonitor ** last_query_caps_fail_monitor,
205 GstValidatePadMonitor ** last_refused_caps_monitor)
207 GstValidatePadMonitor *monitor;
209 monitor = g_object_get_data (G_OBJECT (pad), "validate-monitor");
212 GST_DEBUG_OBJECT (pad, "Has no monitor");
216 if (monitor->last_query_res && gst_caps_is_empty (monitor->last_query_res)) {
217 gst_object_replace ((GstObject **) last_query_caps_fail_monitor,
218 (GstObject *) monitor);
221 if (monitor->last_refused_caps)
222 gst_object_replace ((GstObject **) last_refused_caps_monitor,
223 (GstObject *) monitor);
227 _get_peer_pad (GstPad * pad)
229 GstPad *peer = gst_pad_get_peer (pad);
234 while (GST_IS_PROXY_PAD (peer)) {
237 if (GST_PAD_IS_SINK (peer)) {
238 if (GST_IS_GHOST_PAD (peer))
239 next_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (peer));
241 next_pad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (peer)));
243 next_pad = gst_pad_get_peer (peer);
246 gst_object_unref (peer);
257 _gather_pad_negotiation_details (GstPad * pad, GString * str,
258 GstValidatePadMonitor ** last_query_caps_fail_monitor,
259 GstValidatePadMonitor ** last_refused_caps_monitor)
263 GstPad *peer = _get_peer_pad (pad);
265 _check_pad_query_failures (pad, str, last_query_caps_fail_monitor,
266 last_refused_caps_monitor);
271 _check_pad_query_failures (peer, str, last_query_caps_fail_monitor,
272 last_refused_caps_monitor);
274 next = GST_ELEMENT (gst_pad_get_parent (peer));
275 GST_OBJECT_LOCK (next);
276 for (tmp = next->srcpads; tmp; tmp = tmp->next) {
277 GstPad *to_check = (GstPad *) tmp->data;
278 _gather_pad_negotiation_details (to_check, str,
279 last_query_caps_fail_monitor, last_refused_caps_monitor);
281 GST_OBJECT_UNLOCK (next);
283 gst_object_unref (peer);
284 gst_object_unref (next);
288 _incompatible_fields_info_set_found (StructureIncompatibleFieldsInfo * info)
290 if (info->found == FALSE) {
291 g_string_append_printf (info->str, " for the following possible reasons:");
297 _find_structure_incompatible_fields (GQuark field_id, const GValue * value,
298 StructureIncompatibleFieldsInfo * info)
300 gchar *value_str, *filter_str;
301 const GValue *filter_value = gst_structure_id_get_value (info->filter,
307 value_str = gst_value_serialize (value);
308 filter_str = gst_value_serialize (filter_value);
310 if (!gst_value_can_intersect (value, filter_value)) {
311 _incompatible_fields_info_set_found (info);
312 g_string_append_printf (info->str,
313 "\n -> Field '%s' downstream value from structure %d '(%s)%s' can't intersect with"
314 " filter value from structure number %d '(%s)%s' because of their types.",
315 g_quark_to_string (field_id), info->caps_struct_num,
316 G_VALUE_TYPE_NAME (value), value_str, info->filter_caps_struct_num,
317 G_VALUE_TYPE_NAME (filter_value), filter_str);
322 if (gst_value_intersect (NULL, value, filter_value)) {
329 _incompatible_fields_info_set_found (info);
330 g_string_append_printf (info->str,
331 "\n -> Field '%s' downstream value from structure %d '(%s)%s' can't intersect with"
332 " filter value from structure number %d '(%s)%s'",
333 g_quark_to_string (field_id), info->caps_struct_num,
334 G_VALUE_TYPE_NAME (value), value_str, info->filter_caps_struct_num,
335 G_VALUE_TYPE_NAME (filter_value), filter_str);
344 _append_query_caps_failure_details (GstValidatePadMonitor * monitor,
348 gboolean found = FALSE, empty_filter;
349 GstCaps *filter = gst_caps_copy (monitor->last_query_filter);
350 const gchar *filter_name, *possible_name;
351 GstStructure *filter_struct, *possible_struct;
353 GST_PAD (gst_validate_monitor_get_target (GST_VALIDATE_MONITOR
355 GstCaps *possible_caps = gst_pad_query_caps (pad, NULL);
357 g_string_append_printf (str,
358 "\n Caps negotiation failed starting from pad '%s'"
359 " as the QUERY_CAPS returned EMPTY caps",
360 gst_validate_reporter_get_name (GST_VALIDATE_REPORTER (monitor)));
362 empty_filter = gst_caps_is_empty (filter);
364 GstPad *peer = _get_peer_pad (pad);
365 gchar *prev_path = NULL;
368 GstObject *prev = gst_pad_get_parent (peer);
370 prev_path = gst_object_get_path_string (prev);
371 gst_object_unref (prev);
375 g_string_append_printf (str,
376 "\n - The QUERY filter caps is EMPTY, this is invalid and is a bug in "
377 "a previous element (probably in: '%s')\n",
378 prev_path ? prev_path : "no suspect");
382 for (i = 0; i < gst_caps_get_size (possible_caps); i++) {
383 possible_struct = gst_caps_get_structure (possible_caps, i);
384 possible_name = gst_structure_get_name (possible_struct);
386 for (j = 0; j < gst_caps_get_size (filter); j++) {
387 StructureIncompatibleFieldsInfo info = {
388 .caps_struct_num = i,
389 .filter_caps_struct_num = j,
394 info.filter = filter_struct = gst_caps_get_structure (filter, j);
395 filter_name = gst_structure_get_name (filter_struct);
397 if (g_strcmp0 (possible_name, filter_name)) {
398 _incompatible_fields_info_set_found (&info);
399 g_string_append_printf (str,
400 "\n -> Downstream caps struct %d name '%s' differs from "
401 "filter caps struct %d name '%s'",
402 i, possible_name, j, filter_name);
407 gst_structure_foreach (possible_struct,
408 (GstStructureForeachFunc) _find_structure_incompatible_fields, &info);
415 if (!found && !empty_filter) {
416 gchar *filter_caps_str = gst_caps_to_string (filter);
417 gchar *possible_caps_str = gst_caps_to_string (possible_caps);
419 g_string_append_printf (str,
420 ". The exact reason could not be determined but"
421 " here is the gathered information:\n"
422 " - %s last query caps filter: %s\n"
423 " - %s possible caps (as returned by a query on it without filter): %s\n",
424 gst_validate_reporter_get_name (GST_VALIDATE_REPORTER (monitor)),
426 gst_validate_reporter_get_name (GST_VALIDATE_REPORTER (monitor)),
430 gst_caps_unref (possible_caps);
431 gst_caps_unref (filter);
432 gst_object_unref (pad);
437 _append_accept_caps_failure_details (GstValidatePadMonitor * monitor,
441 GstCaps *refused_caps = gst_caps_copy (monitor->last_refused_caps);
443 GST_PAD (gst_validate_monitor_get_target (GST_VALIDATE_MONITOR
445 GstCaps *possible_caps = gst_pad_query_caps (pad, NULL);
446 gchar *caps_str = gst_caps_to_string (monitor->last_refused_caps);
447 StructureIncompatibleFieldsInfo info = {
452 g_string_append_printf (str,
453 "\n Caps negotiation failed at pad '%s' as it refused caps: %s",
454 gst_validate_reporter_get_name (GST_VALIDATE_REPORTER (monitor)),
458 for (i = 0; i < gst_caps_get_size (refused_caps); i++) {
459 GstStructure *refused_struct = gst_caps_get_structure (refused_caps, i);
460 const gchar *filter_name;
461 const gchar *refused_name = gst_structure_get_name (refused_struct);
463 for (j = 0; j < gst_caps_get_size (possible_caps); j++) {
464 info.caps_struct_num = i,
465 info.filter_caps_struct_num = j,
466 info.filter = gst_caps_get_structure (possible_caps, j);
468 filter_name = gst_structure_get_name (info.filter);
469 if (g_strcmp0 (refused_name, filter_name)) {
470 g_string_append_printf (str,
471 "\n -> Downstream caps struct %d name '%s' differs from "
472 "filter caps struct %d name '%s'", i, refused_name, j, filter_name);
477 gst_structure_foreach (refused_struct,
478 (GstStructureForeachFunc) _find_structure_incompatible_fields, &info);
482 gst_caps_unref (possible_caps);
483 gst_object_unref (pad);
489 _generate_not_negotiated_error_report (GstMessage * msg)
493 GstElement *element = GST_ELEMENT (GST_MESSAGE_SRC (msg));
494 GstValidatePadMonitor *last_query_caps_fail_monitor = NULL,
495 *last_refused_caps_monitor = NULL;
497 str = g_string_new (NULL);
498 g_string_append_printf (str, "Error message posted by: %s",
499 GST_OBJECT_NAME (element));
501 GST_OBJECT_LOCK (element);
502 for (tmp = element->srcpads; tmp; tmp = tmp->next) {
503 GstPad *to_check = (GstPad *) tmp->data;
504 _gather_pad_negotiation_details (to_check, str,
505 &last_query_caps_fail_monitor, &last_refused_caps_monitor);
507 GST_OBJECT_UNLOCK (element);
509 if (last_query_caps_fail_monitor)
510 _append_query_caps_failure_details (last_query_caps_fail_monitor, str);
511 else if (last_refused_caps_monitor)
512 _append_accept_caps_failure_details (last_refused_caps_monitor, str);
514 GST_ERROR ("We should always be able to generate a detailed report"
515 " about why negotiation failed. Please report a bug against"
516 " gst-devtools:validate with this message and a way to reproduce.");
519 gst_object_replace ((GstObject **) & last_query_caps_fail_monitor, NULL);
520 gst_object_replace ((GstObject **) & last_refused_caps_monitor, NULL);
522 return g_string_free (str, FALSE);
526 _bus_handler (GstBus * bus, GstMessage * message,
527 GstValidatePipelineMonitor * monitor)
531 const GstStructure *details = NULL;
532 gint error_flow = GST_FLOW_OK;
534 if (GST_VALIDATE_MONITOR_CAST (monitor)->verbosity &
535 GST_VALIDATE_VERBOSITY_MESSAGES
536 && GST_MESSAGE_TYPE (message) != GST_MESSAGE_PROPERTY_NOTIFY) {
538 const GstStructure *s;
540 GString *str = g_string_new (NULL);
542 seqnum = gst_message_get_seqnum (message);
543 s = gst_message_get_structure (message);
544 src_obj = GST_MESSAGE_SRC (message);
546 if (GST_IS_ELEMENT (src_obj)) {
547 g_string_append_printf (str, "Got message #%u from element \"%s\" (%s): ",
548 (guint) seqnum, GST_ELEMENT_NAME (src_obj),
549 GST_MESSAGE_TYPE_NAME (message));
550 } else if (GST_IS_PAD (src_obj)) {
551 g_string_append_printf (str, "Got message #%u from pad \"%s:%s\" (%s): ",
552 (guint) seqnum, GST_DEBUG_PAD_NAME (src_obj),
553 GST_MESSAGE_TYPE_NAME (message));
554 } else if (GST_IS_OBJECT (src_obj)) {
555 g_string_append_printf (str, "Got message #%u from object \"%s\" (%s): ",
556 (guint) seqnum, GST_OBJECT_NAME (src_obj),
557 GST_MESSAGE_TYPE_NAME (message));
559 g_string_append_printf (str, "Got message #%u (%s): ", (guint) seqnum,
560 GST_MESSAGE_TYPE_NAME (message));
565 sstr = gst_structure_to_string (s);
566 g_string_append_printf (str, "%s\n", sstr);
569 g_string_append (str, "no message details\n");
571 gst_validate_printf (NULL, "%s", str->str);
572 g_string_free (str, TRUE);
574 switch (GST_MESSAGE_TYPE (message)) {
575 case GST_MESSAGE_EOS:
576 print_position (GST_VALIDATE_MONITOR (monitor));
578 case GST_MESSAGE_ERROR:
579 gst_message_parse_error (message, &err, &debug);
580 gst_message_parse_error_details (message, &details);
582 if (g_error_matches (err, GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN)) {
583 if (!gst_validate_fail_on_missing_plugin ()) {
584 gst_validate_skip_test ("missing plugin: %s -- Debug message: %s\n",
585 err->message, debug);
587 GST_VALIDATE_REPORT (monitor, MISSING_PLUGIN,
588 "Error: %s -- Debug message: %s", err->message, debug);
590 } else if ((g_error_matches (err, GST_STREAM_ERROR,
591 GST_STREAM_ERROR_FAILED) && details
592 && gst_structure_get_int (details, "flow-return", &error_flow)
593 && error_flow == GST_FLOW_NOT_NEGOTIATED)
594 || g_error_matches (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FORMAT)) {
595 gchar *report = _generate_not_negotiated_error_report (message);
597 GST_VALIDATE_REPORT (monitor, NOT_NEGOTIATED, "%s", report);
600 GST_VALIDATE_REPORT (monitor, ERROR_ON_BUS,
601 "Got error: %s -- Debug message: %s (%" GST_PTR_FORMAT ")",
602 err->message, debug, details);
605 GST_VALIDATE_MONITOR_LOCK (monitor);
606 monitor->got_error = TRUE;
607 GST_VALIDATE_MONITOR_UNLOCK (monitor);
611 case GST_MESSAGE_WARNING:
612 gst_message_parse_warning (message, &err, &debug);
613 GST_VALIDATE_REPORT (monitor, WARNING_ON_BUS,
614 "Got warning: %s -- Debug message: %s", err->message, debug);
618 case GST_MESSAGE_STATE_CHANGED:
621 gst_validate_monitor_get_target (GST_VALIDATE_MONITOR (monitor));
622 if (GST_MESSAGE_SRC (message) == target) {
623 GstState oldstate, newstate, pending;
625 gst_message_parse_state_changed (message, &oldstate, &newstate,
628 if (oldstate == GST_STATE_READY && newstate == GST_STATE_PAUSED) {
629 monitor->print_pos_srcid =
630 g_timeout_add (PRINT_POSITION_TIMEOUT,
631 (GSourceFunc) print_position, monitor);
632 } else if (oldstate >= GST_STATE_PAUSED && newstate <= GST_STATE_READY) {
633 if (monitor->print_pos_srcid
634 && g_source_remove (monitor->print_pos_srcid))
635 monitor->print_pos_srcid = 0;
636 monitor->got_error = FALSE;
641 gst_object_unref (target);
645 case GST_MESSAGE_BUFFERING:
647 JsonBuilder *jbuilder = json_builder_new ();
648 GstBufferingMode mode;
651 gst_message_parse_buffering (message, &percent);
652 gst_message_parse_buffering_stats (message, &mode, NULL, NULL, NULL);
654 json_builder_begin_object (jbuilder);
655 json_builder_set_member_name (jbuilder, "type");
656 json_builder_add_string_value (jbuilder, "buffering");
657 json_builder_set_member_name (jbuilder, "state");
658 if (percent == 100) {
659 /* a 100% message means buffering is done */
660 gst_validate_printf (NULL, "\nDone buffering\n");
661 json_builder_add_string_value (jbuilder, "done");
662 if (monitor->buffering) {
663 monitor->print_pos_srcid =
664 g_timeout_add (PRINT_POSITION_TIMEOUT,
665 (GSourceFunc) print_position, monitor);
666 monitor->buffering = FALSE;
670 if (!monitor->buffering) {
671 monitor->buffering = TRUE;
672 gst_validate_printf (NULL, "\nStart buffering\n");
673 json_builder_add_string_value (jbuilder, "started");
674 if (monitor->print_pos_srcid
675 && g_source_remove (monitor->print_pos_srcid)) {
676 monitor->print_pos_srcid = 0;
679 json_builder_add_string_value (jbuilder, "progress");
682 gst_validate_printf (NULL, "%s %d%% \r", "Buffering...", percent);
684 json_builder_set_member_name (jbuilder, "position");
685 json_builder_add_int_value (jbuilder, percent);
686 json_builder_end_object (jbuilder);
688 gst_validate_send (json_builder_get_root (jbuilder));
689 g_object_unref (jbuilder);
692 case GST_MESSAGE_STREAM_COLLECTION:
694 GstStreamCollection *collection = NULL;
695 gst_message_parse_stream_collection (message, &collection);
696 gst_object_replace ((GstObject **) & monitor->stream_collection,
697 (GstObject *) collection);
698 gst_object_unref (collection);
701 case GST_MESSAGE_STREAMS_SELECTED:
705 if (monitor->streams_selected) {
706 g_list_free_full (monitor->streams_selected, gst_object_unref);
707 monitor->streams_selected = NULL;
710 for (i = 0; i < gst_message_streams_selected_get_size (message); i++) {
712 gst_message_streams_selected_get_stream (message, i);
714 monitor->streams_selected =
715 g_list_append (monitor->streams_selected, stream);
719 case GST_MESSAGE_PROPERTY_NOTIFY:
724 gchar *val_str = NULL;
727 if (!(GST_VALIDATE_MONITOR_CAST (monitor)->verbosity &
728 GST_VALIDATE_VERBOSITY_PROPS_CHANGES))
731 gst_message_parse_property_notify (message, &obj, &name, &val);
733 obj_name = gst_object_get_path_string (GST_OBJECT (obj));
735 if (G_VALUE_HOLDS_STRING (val))
736 val_str = g_value_dup_string (val);
737 else if (G_VALUE_TYPE (val) == GST_TYPE_CAPS)
738 val_str = gst_caps_to_string (g_value_get_boxed (val));
739 else if (G_VALUE_TYPE (val) == GST_TYPE_TAG_LIST)
740 val_str = gst_tag_list_to_string (g_value_get_boxed (val));
741 else if (G_VALUE_TYPE (val) == GST_TYPE_STRUCTURE)
742 val_str = gst_structure_to_string (g_value_get_boxed (val));
744 val_str = gst_value_serialize (val);
746 val_str = g_strdup ("(no value)");
749 gst_validate_printf (NULL, "%s: %s = %s\n", obj_name, name, val_str);
762 gst_validate_pipeline_monitor_create_scenarios (GstValidateBinMonitor * monitor)
764 /* scenarios currently only make sense for pipelines */
765 const gchar *scenarios_names, *scenario_name = NULL;
766 gchar **scenarios = NULL, *testfile = NULL;
768 gst_validate_monitor_get_target (GST_VALIDATE_MONITOR (monitor));
769 GstValidateRunner *runner =
770 gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (monitor));
771 GList *scenario_structs = NULL;
773 if (gst_validate_get_test_file_scenario (&scenario_structs, &scenario_name,
777 gst_validate_scenario_factory_create (runner,
778 GST_ELEMENT_CAST (target), scenario_name);
783 gst_validate_scenario_from_structs (runner,
784 GST_ELEMENT_CAST (target), scenario_structs, testfile);
789 if ((scenarios_names = g_getenv ("GST_VALIDATE_SCENARIO"))) {
792 scenarios = g_strsplit (scenarios_names, G_SEARCHPATH_SEPARATOR_S, 0);
793 for (i = 0; scenarios[i]; i++) {
794 gchar **scenario_v = g_strsplit (scenarios[i], "->", 2);
796 if (scenario_v[1] && target) {
797 if (!g_pattern_match_simple (scenario_v[1], GST_OBJECT_NAME (target))) {
798 GST_INFO_OBJECT (monitor, "Not attaching to pipeline %" GST_PTR_FORMAT
799 " as not matching pattern %s", target, scenario_v[1]);
801 g_strfreev (scenario_v);
807 gst_validate_scenario_factory_create (runner,
808 GST_ELEMENT_CAST (target), scenario_v[0]);
810 GST_INFO_OBJECT (monitor, "Not creating scenario as monitor"
811 " already does not have a target.");
812 g_strfreev (scenario_v);
816 g_strfreev (scenarios);
818 gst_object_unref (target);
820 gst_object_unref (runner);
824 * gst_validate_pipeline_monitor_new:
825 * @pipeline: (transfer none): a #GstPipeline to run Validate on
826 * @runner: (transfer none): a #GstValidateRunner
827 * @parent: (nullable): The parent of the new monitor
829 * Returns: (transfer full): A #GstValidatePipelineMonitor or NULL
831 GstValidatePipelineMonitor *
832 gst_validate_pipeline_monitor_new (GstPipeline * pipeline,
833 GstValidateRunner * runner, GstValidateMonitor * parent)
836 GstValidatePipelineMonitor *monitor =
837 g_object_new (GST_TYPE_VALIDATE_PIPELINE_MONITOR, "object",
838 pipeline, "validate-runner", runner, "validate-parent", parent,
839 "pipeline", pipeline, NULL);
841 gst_validate_monitor_get_target (GST_VALIDATE_MONITOR (monitor));
843 if (target == NULL) {
844 g_object_unref (monitor);
848 gst_validate_pipeline_monitor_create_scenarios (GST_VALIDATE_BIN_MONITOR
851 bus = gst_element_get_bus (GST_ELEMENT (pipeline));
852 gst_bus_enable_sync_message_emission (bus);
853 g_signal_connect (bus, "sync-message", (GCallback) _bus_handler, monitor);
855 if (GST_VALIDATE_MONITOR_CAST (monitor)->verbosity &
856 GST_VALIDATE_VERBOSITY_PROPS_CHANGES) {
857 monitor->deep_notify_id =
858 gst_element_add_property_deep_notify_watch ((GstElement *) pipeline,
862 gst_object_unref (bus);
864 if (g_strcmp0 (G_OBJECT_TYPE_NAME (pipeline), "GstPlayBin") == 0)
865 monitor->is_playbin = TRUE;
866 else if (g_strcmp0 (G_OBJECT_TYPE_NAME (pipeline), "GstPlayBin3") == 0)
867 monitor->is_playbin3 = TRUE;
868 gst_object_unref (target);