2 * Copyright (C) 2014 Thibault Saunier <thibault.saunier@collabora.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #include <gst/validate/validate.h>
22 #include <gst/validate/gst-validate-pad-monitor.h>
23 #include <gst/validate/media-descriptor-parser.h>
24 #include <gst/check/gstcheck.h>
25 #include "test-utils.h"
27 static GstValidateRunner *
28 _start_monitoring_bin (GstBin * bin)
30 GstValidateRunner *runner;
31 GstValidateMonitor *monitor;
33 runner = gst_validate_runner_new ();
35 gst_validate_monitor_factory_create (GST_OBJECT (bin), runner, NULL);
37 gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor));
42 _stop_monitoring_bin (GstBin * bin, GstValidateRunner * runner)
44 GstValidateMonitor *monitor;
47 (GstValidateMonitor *) g_object_get_data (G_OBJECT (bin),
49 gst_object_unref (bin);
50 ASSERT_OBJECT_REFCOUNT (monitor, "monitor", 1);
51 gst_object_unref (monitor);
52 ASSERT_OBJECT_REFCOUNT (runner, "runner", 2);
53 gst_object_unref (runner);
56 static GstValidateMonitor *
57 _start_monitoring_element (GstElement * element, GstValidateRunner * runner)
59 GstValidateMonitor *monitor;
61 monitor = gst_validate_monitor_factory_create (GST_OBJECT (element),
68 _check_reports_refcount (GstPad * pad, gint refcount)
71 GstValidateReporter *reporter =
72 (GstValidateReporter *) g_object_get_data (G_OBJECT (pad),
75 reports = gst_validate_reporter_get_reports (reporter);
76 /* We take a ref here */
79 for (tmp = reports; tmp; tmp = tmp->next)
80 fail_unless_equals_int (((GstMiniObject *) tmp->data)->refcount, refcount);
82 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
86 gst_discont_buffer_new (void)
88 GstBuffer *buffer = gst_buffer_new ();
90 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
95 GST_START_TEST (buffer_before_segment)
97 GstPad *srcpad, *sinkpad;
99 GstValidateRunner *runner;
100 GstValidateReport *report;
101 GstValidateMonitor *monitor;
104 /* getting an existing element class is cheating, but easier */
105 sink = gst_element_factory_make ("fakesink", "fakesink");
107 srcpad = gst_pad_new ("src", GST_PAD_SRC);
108 sinkpad = gst_element_get_static_pad (sink, "sink");
109 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
110 gst_clear_object (&sinkpad);
112 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE));
113 runner = gst_validate_runner_new ();
115 gst_validate_monitor_factory_create (GST_OBJECT (srcpad), runner, NULL);
116 fail_unless (GST_IS_VALIDATE_PAD_MONITOR (monitor));
119 /* We want to handle the src behaviour ourself */
120 fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
121 fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_PLAYING),
122 GST_STATE_CHANGE_ASYNC);
124 /* Send a buffer before pushing any segment (FAILS) */
126 _gst_check_expecting_log = TRUE;
127 fail_unless_equals_int (gst_pad_push (srcpad,
128 gst_discont_buffer_new ()), GST_FLOW_OK);
130 reports = gst_validate_runner_get_reports (runner);
131 assert_equals_int (g_list_length (reports), 1);
132 report = reports->data;
133 fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_WARNING);
134 fail_unless_equals_int (report->issue->issue_id, BUFFER_BEFORE_SEGMENT);
135 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
138 /* Setup all needed event and push a new buffer (WORKS) */
140 _gst_check_expecting_log = FALSE;
141 gst_check_setup_events (srcpad, sink, NULL, GST_FORMAT_TIME);
142 fail_unless_equals_int (gst_pad_push (srcpad, gst_discont_buffer_new ()),
144 reports = gst_validate_runner_get_reports (runner);
145 assert_equals_int (g_list_length (reports), 1);
146 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
150 fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, FALSE));
151 fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_NULL),
152 GST_STATE_CHANGE_SUCCESS);
154 _check_reports_refcount (srcpad, 2);
155 gst_object_unref (srcpad);
156 gst_check_object_destroyed_on_unref (sink);
157 ASSERT_OBJECT_REFCOUNT (runner, "runner", 2);
158 gst_object_unref (runner);
163 GST_START_TEST (buffer_outside_segment)
165 GstPad *srcpad, *pad;
168 GstElement *sink, *identity;
169 gchar *identity_klass;
170 GstValidateReport *report;
171 GstValidateRunner *runner;
172 GstValidateMonitor *monitor;
175 srcpad = gst_pad_new ("src", GST_PAD_SRC);
176 identity = gst_element_factory_make ("identity", NULL);
177 sink = gst_element_factory_make ("fakesink", "fakesink");
180 g_strdup (gst_element_class_get_metadata (GST_ELEMENT_GET_CLASS
181 (identity), "klass"));
183 /* Testing if a buffer is outside a segment is only done for buffer outputed
184 * from decoders for the moment, fake a Decoder so that the test is properly
186 gst_element_class_add_metadata (GST_ELEMENT_GET_CLASS (identity), "klass",
189 pad = gst_element_get_static_pad (identity, "sink");
190 fail_unless (gst_pad_link (srcpad, pad) == GST_PAD_LINK_OK);
191 gst_clear_object (&pad);
193 fail_unless (gst_element_link (identity, sink));
195 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE));
196 runner = gst_validate_runner_new ();
198 gst_validate_monitor_factory_create (GST_OBJECT (identity), runner, NULL);
199 gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor));
201 pad = gst_element_get_static_pad (identity, "src");
202 fail_unless (GST_IS_VALIDATE_PAD_MONITOR (g_object_get_data ((GObject *)
203 pad, "validate-monitor")));
204 gst_clear_object (&pad);
206 fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
207 fail_unless_equals_int (gst_element_set_state (identity, GST_STATE_PLAYING),
208 GST_STATE_CHANGE_SUCCESS);
209 fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_PLAYING),
210 GST_STATE_CHANGE_ASYNC);
212 gst_segment_init (&segment, GST_FORMAT_TIME);
214 segment.stop = GST_SECOND;
215 fail_unless (gst_pad_push_event (srcpad,
216 gst_event_new_stream_start ("the-stream")));
217 fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&segment)));
219 /* Pushing a buffer that is outside the segment */
221 buffer = gst_discont_buffer_new ();
222 GST_BUFFER_PTS (buffer) = 10 * GST_SECOND;
223 GST_BUFFER_DURATION (buffer) = GST_SECOND;
224 fail_if (GST_PAD_IS_FLUSHING (gst_element_get_static_pad (identity,
226 fail_if (GST_PAD_IS_FLUSHING (gst_element_get_static_pad (identity,
228 fail_if (GST_PAD_IS_FLUSHING (gst_element_get_static_pad (sink, "sink")));
229 fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK);
231 reports = gst_validate_runner_get_reports (runner);
232 assert_equals_int (g_list_length (reports), 1);
233 report = reports->data;
234 fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_ISSUE);
235 fail_unless_equals_int (report->issue->issue_id, BUFFER_IS_OUT_OF_SEGMENT);
236 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
239 /* Pushing a buffer inside the segment */
241 fail_unless_equals_int (gst_pad_push (srcpad, gst_discont_buffer_new ()),
243 reports = gst_validate_runner_get_reports (runner);
244 assert_equals_int (g_list_length (reports), 1);
245 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
250 fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, FALSE));
251 gst_object_unref (srcpad);
253 gst_element_class_add_metadata (GST_ELEMENT_GET_CLASS (identity), "klass",
255 g_free (identity_klass);
256 gst_object_unref (runner);
258 fail_unless_equals_int (gst_element_set_state (identity, GST_STATE_NULL),
259 GST_STATE_CHANGE_SUCCESS);
260 gst_element_unlink (identity, sink);
261 fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_NULL),
262 GST_STATE_CHANGE_SUCCESS);
263 gst_object_unref (identity);
264 gst_object_unref (sink);
265 gst_object_unref (monitor);
271 fake_demuxer_prepare_pads (GstBin * pipeline, GstElement * demux,
272 GstValidateRunner * runner)
277 fail_unless (g_list_length (demux->srcpads), 3);
279 for (tmp = demux->srcpads; tmp; tmp = tmp->next) {
281 gchar *name = g_strdup_printf ("sink-%d", i++);
282 GstElement *sink = gst_element_factory_make ("fakesink", name);
284 gst_bin_add (pipeline, sink);
286 new_peer = sink->sinkpads->data;
287 gst_pad_link (tmp->data, new_peer);
288 gst_element_set_state (sink, GST_STATE_PLAYING);
289 gst_pad_activate_mode (tmp->data, GST_PAD_MODE_PUSH, TRUE);
294 fail_unless (gst_pad_activate_mode (demux->sinkpads->data, GST_PAD_MODE_PUSH,
298 static GstValidatePadMonitor *
299 _get_pad_monitor (GstPad * pad)
301 GstValidatePadMonitor *m = get_pad_monitor (pad);
303 gst_object_unref (pad);
309 _test_flow_aggregation (GstFlowReturn flow, GstFlowReturn flow1,
310 GstFlowReturn flow2, GstFlowReturn demux_flow, gboolean should_fail)
313 GstValidateReport *report;
314 GstValidatePadMonitor *pmonitor, *pmonitor1, *pmonitor2;
315 GstElement *demuxer = fake_demuxer_new ();
316 GstBin *pipeline = GST_BIN (gst_pipeline_new ("validate-pipeline"));
318 GstValidateRunner *runner;
320 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE));
321 runner = _start_monitoring_bin (pipeline);
323 gst_bin_add (pipeline, demuxer);
324 fake_demuxer_prepare_pads (pipeline, demuxer, runner);
326 srcpad = gst_pad_new ("srcpad1", GST_PAD_SRC);
327 gst_pad_link (srcpad, demuxer->sinkpads->data);
328 fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
329 gst_check_setup_events_with_stream_id (srcpad, demuxer, NULL,
330 GST_FORMAT_TIME, "the-stream");
332 pmonitor = _get_pad_monitor (gst_pad_get_peer (demuxer->srcpads->data));
334 _get_pad_monitor (gst_pad_get_peer (demuxer->srcpads->next->data));
336 _get_pad_monitor (gst_pad_get_peer (demuxer->srcpads->next->next->data));
338 pmonitor->last_flow_return = flow;
339 pmonitor1->last_flow_return = flow1;
340 pmonitor2->last_flow_return = flow2;
341 FAKE_DEMUXER (demuxer)->return_value = demux_flow;
343 fail_unless_equals_int (gst_pad_push (srcpad, gst_discont_buffer_new ()),
346 reports = gst_validate_runner_get_reports (runner);
348 assert_equals_int (g_list_length (reports), 1);
349 report = reports->data;
350 fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_CRITICAL);
351 fail_unless_equals_int (report->issue->issue_id, WRONG_FLOW_RETURN);
353 assert_equals_int (g_list_length (reports), 0);
357 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
358 clean_bus (GST_ELEMENT (pipeline));
360 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
361 ASSERT_OBJECT_REFCOUNT (pipeline, "ours", 1);
362 gst_object_ref (demuxer);
363 gst_object_ref (pmonitor);
364 _stop_monitoring_bin (pipeline, runner);
366 ASSERT_OBJECT_REFCOUNT (demuxer, "plop", 1);
367 gst_object_unref (demuxer);
368 ASSERT_OBJECT_REFCOUNT (pmonitor, "plop", 1);
369 gst_object_unref (pmonitor);
370 gst_object_unref (srcpad);
373 #define FLOW_TEST(name, flow1, flow2, flow3, demux_flow, fails) \
374 GST_START_TEST(flow_aggregation_##name) { \
375 _test_flow_aggregation (GST_FLOW_##flow1, GST_FLOW_##flow2, \
376 GST_FLOW_##flow3, GST_FLOW_##demux_flow, fails); \
379 FLOW_TEST (ok_ok_error_ok, OK, OK, ERROR, OK, TRUE);
380 FLOW_TEST (eos_eos_eos_ok, EOS, EOS, EOS, OK, TRUE);
381 FLOW_TEST (flushing_ok_ok_ok, FLUSHING, OK, OK, OK, TRUE);
382 FLOW_TEST (not_neg_ok_ok_ok, NOT_NEGOTIATED, OK, OK, OK, TRUE);
383 /*[> Passing cases: <]*/
384 FLOW_TEST (eos_eos_eos_eos, EOS, EOS, EOS, EOS, FALSE);
385 FLOW_TEST (eos_eos_ok_ok, EOS, EOS, OK, OK, FALSE);
386 FLOW_TEST (ok_ok_ok_eos, OK, OK, OK, EOS, FALSE);
387 FLOW_TEST (not_neg_ok_ok_not_neg, NOT_NEGOTIATED, OK, OK, NOT_NEGOTIATED,
391 GST_START_TEST (issue_concatenation)
393 GstPad *srcpad1, *srcpad2, *sinkpad, *fakemixer_sink1, *fakemixer_sink2;
394 GstElement *src1, *src2, *sink, *fakemixer;
395 GstValidateRunner *runner;
396 GstValidatePadMonitor *srcpad_monitor1, *srcpad_monitor2, *sinkpad_monitor;
397 GstValidatePadMonitor *fakemixer_sink_monitor1, *fakemixer_sink_monitor2;
401 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "subchain", TRUE));
402 runner = gst_validate_runner_new ();
404 src1 = create_and_monitor_element ("fakesrc2", NULL, runner);
405 src2 = create_and_monitor_element ("fakesrc2", NULL, runner);
406 fakemixer = create_and_monitor_element ("fakemixer", "fakemixer", runner);
407 sink = create_and_monitor_element ("fakesink", "fakesink", runner);
409 srcpad1 = gst_element_get_static_pad (src1, "src");
410 srcpad_monitor1 = g_object_get_data (G_OBJECT (srcpad1), "validate-monitor");
411 srcpad2 = gst_element_get_static_pad (src2, "src");
412 srcpad_monitor2 = g_object_get_data (G_OBJECT (srcpad2), "validate-monitor");
413 fakemixer_sink1 = gst_element_get_request_pad (fakemixer, "sink_%u");
414 fakemixer_sink_monitor1 =
415 g_object_get_data (G_OBJECT (fakemixer_sink1), "validate-monitor");
416 fakemixer_sink2 = gst_element_get_request_pad (fakemixer, "sink_%u");
417 fakemixer_sink_monitor2 =
418 g_object_get_data (G_OBJECT (fakemixer_sink2), "validate-monitor");
419 sinkpad = gst_element_get_static_pad (sink, "sink");
420 sinkpad_monitor = g_object_get_data (G_OBJECT (sinkpad), "validate-monitor");
422 fail_unless (gst_element_link (fakemixer, sink));
423 fail_unless (gst_pad_link (srcpad1, fakemixer_sink1) == GST_PAD_LINK_OK);
424 fail_unless (gst_pad_link (srcpad2, fakemixer_sink2) == GST_PAD_LINK_OK);
426 /* We want to handle the src behaviour ourselves */
427 fail_unless (gst_pad_activate_mode (srcpad1, GST_PAD_MODE_PUSH, TRUE));
428 fail_unless (gst_pad_activate_mode (srcpad2, GST_PAD_MODE_PUSH, TRUE));
430 gst_check_setup_events_with_stream_id (srcpad1, fakemixer, NULL,
431 GST_FORMAT_TIME, "stream1");
432 gst_check_setup_events_with_stream_id (srcpad2, fakemixer, NULL,
433 GST_FORMAT_TIME, "stream2");
435 fail_unless_equals_int (gst_element_set_state (fakemixer, GST_STATE_PLAYING),
436 GST_STATE_CHANGE_SUCCESS);
437 fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_PLAYING),
438 GST_STATE_CHANGE_ASYNC);
441 /* Send an unexpected flush stop */
442 _gst_check_expecting_log = TRUE;
443 fail_unless (gst_pad_push_event (srcpad1, gst_event_new_flush_stop (TRUE)));
445 /* The runner only sees one report */
446 reports = gst_validate_runner_get_reports (runner);
447 assert_equals_int (g_list_length (reports), 1);
448 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
450 /* Each pad monitor on the way actually holds a report */
451 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
453 fail_unless_equals_int (n_reports, 1);
454 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
456 fail_unless_equals_int (n_reports, 1);
457 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
458 fakemixer_sink_monitor1);
459 fail_unless_equals_int (n_reports, 1);
461 /* But not the pad monitor of the other fakemixer sink */
462 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
463 fakemixer_sink_monitor2);
464 fail_unless_equals_int (n_reports, 0);
465 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
467 fail_unless_equals_int (n_reports, 0);
469 /* Once again but on the other fakemixer sink */
470 fail_unless (gst_pad_push_event (srcpad2, gst_event_new_flush_stop (TRUE)));
472 /* The runner now sees two reports */
473 reports = gst_validate_runner_get_reports (runner);
474 assert_equals_int (g_list_length (reports), 2);
475 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
477 /* These monitors already saw that issue */
478 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
480 fail_unless_equals_int (n_reports, 1);
481 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
483 fail_unless_equals_int (n_reports, 1);
484 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
485 fakemixer_sink_monitor1);
486 fail_unless_equals_int (n_reports, 1);
488 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
489 fakemixer_sink_monitor2);
490 fail_unless_equals_int (n_reports, 1);
491 n_reports = gst_validate_reporter_get_reports_count ((GstValidateReporter *)
493 fail_unless_equals_int (n_reports, 1);
496 fail_unless (gst_pad_activate_mode (srcpad1, GST_PAD_MODE_PUSH, FALSE));
497 fail_unless (gst_pad_activate_mode (srcpad2, GST_PAD_MODE_PUSH, FALSE));
498 fail_unless_equals_int (gst_element_set_state (fakemixer, GST_STATE_NULL),
499 GST_STATE_CHANGE_SUCCESS);
500 fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_NULL),
501 GST_STATE_CHANGE_SUCCESS);
503 /* The reporter, the runner */
504 _check_reports_refcount (srcpad1, 2);
505 /* The reporter, the master report */
506 _check_reports_refcount (fakemixer_sink1, 2);
507 free_element_monitor (src1);
508 free_element_monitor (src2);
509 free_element_monitor (fakemixer);
510 free_element_monitor (sink);
511 gst_object_unref (srcpad1);
512 gst_object_unref (srcpad2);
513 gst_object_unref (sinkpad);
514 gst_object_unref (fakemixer_sink1);
515 gst_object_unref (fakemixer_sink2);
516 gst_check_objects_destroyed_on_unref (fakemixer, fakemixer_sink1,
517 fakemixer_sink2, NULL);
518 gst_check_objects_destroyed_on_unref (src1, srcpad1, NULL);
519 gst_check_objects_destroyed_on_unref (src2, srcpad2, NULL);
520 gst_check_objects_destroyed_on_unref (sink, sinkpad, NULL);
521 ASSERT_OBJECT_REFCOUNT (runner, "runner", 2);
522 gst_object_unref (runner);
528 static const gchar * media_info =
529 "<file duration='10031000000' frame-detection='1' uri='file:///I/am/so/fake.fakery' seekable='true'>"
530 " <streams caps='video/quicktime'>"
531 " <stream type='video' caps='video/x-raw'>"
532 " <frame duration='1' id='0' is-keyframe='true' offset='18446744073709551615' offset-end='18446744073709551615' pts='0' dts='0' checksum='cfeb9b47da2bb540cd3fa84cffea4df9'/>" /* buffer1 */
533 " <frame duration='1' id='1' is-keyframe='false' offset='18446744073709551615' offset-end='18446744073709551615' pts='1' dts='1' checksum='e40d7cd997bd14462468d201f1e1a3d4'/>" /* buffer2 */
534 " <frame duration='1' id='2' is-keyframe='false' offset='18446744073709551615' offset-end='18446744073709551615' pts='2' dts='2' checksum='4136320f0da0738a06c787dce827f034'/>" /* buffer3 */
535 " <frame duration='1' id='3' is-keyframe='false' offset='18446744073709551615' offset-end='18446744073709551615' pts='3' dts='3' checksum='sure my dear'/>" /* gonna fail */
536 " <frame duration='1' id='4' is-keyframe='true' offset='18446744073709551615' offset-end='18446744073709551615' pts='4' dts='4' checksum='569d8927835c44fd4ff40b8408657f9e'/>" /* buffer4 */
537 " <frame duration='1' id='5' is-keyframe='false' offset='18446744073709551615' offset-end='18446744073709551615' pts='5' dts='5' checksum='fcea4caed9b2c610fac1f2a6b38b1d5f'/>" /* buffer5 */
538 " <frame duration='1' id='6' is-keyframe='false' offset='18446744073709551615' offset-end='18446744073709551615' pts='6' dts='6' checksum='c7536747446a1503b1d9b02744144fa9'/>" /* buffer6 */
539 " <frame duration='1' id='7' is-keyframe='false' offset='18446744073709551615' offset-end='18446744073709551615' pts='7' dts='7' checksum='sure my dear'/>" /* gonna fail */
547 typedef struct _BufferDesc
549 const gchar *content;
552 GstClockTime duration;
559 _create_buffer (BufferDesc * bdesc)
561 gchar *tmp = g_strdup (bdesc->content);
563 gst_buffer_new_wrapped (tmp, strlen (tmp) * sizeof (gchar));
565 GST_BUFFER_DTS (buffer) = bdesc->dts;
566 GST_BUFFER_PTS (buffer) = bdesc->pts;
567 GST_BUFFER_DURATION (buffer) = bdesc->duration;
570 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
572 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
574 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
580 _check_media_info (GstSegment * segment, BufferDesc * bufs)
585 GstPad *srcpad, *sinkpad;
586 GstValidateReport *report;
587 GstValidateMonitor *monitor;
588 GstValidateRunner *runner;
589 GstValidateMediaDescriptor *mdesc;
593 gint i, num_issues = 0;
595 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE));
596 runner = gst_validate_runner_new ();
598 mdesc = (GstValidateMediaDescriptor *)
599 gst_validate_media_descriptor_parser_new_from_xml (runner, media_info,
602 decoder = fake_decoder_new ();
603 monitor = _start_monitoring_element (decoder, runner);
604 gst_validate_monitor_set_media_descriptor (monitor, mdesc);
605 gst_object_unref (mdesc);
607 srcpad = gst_pad_new ("src", GST_PAD_SRC);
608 sinkpad = decoder->sinkpads->data;
609 ASSERT_OBJECT_REFCOUNT (sinkpad, "decoder ref", 1);
610 fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
611 fail_unless_equals_int (gst_element_set_state (decoder, GST_STATE_PLAYING),
612 GST_STATE_CHANGE_SUCCESS);
614 assert_equals_string (gst_pad_link_get_name (gst_pad_link (srcpad, sinkpad)),
615 gst_pad_link_get_name (GST_PAD_LINK_OK));
619 ("video/x-raw, width=360, height=42, framerate=24/1, pixel-aspect-ratio =1/1, format=AYUV");
620 gst_check_setup_events_with_stream_id (srcpad, decoder, caps, GST_FORMAT_TIME,
622 gst_caps_unref (caps);
625 segev = gst_event_new_segment (segment);
626 fail_unless (gst_pad_push_event (srcpad, segev));
629 for (i = 0; bufs[i].content != NULL; i++) {
631 BufferDesc *buf = &bufs[i];
632 buffer = _create_buffer (buf);
634 assert_equals_string (gst_flow_get_name (gst_pad_push (srcpad, buffer)),
635 gst_flow_get_name (GST_FLOW_OK));
636 reports = gst_validate_runner_get_reports (runner);
638 num_issues += buf->num_issues;
639 assert_equals_int (g_list_length (reports), num_issues);
641 if (buf->num_issues) {
642 GList *tmp = g_list_nth (reports, num_issues - buf->num_issues);
647 fail_unless_equals_int (report->level,
648 GST_VALIDATE_REPORT_LEVEL_WARNING);
649 fail_unless_equals_int (report->issue->issue_id, WRONG_BUFFER);
653 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
657 fail_unless (gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, FALSE));
658 fail_unless_equals_int (gst_element_set_state (decoder, GST_STATE_NULL),
659 GST_STATE_CHANGE_SUCCESS);
661 gst_object_unref (srcpad);
662 gst_check_objects_destroyed_on_unref (decoder, sinkpad, NULL);
663 ASSERT_OBJECT_REFCOUNT (runner, "runner", 2);
664 gst_object_unref (runner);
665 gst_object_unref (monitor);
668 #define MEDIA_INFO_TEST(name,segment_start,bufs) \
669 GST_START_TEST(media_info_##name) { \
670 if (segment_start >= 0) { \
671 GstSegment segment; \
672 gst_segment_init (&segment, GST_FORMAT_TIME); \
673 segment.start = segment_start; \
674 _check_media_info (&segment, (bufs)); \
676 _check_media_info (NULL, (bufs)); \
680 MEDIA_INFO_TEST (1, -1,
683 .content = "buffer1",
691 .content = "buffer2",
699 .content = "buffer3",
707 .content = "fail please",
717 /* Segment start is 2, the first buffer is expected (first Keyframe) */
718 MEDIA_INFO_TEST (2, 2,
721 .content = "buffer2", /* Wrong checksum */
731 /* Segment start is 2, the first buffer is expected (first Keyframe) */
732 MEDIA_INFO_TEST (3, 2,
734 { /* The right first buffer */
735 .content = "buffer1",
745 /* Segment start is 6, the 4th buffer is expected (first Keyframe) */
746 MEDIA_INFO_TEST (4, 6,
748 { /* The right fourth buffer */
749 .content = "buffer4",
759 /* Segment start is 6, the 4th buffer is expected (first Keyframe) */
760 MEDIA_INFO_TEST (5, 6,
762 { /* The sixth buffer... all wrong! */
763 .content = "buffer6",
774 GST_START_TEST (caps_events)
776 GstPad *srcpad, *sinkpad;
777 GstElement *decoder = fake_decoder_new ();
778 GstElement *sink = gst_element_factory_make ("fakesink", NULL);
779 GstBin *pipeline = GST_BIN (gst_pipeline_new ("validate-pipeline"));
781 GstValidateReport *report;
782 GstValidateRunner *runner;
785 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE));
786 runner = _start_monitoring_bin (pipeline);
788 gst_bin_add_many (pipeline, decoder, sink, NULL);
789 srcpad = gst_pad_new ("srcpad1", GST_PAD_SRC);
790 sinkpad = decoder->sinkpads->data;
791 gst_pad_link (srcpad, sinkpad);
793 gst_element_link (decoder, sink);
794 fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
795 GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC);
796 fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
798 reports = gst_validate_runner_get_reports (runner);
799 assert_equals_int (g_list_length (reports), 0);
800 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
804 ("video/x-raw, format=AYUV, width=320, height=240, pixel-aspect-ratio=1/1");
805 fail_unless (gst_pad_push_event (srcpad, gst_event_new_caps (caps)));
806 gst_caps_unref (caps);
807 reports = gst_validate_runner_get_reports (runner);
809 /* Our caps didn't have a framerate, the decoder sink should complain about
811 assert_equals_int (g_list_length (reports), 1);
812 report = reports->data;
813 fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_ISSUE);
814 fail_unless_equals_int (report->issue->issue_id, CAPS_IS_MISSING_FIELD);
815 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
819 ("video/x-raw, format=AYUV, framerate=24/1, width=(fraction)320, height=240, pixel-aspect-ratio=1/1");
820 fail_unless (gst_pad_push_event (srcpad, gst_event_new_caps (caps)));
821 gst_caps_unref (caps);
823 reports = gst_validate_runner_get_reports (runner);
824 assert_equals_int (g_list_length (reports), 2);
825 report = reports->next->data;
826 /* A width isn't supposed to be a fraction */
827 fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_WARNING);
828 fail_unless_equals_int (report->issue->issue_id, CAPS_FIELD_HAS_BAD_TYPE);
829 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
833 ("video/x-raw, format=AYUV, framerate=24/1, width=320, height=240, pixel-aspect-ratio=1/1");
834 fail_unless (gst_pad_push_event (srcpad, gst_event_new_caps (caps)));
835 gst_caps_unref (caps);
839 ("video/x-raw, format=AYUV, framerate=24/1, width=320, height=240, pixel-aspect-ratio=1/1");
840 fail_unless (gst_pad_push_event (srcpad, gst_event_new_caps (caps)));
841 gst_caps_unref (caps);
843 reports = gst_validate_runner_get_reports (runner);
844 assert_equals_int (g_list_length (reports), 3);
845 report = reports->next->next->data;
846 /* A width isn't supposed to be a fraction */
847 fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_WARNING);
848 /* Pushing the same twice isn't very useful */
849 fail_unless_equals_int (report->issue->issue_id, EVENT_CAPS_DUPLICATE);
852 clean_bus (GST_ELEMENT (pipeline));
854 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
856 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
857 _stop_monitoring_bin (pipeline, runner);
859 gst_object_unref (srcpad);
864 GST_START_TEST (eos_without_segment)
866 GstPad *srcpad, *sinkpad;
867 GstValidateReport *report;
868 GstElement *decoder = fake_decoder_new ();
869 GstElement *sink = gst_element_factory_make ("fakesink", NULL);
870 GstBin *pipeline = GST_BIN (gst_pipeline_new ("validate-pipeline"));
872 GstValidateRunner *runner;
874 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE));
875 runner = _start_monitoring_bin (pipeline);
877 gst_bin_add_many (pipeline, decoder, sink, NULL);
878 srcpad = gst_pad_new ("srcpad1", GST_PAD_SRC);
879 sinkpad = decoder->sinkpads->data;
880 gst_pad_link (srcpad, sinkpad);
882 gst_element_link (decoder, sink);
883 fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
884 GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC);
885 fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
887 reports = gst_validate_runner_get_reports (runner);
888 assert_equals_int (g_list_length (reports), 0);
889 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
891 fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
892 reports = gst_validate_runner_get_reports (runner);
894 /* Getting the issue on the srcpad -> decoder.sinkpad -> decoder->srcpad */
895 assert_equals_int (g_list_length (reports), 3);
896 report = reports->data;
897 fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_WARNING);
898 fail_unless_equals_int (report->issue->issue_id, EVENT_EOS_WITHOUT_SEGMENT);
899 clean_bus (GST_ELEMENT (pipeline));
901 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
903 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
904 _stop_monitoring_bin (pipeline, runner);
906 gst_object_unref (srcpad);
911 GST_START_TEST (buffer_timestamp_out_of_received_range)
913 GstPad *srcpad, *sinkpad;
914 GstElement *decoder = fake_decoder_new ();
915 GstElement *sink = gst_element_factory_make ("fakesink", NULL);
916 GstBin *pipeline = GST_BIN (gst_pipeline_new ("validate-pipeline"));
918 GstValidateRunner *runner;
921 GstPad *decoder_srcpad;
922 GstValidateReport *report;
924 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE));
925 runner = _start_monitoring_bin (pipeline);
927 gst_bin_add_many (pipeline, decoder, sink, NULL);
928 srcpad = gst_pad_new ("srcpad1", GST_PAD_SRC);
929 sinkpad = decoder->sinkpads->data;
930 gst_pad_link (srcpad, sinkpad);
932 gst_element_link (decoder, sink);
933 ASSERT_SET_STATE (GST_ELEMENT (pipeline), GST_STATE_PLAYING,
934 GST_STATE_CHANGE_ASYNC);
935 fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
937 gst_segment_init (&segment, GST_FORMAT_TIME);
939 segment.stop = GST_SECOND;
940 fail_unless (gst_pad_push_event (srcpad,
941 gst_event_new_stream_start ("the-stream")));
942 fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&segment)));
945 buffer = gst_discont_buffer_new ();
946 GST_BUFFER_PTS (buffer) = 0 * GST_SECOND;
947 GST_BUFFER_DURATION (buffer) = 0.1 * GST_SECOND;
948 fail_unless (gst_pad_push (srcpad, buffer) == GST_FLOW_OK);
951 decoder_srcpad = gst_element_get_static_pad (decoder, "src");
954 buffer = gst_discont_buffer_new ();
955 GST_BUFFER_PTS (buffer) = 0.9 * GST_SECOND;
956 GST_BUFFER_DURATION (buffer) = 0.1 * GST_SECOND;
957 fail_unless (gst_pad_push (decoder_srcpad, buffer) == GST_FLOW_OK);
960 reports = gst_validate_runner_get_reports (runner);
962 assert_equals_int (g_list_length (reports), 1);
963 report = reports->data;
964 fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_WARNING);
965 fail_unless_equals_int (report->issue->issue_id,
966 BUFFER_TIMESTAMP_OUT_OF_RECEIVED_RANGE);
967 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
969 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
971 gst_object_unref (decoder_srcpad);
972 gst_object_unref (srcpad);
974 _stop_monitoring_bin (pipeline, runner);
980 GST_START_TEST (flow_error_without_message)
982 GstElement *decoder = fake_decoder_new ();
983 GstElement *src = gst_element_factory_make ("fakesrc", NULL);
984 GstElement *sink = gst_element_factory_make ("fakesink", NULL);
985 GstBin *pipeline = GST_BIN (gst_pipeline_new ("validate-pipeline"));
987 GstValidateRunner *runner;
988 GstValidateReport *report;
990 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE));
991 runner = _start_monitoring_bin (pipeline);
993 gst_bin_add_many (pipeline, src, decoder, sink, NULL);
994 fail_unless (gst_element_link_many (src, decoder, sink, NULL));
996 FAKE_DECODER (decoder)->return_value = GST_FLOW_ERROR;
997 ASSERT_SET_STATE (GST_ELEMENT (pipeline), GST_STATE_PLAYING,
998 GST_STATE_CHANGE_ASYNC);
1000 gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
1001 GST_CLOCK_TIME_NONE);
1003 reports = gst_validate_runner_get_reports (runner);
1005 fail_unless (g_list_length (reports) >= 1);
1006 report = reports->data;
1007 fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_WARNING);
1008 fail_unless_equals_int (report->issue->issue_id,
1009 FLOW_ERROR_WITHOUT_ERROR_MESSAGE);
1010 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
1012 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
1014 _stop_monitoring_bin (pipeline, runner);
1020 GST_START_TEST (flow_error_with_message)
1022 GstElement *decoder = fake_decoder_new ();
1023 GstElement *src = gst_element_factory_make ("fakesrc", NULL);
1024 GstElement *sink = gst_element_factory_make ("fakesink", NULL);
1025 GstBin *pipeline = GST_BIN (gst_pipeline_new ("validate-pipeline"));
1027 GstValidateRunner *runner;
1028 GstValidateReport *report;
1029 const GError gerror =
1030 { G_IO_ERROR, G_IO_ERROR_FAILED, (gchar *) "fake error" };
1032 fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE));
1033 runner = _start_monitoring_bin (pipeline);
1035 gst_bin_add_many (pipeline, src, decoder, sink, NULL);
1036 fail_unless (gst_element_link_many (src, decoder, sink, NULL));
1038 g_object_set (src, "is-live", TRUE, NULL);
1040 FAKE_DECODER (decoder)->return_value = GST_FLOW_ERROR;
1042 ASSERT_SET_STATE (GST_ELEMENT (pipeline), GST_STATE_PAUSED,
1043 GST_STATE_CHANGE_NO_PREROLL);
1045 gst_element_post_message (decoder,
1046 gst_message_new_error (GST_OBJECT (decoder),
1047 (GError *) & gerror, "This is a fake error"));
1049 ASSERT_SET_STATE (GST_ELEMENT (pipeline), GST_STATE_PLAYING,
1050 GST_STATE_CHANGE_ASYNC);
1052 gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
1053 GST_CLOCK_TIME_NONE);
1055 reports = gst_validate_runner_get_reports (runner);
1057 assert_equals_int (g_list_length (reports), 1);
1058 report = reports->data;
1059 fail_unless_equals_int (report->issue->issue_id, ERROR_ON_BUS);
1060 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
1062 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
1064 _stop_monitoring_bin (pipeline, runner);
1072 gst_validate_suite (void)
1074 Suite *s = suite_create ("padmonitor");
1075 TCase *tc_chain = tcase_create ("padmonitor");
1076 suite_add_tcase (s, tc_chain);
1078 if (atexit (gst_validate_deinit) != 0) {
1079 GST_ERROR ("failed to set gst_validate_deinit as exit function");
1082 fake_elements_register ();
1084 tcase_add_test (tc_chain, buffer_before_segment);
1085 tcase_add_test (tc_chain, buffer_outside_segment);
1086 tcase_add_test (tc_chain, buffer_timestamp_out_of_received_range);
1088 tcase_add_test (tc_chain, media_info_1);
1089 tcase_add_test (tc_chain, media_info_2);
1090 tcase_add_test (tc_chain, media_info_3);
1091 tcase_add_test (tc_chain, media_info_4);
1092 tcase_add_test (tc_chain, media_info_5);
1094 tcase_add_test (tc_chain, flow_aggregation_ok_ok_error_ok);
1095 tcase_add_test (tc_chain, flow_aggregation_eos_eos_eos_ok);
1096 tcase_add_test (tc_chain, flow_aggregation_flushing_ok_ok_ok);
1097 tcase_add_test (tc_chain, flow_aggregation_not_neg_ok_ok_ok);
1098 tcase_add_test (tc_chain, flow_aggregation_eos_eos_eos_eos);
1099 tcase_add_test (tc_chain, flow_aggregation_eos_eos_ok_ok);
1100 tcase_add_test (tc_chain, flow_aggregation_ok_ok_ok_eos);
1101 tcase_add_test (tc_chain, flow_aggregation_not_neg_ok_ok_not_neg);
1103 tcase_add_test (tc_chain, issue_concatenation);
1104 tcase_add_test (tc_chain, eos_without_segment);
1105 tcase_add_test (tc_chain, caps_events);
1106 tcase_add_test (tc_chain, flow_error_without_message);
1107 tcase_add_test (tc_chain, flow_error_with_message);
1112 GST_CHECK_MAIN (gst_validate);