mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-19 20:46:22 +00:00
validate-pad-monitor: concatenate issues.
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=735665 The process is to check for a similar report in intercept_report on the pads of the upstream element, set that report as the master report of the intercepted report, and return REPORTER_KEEP instead of REPORTER_REPORT.
This commit is contained in:
parent
d747e1cd05
commit
6e08079f8b
2 changed files with 262 additions and 0 deletions
|
@ -122,11 +122,124 @@ typedef struct
|
|||
} SerializedEventData;
|
||||
|
||||
|
||||
static gboolean
|
||||
_find_master_report_on_pad (GstPad * pad, GstValidateReport * report)
|
||||
{
|
||||
GstValidatePadMonitor *pad_monitor;
|
||||
GstValidateReport *prev_report;
|
||||
GstPad *tmp_pad;
|
||||
gboolean result = FALSE;
|
||||
|
||||
gst_object_ref (pad);
|
||||
|
||||
|
||||
/* We don't monitor ghost pads */
|
||||
while (GST_IS_GHOST_PAD (pad)) {
|
||||
tmp_pad = pad;
|
||||
pad = gst_ghost_pad_get_target ((GstGhostPad *) pad);
|
||||
gst_object_unref (tmp_pad);
|
||||
}
|
||||
|
||||
while (GST_IS_PROXY_PAD (pad)) {
|
||||
tmp_pad = pad;
|
||||
pad = gst_pad_get_peer (pad);
|
||||
gst_object_unref (tmp_pad);
|
||||
}
|
||||
|
||||
pad_monitor = g_object_get_data ((GObject *) pad, "validate-monitor");
|
||||
|
||||
/* For some reason this pad isn't monitored */
|
||||
if (pad_monitor == NULL)
|
||||
goto done;
|
||||
|
||||
prev_report = gst_validate_reporter_get_report ((GstValidateReporter *)
|
||||
pad_monitor, report->issue->issue_id);
|
||||
|
||||
if (prev_report) {
|
||||
if (prev_report->master_report)
|
||||
gst_validate_report_set_master_report (report,
|
||||
prev_report->master_report);
|
||||
else
|
||||
gst_validate_report_set_master_report (report, prev_report);
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
done:
|
||||
gst_object_unref (pad);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_find_master_report_for_sink_pad (GstValidatePadMonitor * pad_monitor,
|
||||
GstValidateReport * report)
|
||||
{
|
||||
GstPad *peerpad;
|
||||
gboolean result = FALSE;
|
||||
|
||||
peerpad = gst_pad_get_peer (pad_monitor->pad);
|
||||
|
||||
/* If the peer src pad already has a similar report no need to look
|
||||
* any further */
|
||||
if (peerpad && _find_master_report_on_pad (peerpad, report))
|
||||
result = TRUE;
|
||||
|
||||
if (peerpad)
|
||||
gst_object_unref (peerpad);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_find_master_report_for_src_pad (GstValidatePadMonitor * pad_monitor,
|
||||
GstValidateReport * report)
|
||||
{
|
||||
GstIterator *iter;
|
||||
gboolean done;
|
||||
GstPad *pad;
|
||||
gboolean result = FALSE;
|
||||
|
||||
iter =
|
||||
gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD
|
||||
(pad_monitor));
|
||||
done = FALSE;
|
||||
while (!done) {
|
||||
GValue value = { 0, };
|
||||
switch (gst_iterator_next (iter, &value)) {
|
||||
case GST_ITERATOR_OK:
|
||||
pad = g_value_get_object (&value);
|
||||
|
||||
if (_find_master_report_on_pad (pad, report)) {
|
||||
result = TRUE;
|
||||
done = TRUE;
|
||||
}
|
||||
|
||||
g_value_reset (&value);
|
||||
break;
|
||||
case GST_ITERATOR_RESYNC:
|
||||
gst_iterator_resync (iter);
|
||||
break;
|
||||
case GST_ITERATOR_ERROR:
|
||||
GST_WARNING_OBJECT (pad_monitor->pad,
|
||||
"Internal links pad iteration error");
|
||||
done = TRUE;
|
||||
break;
|
||||
case GST_ITERATOR_DONE:
|
||||
done = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
gst_iterator_free (iter);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GstValidateInterceptionReturn
|
||||
gst_validate_pad_monitor_intercept_report (GstValidateReporter *
|
||||
reporter, GstValidateReport * report)
|
||||
{
|
||||
GstValidateReporterInterface *iface_class, *old_iface_class;
|
||||
GstValidatePadMonitor *pad_monitor = GST_VALIDATE_PAD_MONITOR (reporter);
|
||||
|
||||
iface_class =
|
||||
G_TYPE_INSTANCE_GET_INTERFACE (reporter, GST_TYPE_VALIDATE_REPORTER,
|
||||
|
@ -134,6 +247,14 @@ gst_validate_pad_monitor_intercept_report (GstValidateReporter *
|
|||
old_iface_class = g_type_interface_peek_parent (iface_class);
|
||||
|
||||
old_iface_class->intercept_report (reporter, report);
|
||||
|
||||
if (GST_PAD_IS_SINK (pad_monitor->pad)
|
||||
&& _find_master_report_for_sink_pad (pad_monitor, report))
|
||||
return GST_VALIDATE_REPORTER_KEEP;
|
||||
else if (GST_PAD_IS_SRC (pad_monitor->pad)
|
||||
&& _find_master_report_for_src_pad (pad_monitor, report))
|
||||
return GST_VALIDATE_REPORTER_KEEP;
|
||||
|
||||
return GST_VALIDATE_REPORTER_REPORT;
|
||||
}
|
||||
|
||||
|
|
|
@ -378,6 +378,146 @@ GST_START_TEST (flow_aggregation)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
static GstPadProbeReturn
|
||||
drop_buffers (GstPad * pad, GstPadProbeInfo * info, gpointer unused)
|
||||
{
|
||||
return GST_PAD_PROBE_DROP;
|
||||
}
|
||||
|
||||
GST_START_TEST (issue_concatenation)
|
||||
{
|
||||
GstPad *srcpad1, *srcpad2, *sinkpad, *funnel_sink1, *funnel_sink2;
|
||||
GstElement *src1, *src2, *sink, *funnel;
|
||||
GstValidateRunner *runner;
|
||||
GstValidatePadMonitor *srcpad_monitor1, *srcpad_monitor2, *sinkpad_monitor;
|
||||
GstValidatePadMonitor *funnel_sink_monitor1, *funnel_sink_monitor2;
|
||||
GstSegment segment;
|
||||
GList *reports;
|
||||
gint n_reports;
|
||||
gulong probe_id1, probe_id2;
|
||||
|
||||
runner = gst_validate_runner_new ();
|
||||
|
||||
src1 = create_and_monitor_element ("fakesrc", "fakesrc1", runner);
|
||||
src2 = create_and_monitor_element ("fakesrc", "fakesrc2", runner);
|
||||
funnel = create_and_monitor_element ("funnel", "funnel", runner);
|
||||
sink = create_and_monitor_element ("fakesink", "fakesink", runner);
|
||||
|
||||
srcpad1 = gst_element_get_static_pad (src1, "src");
|
||||
srcpad_monitor1 = g_object_get_data (G_OBJECT(srcpad1), "validate-monitor");
|
||||
srcpad2 = gst_element_get_static_pad (src2, "src");
|
||||
srcpad_monitor2 = g_object_get_data (G_OBJECT(srcpad2), "validate-monitor");
|
||||
funnel_sink1 = gst_element_get_request_pad (funnel, "sink_%u");
|
||||
funnel_sink_monitor1 = g_object_get_data (G_OBJECT(funnel_sink1), "validate-monitor");
|
||||
funnel_sink2 = gst_element_get_request_pad (funnel, "sink_%u");
|
||||
funnel_sink_monitor2 = g_object_get_data (G_OBJECT(funnel_sink2), "validate-monitor");
|
||||
sinkpad = gst_element_get_static_pad (sink, "sink");
|
||||
sinkpad_monitor = g_object_get_data (G_OBJECT(sinkpad), "validate-monitor");
|
||||
|
||||
fail_unless (gst_element_link (funnel, sink));
|
||||
fail_unless (gst_pad_link (srcpad1, funnel_sink1) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_link (srcpad2, funnel_sink2) == GST_PAD_LINK_OK);
|
||||
|
||||
/* There's gonna be some clunkiness in here because of funnel*/
|
||||
probe_id1 = gst_pad_add_probe (srcpad1,
|
||||
GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST,
|
||||
(GstPadProbeCallback) drop_buffers, NULL, NULL);
|
||||
probe_id2 = gst_pad_add_probe (srcpad2,
|
||||
GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST,
|
||||
(GstPadProbeCallback) drop_buffers, NULL, NULL);
|
||||
|
||||
/* We want to handle the src behaviour ourselves */
|
||||
fail_unless (gst_pad_activate_mode (srcpad1, GST_PAD_MODE_PUSH, TRUE));
|
||||
fail_unless (gst_pad_activate_mode (srcpad2, GST_PAD_MODE_PUSH, TRUE));
|
||||
|
||||
/* Setup all needed events */
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
segment.start = 0;
|
||||
segment.stop = GST_SECOND;
|
||||
|
||||
fail_unless (gst_pad_push_event (srcpad1,
|
||||
gst_event_new_stream_start ("the-stream")));
|
||||
fail_unless (gst_pad_push_event (srcpad1, gst_event_new_segment (&segment)));
|
||||
|
||||
fail_unless (gst_pad_push_event (srcpad2,
|
||||
gst_event_new_stream_start ("the-stream")));
|
||||
fail_unless (gst_pad_push_event (srcpad2, gst_event_new_segment (&segment)));
|
||||
|
||||
fail_unless_equals_int (gst_element_set_state (funnel, GST_STATE_PLAYING),
|
||||
GST_STATE_CHANGE_SUCCESS);
|
||||
fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_PLAYING),
|
||||
GST_STATE_CHANGE_ASYNC);
|
||||
|
||||
|
||||
/* Send an unexpected flush stop */
|
||||
_gst_check_expecting_log = TRUE;
|
||||
fail_unless (gst_pad_push_event (srcpad1, gst_event_new_flush_stop (TRUE)));
|
||||
|
||||
/* The runner only sees one report */
|
||||
reports = gst_validate_runner_get_reports (runner);
|
||||
assert_equals_int (g_list_length (reports), 1);
|
||||
g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
|
||||
|
||||
/* Each pad monitor on the way actually holds a report */
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) srcpad_monitor1);
|
||||
fail_unless_equals_int (n_reports, 1);
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) sinkpad_monitor);
|
||||
fail_unless_equals_int (n_reports, 1);
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) funnel_sink_monitor1);
|
||||
fail_unless_equals_int (n_reports, 1);
|
||||
|
||||
/* But not the pad monitor of the other funnel sink */
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) funnel_sink_monitor2);
|
||||
fail_unless_equals_int (n_reports, 0);
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) srcpad_monitor2);
|
||||
fail_unless_equals_int (n_reports, 0);
|
||||
|
||||
/* Once again but on the other funnel sink */
|
||||
fail_unless (gst_pad_push_event (srcpad2, gst_event_new_flush_stop (TRUE)));
|
||||
|
||||
/* The runner now sees two reports */
|
||||
reports = gst_validate_runner_get_reports (runner);
|
||||
assert_equals_int (g_list_length (reports), 2);
|
||||
g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
|
||||
|
||||
/* These monitors already saw that issue */
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) srcpad_monitor1);
|
||||
fail_unless_equals_int (n_reports, 1);
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) sinkpad_monitor);
|
||||
fail_unless_equals_int (n_reports, 1);
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) funnel_sink_monitor1);
|
||||
fail_unless_equals_int (n_reports, 1);
|
||||
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) funnel_sink_monitor2);
|
||||
fail_unless_equals_int (n_reports, 1);
|
||||
n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *) srcpad_monitor2);
|
||||
fail_unless_equals_int (n_reports, 1);
|
||||
|
||||
/* clean up */
|
||||
fail_unless (gst_pad_activate_mode (srcpad1, GST_PAD_MODE_PUSH, FALSE));
|
||||
fail_unless (gst_pad_activate_mode (srcpad2, GST_PAD_MODE_PUSH, FALSE));
|
||||
fail_unless_equals_int (gst_element_set_state (funnel, GST_STATE_NULL),
|
||||
GST_STATE_CHANGE_SUCCESS);
|
||||
fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_NULL),
|
||||
GST_STATE_CHANGE_SUCCESS);
|
||||
|
||||
gst_pad_remove_probe (srcpad1, probe_id1);
|
||||
gst_pad_remove_probe (srcpad2, probe_id2);
|
||||
|
||||
gst_object_unref (srcpad1);
|
||||
gst_object_unref (srcpad2);
|
||||
gst_object_unref (sinkpad);
|
||||
gst_object_unref (funnel_sink1);
|
||||
gst_object_unref (funnel_sink2);
|
||||
check_destroyed (funnel, funnel_sink1, funnel_sink2, NULL);
|
||||
check_destroyed (src1, srcpad1, NULL);
|
||||
check_destroyed (src2, srcpad2, NULL);
|
||||
check_destroyed (sink, sinkpad, NULL);
|
||||
check_destroyed (runner, NULL, NULL);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
gst_validate_suite (void)
|
||||
{
|
||||
|
@ -391,6 +531,7 @@ gst_validate_suite (void)
|
|||
tcase_add_test (tc_chain, buffer_outside_segment);
|
||||
tcase_add_test (tc_chain, first_buffer_running_time);
|
||||
tcase_add_test (tc_chain, flow_aggregation);
|
||||
tcase_add_test (tc_chain, issue_concatenation);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue