From bb93dbb9fb580ece3f505e8d39a53c1e8dbd6d83 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 15 Sep 2014 17:27:54 +0200 Subject: [PATCH] validate: Check all buffers when we have the info from MediaDescriptor We now check that each buffer is the expected one for each buffer that come into the decoder. + Fix some minor leaks in test-utils https://bugzilla.gnome.org/show_bug.cgi?id=736138 --- .../gst/validate/gst-validate-pad-monitor.c | 174 ++++++++++++ .../gst/validate/gst-validate-pad-monitor.h | 7 + validate/gst/validate/gst-validate-report.c | 6 + validate/gst/validate/gst-validate-report.h | 1 + validate/tests/check/validate/padmonitor.c | 256 ++++++++++++++++++ validate/tests/check/validate/test-utils.c | 106 ++++++-- validate/tests/check/validate/test-utils.h | 19 ++ validate/tools/launcher/apps/gstvalidate.py | 2 + 8 files changed, 555 insertions(+), 16 deletions(-) diff --git a/validate/gst/validate/gst-validate-pad-monitor.c b/validate/gst/validate/gst-validate-pad-monitor.c index 159efa8e6a..a5f15572ab 100644 --- a/validate/gst/validate/gst-validate-pad-monitor.c +++ b/validate/gst/validate/gst-validate-pad-monitor.c @@ -1471,6 +1471,94 @@ mark_pads_eos (GstValidatePadMonitor *pad_monitor) } } +static inline gboolean +_should_check_buffers (GstValidatePadMonitor * pad_monitor, + gboolean force_checks) +{ + GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor); + GstValidateMonitor *monitor = GST_VALIDATE_MONITOR (pad_monitor); + + if (pad_monitor->first_buffer || force_checks) { + if (pad_monitor->segment.rate != 1.0) { + GST_INFO_OBJECT (pad_monitor, "We do not support buffer checking" + " for trick modes"); + + pad_monitor->check_buffers = FALSE; + } else if (!PAD_PARENT_IS_DECODER (pad_monitor)) { + GST_DEBUG_OBJECT (pad, "Not on a decoder => no buffer checking"); + + pad_monitor->check_buffers = FALSE; + } else if (GST_PAD_DIRECTION (pad) != GST_PAD_SINK) { + GST_DEBUG_OBJECT (pad, "Not a sinkpad => no buffer checking"); + + pad_monitor->check_buffers = FALSE; + } else if (!pad_monitor->caps_is_video) { + GST_DEBUG_OBJECT (pad, "Not working with video => no buffer checking"); + + pad_monitor->check_buffers = FALSE; + } else if (monitor->media_descriptor == NULL) { + GST_DEBUG_OBJECT (pad, "No media_descriptor set => no buffer checking"); + + pad_monitor->check_buffers = FALSE; + } else if (!gst_media_descriptor_detects_frames (monitor->media_descriptor)) { + GST_DEBUG_OBJECT (pad, "No frame detection media descriptor " + "=> not buffer checking"); + pad_monitor->check_buffers = FALSE; + } else if (pad_monitor->all_bufs == NULL && + !gst_media_descriptor_get_buffers (monitor->media_descriptor, pad, NULL, + &pad_monitor->all_bufs)) { + + GST_INFO_OBJECT (monitor, + "The MediaInfo is marked as detecting frame, but getting frames" + " from pad %" GST_PTR_FORMAT " did not work (some format conversion" + " might be happening)", pad); + + pad_monitor->check_buffers = FALSE; + } else { + if (!pad_monitor->current_buf) + pad_monitor->current_buf = pad_monitor->all_bufs; + pad_monitor->check_buffers = TRUE; + } + } + + return pad_monitor->check_buffers; +} + +static void +gst_validate_monitor_find_next_buffer (GstValidatePadMonitor * pad_monitor) +{ + GList *tmp; + gboolean passed_start = FALSE; + + if (!_should_check_buffers (pad_monitor, TRUE)) + return; + + for (tmp = g_list_last (pad_monitor->all_bufs); tmp; tmp = tmp->prev) { + GstBuffer *cbuf = tmp->data; + GstClockTime ts = + GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (cbuf)) ? GST_BUFFER_DTS (cbuf) + : GST_BUFFER_PTS (cbuf); + + if (!GST_CLOCK_TIME_IS_VALID (ts)) + continue; + + if (ts <= pad_monitor->segment.start) + passed_start = TRUE; + + if (!passed_start) + continue; + + if (!GST_BUFFER_FLAG_IS_SET (cbuf, GST_BUFFER_FLAG_DELTA_UNIT)) { + break; + } + } + + if (tmp == NULL) + pad_monitor->current_buf = pad_monitor->all_bufs; + else + pad_monitor->current_buf = tmp; +} + static gboolean gst_validate_pad_monitor_downstream_event_check (GstValidatePadMonitor * pad_monitor, GstObject * parent, GstEvent * event, @@ -1582,6 +1670,7 @@ gst_validate_pad_monitor_downstream_event_check (GstValidatePadMonitor * } gst_segment_copy_into (segment, &pad_monitor->segment); pad_monitor->has_segment = TRUE; + gst_validate_monitor_find_next_buffer (pad_monitor); } break; case GST_EVENT_CAPS:{ @@ -1685,6 +1774,90 @@ gst_validate_pad_monitor_src_event_check (GstValidatePadMonitor * pad_monitor, return ret; } +static gboolean +gst_validate_pad_monitor_check_right_buffer (GstValidatePadMonitor * + pad_monitor, GstBuffer * buffer) +{ + gchar *checksum; + GstBuffer *wanted_buf; + GstMapInfo map, wanted_map; + + gboolean ret = TRUE; + GstPad *pad = GST_VALIDATE_PAD_MONITOR_GET_PAD (pad_monitor); + + if (_should_check_buffers (pad_monitor, FALSE) == FALSE) + return FALSE; + + if (pad_monitor->current_buf == NULL) { + GST_INFO_OBJECT (pad, "No current buffer one pad, Why?"); + return FALSE; + } + + wanted_buf = pad_monitor->current_buf->data; + + if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (wanted_buf)) && + GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buffer)) && + GST_BUFFER_PTS (wanted_buf) != GST_BUFFER_PTS (buffer)) { + + GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER, + "buffer %" GST_PTR_FORMAT " PTS %ld" + " different than expected: %ld", buffer, + GST_BUFFER_PTS (buffer), GST_BUFFER_PTS (wanted_buf)); + + ret = FALSE; + } + + if (GST_BUFFER_DTS (wanted_buf) != GST_BUFFER_DTS (buffer)) { + GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER, + "buffer %" GST_PTR_FORMAT " DTS %" GST_TIME_FORMAT + " different than expected: %" GST_TIME_FORMAT, buffer, + GST_TIME_ARGS (GST_BUFFER_DTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_DTS (wanted_buf))); + ret = FALSE; + } + + if (GST_BUFFER_DURATION (wanted_buf) != GST_BUFFER_DURATION (buffer)) { + GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER, + "buffer %" GST_PTR_FORMAT " DURATION %" GST_TIME_FORMAT + " different than expected: %" GST_TIME_FORMAT, buffer, + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)), + GST_TIME_ARGS (GST_BUFFER_DURATION (wanted_buf))); + ret = FALSE; + } + + if (GST_BUFFER_FLAG_IS_SET (wanted_buf, GST_BUFFER_FLAG_DELTA_UNIT) != + GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) { + GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER, + "buffer %" GST_PTR_FORMAT " Delta unit is set to %s but expected %s", + buffer, GST_BUFFER_FLAG_IS_SET (buffer, + GST_BUFFER_FLAG_DELTA_UNIT) ? "True" : "False", + GST_BUFFER_FLAG_IS_SET (wanted_buf, + GST_BUFFER_FLAG_DELTA_UNIT) ? "True" : "False"); + ret = FALSE; + } + + g_assert (gst_buffer_map (wanted_buf, &wanted_map, GST_MAP_READ)); + g_assert (gst_buffer_map (buffer, &map, GST_MAP_READ)); + + checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, + (const guchar *) map.data, map.size); + + if (g_strcmp0 ((gchar *) wanted_map.data, checksum)) { + GST_VALIDATE_REPORT (pad_monitor, WRONG_BUFFER, + "buffer %" GST_PTR_FORMAT " checksum %s different from expected: %s", + buffer, checksum, wanted_map.data); + ret = FALSE; + } + + gst_buffer_unmap (wanted_buf, &wanted_map); + gst_buffer_unmap (buffer, &map); + g_free (checksum); + + pad_monitor->current_buf = pad_monitor->current_buf->next; + + return ret; +} + static GstFlowReturn gst_validate_pad_monitor_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer) @@ -1696,6 +1869,7 @@ gst_validate_pad_monitor_chain_func (GstPad * pad, GstObject * parent, GST_VALIDATE_PAD_MONITOR_PARENT_LOCK (pad_monitor); GST_VALIDATE_MONITOR_LOCK (pad_monitor); + gst_validate_pad_monitor_check_right_buffer (pad_monitor, buffer); gst_validate_pad_monitor_check_first_buffer (pad_monitor, buffer); gst_validate_pad_monitor_update_buffer_data (pad_monitor, buffer); gst_validate_pad_monitor_check_eos (pad_monitor, buffer); diff --git a/validate/gst/validate/gst-validate-pad-monitor.h b/validate/gst/validate/gst-validate-pad-monitor.h index 27f9f2f734..82737bed16 100644 --- a/validate/gst/validate/gst-validate-pad-monitor.h +++ b/validate/gst/validate/gst-validate-pad-monitor.h @@ -29,6 +29,7 @@ typedef struct _GstValidatePadMonitor GstValidatePadMonitor; typedef struct _GstValidatePadMonitorClass GstValidatePadMonitorClass; #include +#include #include G_BEGIN_DECLS @@ -110,6 +111,12 @@ struct _GstValidatePadMonitor { */ GstClockTime timestamp_range_start; GstClockTime timestamp_range_end; + + /* GstMediaCheck related fields */ + GList *all_bufs; + /* The GstBuffer that should arrive next in a GList */ + GList *current_buf; + gboolean check_buffers; }; /** diff --git a/validate/gst/validate/gst-validate-report.c b/validate/gst/validate/gst-validate-report.c index cca74aea46..a2211658cd 100644 --- a/validate/gst/validate/gst-validate-report.c +++ b/validate/gst/validate/gst-validate-report.c @@ -130,6 +130,12 @@ gst_validate_report_load_issues (void) REGISTER_VALIDATE_ISSUE (WARNING, FIRST_BUFFER_RUNNING_TIME_IS_NOT_ZERO, _("first buffer's running time isn't 0"), _("the first buffer's received running time is expected to be 0")); + REGISTER_VALIDATE_ISSUE (WARNING, WRONG_BUFFER, + _("Received buffer does not correspond to wanted one."), + _("When checking playback of a file against a MediaInfo file" + " all buffers coming into the decoders might be checked" + " and should have the exact expected metadatas and hash of the" + " content")); REGISTER_VALIDATE_ISSUE (CRITICAL, WRONG_FLOW_RETURN, _("flow return from pad push doesn't match expected value"), _("flow return from a 1:1 sink/src pad element is as simple as " diff --git a/validate/gst/validate/gst-validate-report.h b/validate/gst/validate/gst-validate-report.h index e9ce167d1e..c80c0ecb3d 100644 --- a/validate/gst/validate/gst-validate-report.h +++ b/validate/gst/validate/gst-validate-report.h @@ -77,6 +77,7 @@ typedef enum { #define GST_VALIDATE_ISSUE_ID_FIRST_BUFFER_RUNNING_TIME_IS_NOT_ZERO (((GstValidateIssueId) GST_VALIDATE_AREA_BUFFER) << GST_VALIDATE_ISSUE_ID_SHIFT | 4) #define GST_VALIDATE_ISSUE_ID_WRONG_FLOW_RETURN (((GstValidateIssueId) GST_VALIDATE_AREA_BUFFER) << GST_VALIDATE_ISSUE_ID_SHIFT | 5) #define GST_VALIDATE_ISSUE_ID_BUFFER_AFTER_EOS (((GstValidateIssueId) GST_VALIDATE_AREA_BUFFER) << GST_VALIDATE_ISSUE_ID_SHIFT | 6) +#define GST_VALIDATE_ISSUE_ID_WRONG_BUFFER (((GstValidateIssueId) GST_VALIDATE_AREA_BUFFER) << GST_VALIDATE_ISSUE_ID_SHIFT | 7) #define GST_VALIDATE_ISSUE_ID_CAPS_IS_MISSING_FIELD (((GstValidateIssueId) GST_VALIDATE_AREA_CAPS) << GST_VALIDATE_ISSUE_ID_SHIFT | 1) #define GST_VALIDATE_ISSUE_ID_CAPS_FIELD_HAS_BAD_TYPE (((GstValidateIssueId) GST_VALIDATE_AREA_CAPS) << GST_VALIDATE_ISSUE_ID_SHIFT | 2) diff --git a/validate/tests/check/validate/padmonitor.c b/validate/tests/check/validate/padmonitor.c index 73558b12bb..477a51ba96 100644 --- a/validate/tests/check/validate/padmonitor.c +++ b/validate/tests/check/validate/padmonitor.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "test-utils.h" @@ -545,6 +546,260 @@ GST_START_TEST (issue_concatenation) check_destroyed (sink, sinkpad, NULL); check_destroyed (runner, NULL, NULL); } +GST_END_TEST; + +/* *INDENT-OFF* */ +static const gchar * media_info = +"" +" " +" " +" " /* buffer1 */ +" " /* buffer2 */ +" " /* buffer3 */ +" " /* gonna fail */ +" " /* buffer4 */ +" " /* buffer5 */ +" " /* buffer6 */ +" " /* gonna fail */ +" " +" " +" " +" " +""; +/* *INDENT-ON* */ + +typedef struct _BufferDesc +{ + const gchar *content; + GstClockTime pts; + GstClockTime dts; + GstClockTime duration; + gboolean keyframe; + + gint num_issues; +} BufferDesc; + +static GstBuffer * +_create_buffer (BufferDesc * bdesc) +{ + gchar *tmp = g_strdup (bdesc->content); + GstBuffer *buffer = + gst_buffer_new_wrapped (tmp, strlen (tmp) * sizeof (gchar)); + + GST_BUFFER_DTS (buffer) = bdesc->dts; + GST_BUFFER_PTS (buffer) = bdesc->pts; + GST_BUFFER_DURATION (buffer) = bdesc->duration; + + if (bdesc->keyframe) + GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + else + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + return buffer; +} + +static void +_check_media_info (GstSegment * segment, BufferDesc * bufs) +{ + GList *reports; + GstEvent *segev; + GstBuffer *buffer; + GstElement *decoder; + GstPad *srcpad, *sinkpad; + GstValidateReport *report; + GstValidateMonitor *monitor; + GstValidateRunner *runner; + GstMediaDescriptor *mdesc; + + GError *err = NULL; + gint i, num_issues = 0; + + fail_unless (g_setenv ("GST_VALIDATE_REPORT_LEVEL", "all", TRUE)); + runner = gst_validate_runner_new (); + + mdesc = (GstMediaDescriptor *) + gst_media_descriptor_parser_new_from_xml (runner, media_info, &err); + + decoder = fake_decoder_new (); + monitor = gst_validate_monitor_factory_create (GST_OBJECT (decoder), + runner, NULL); + gst_validate_monitor_set_media_descriptor (monitor, mdesc); + + srcpad = gst_pad_new ("src", GST_PAD_SRC); + sinkpad = decoder->sinkpads->data; + ASSERT_OBJECT_REFCOUNT (sinkpad, "decoder ref", 1); + fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE)); + fail_unless_equals_int (gst_element_set_state (decoder, GST_STATE_PLAYING), + GST_STATE_CHANGE_SUCCESS); + + assert_equals_string (gst_pad_link_get_name (gst_pad_link (srcpad, sinkpad)), + gst_pad_link_get_name (GST_PAD_LINK_OK)); + + gst_check_setup_events_with_stream_id (srcpad, decoder, + gst_caps_from_string ("video/x-fake"), GST_FORMAT_TIME, "the-stream"); + + + if (segment) { + segev = gst_event_new_segment (segment); + fail_unless (gst_pad_push_event (srcpad, segev)); + } + + for (i = 0; bufs[i].content != NULL; i++) { + BufferDesc *buf = &bufs[i]; + buffer = _create_buffer (buf); + + assert_equals_string (gst_flow_get_name (gst_pad_push (srcpad, buffer)), + gst_flow_get_name (GST_FLOW_OK)); + reports = gst_validate_runner_get_reports (runner); + + num_issues += buf->num_issues; + assert_equals_int (g_list_length (reports), num_issues); + + if (buf->num_issues) { + GList *tmp = g_list_nth (reports, num_issues - buf->num_issues); + + while (tmp) { + report = tmp->data; + + fail_unless_equals_int (report->level, + GST_VALIDATE_REPORT_LEVEL_WARNING); + fail_unless_equals_int (report->issue->issue_id, + GST_VALIDATE_ISSUE_ID_WRONG_BUFFER); + tmp = tmp->next; + } + } + } + + /* clean up */ + fail_unless (gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, FALSE)); + fail_unless_equals_int (gst_element_set_state (decoder, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (srcpad); + check_destroyed (decoder, sinkpad, NULL); + check_destroyed (runner, NULL, NULL); +} + +GST_START_TEST (check_media_info) +{ + GstSegment segment; + + +/* *INDENT-OFF* */ + _check_media_info (NULL, + (BufferDesc []) { + { + .content = "buffer1", + .pts = 0, + .dts = 0, + .duration = 1, + .keyframe = TRUE, + .num_issues = 0 + }, + { + .content = "buffer2", + .pts = 1, + .dts = 1, + .duration = 1, + .keyframe = FALSE, + .num_issues = 0 + }, + { + .content = "buffer3", + .pts = 2, + .dts = 2, + .duration = 1, + .keyframe = FALSE, + .num_issues = 0 + }, + { + .content = "fail please", + .pts = 3, + .dts = 3, + .duration = 1, + .keyframe = FALSE, + .num_issues = 1 + }, + { NULL} + }); +/* *INDENT-ON* */ + + gst_segment_init (&segment, GST_FORMAT_TIME); + /* Segment start is 2, the first buffer is expected (first Keyframe) */ + segment.start = 2; + +/* *INDENT-OFF* */ + _check_media_info (&segment, + (BufferDesc []) { + { + .content = "buffer2", /* Wrong checksum */ + .pts = 0, + .dts = 0, + .duration = 1, + .keyframe = TRUE, + .num_issues = 1 + }, + { NULL} + }); +/* *INDENT-ON* */ + + gst_segment_init (&segment, GST_FORMAT_TIME); + /* Segment start is 2, the first buffer is expected (first Keyframe) */ + segment.start = 2; + +/* *INDENT-OFF* */ + _check_media_info (&segment, + (BufferDesc []) { + { /* The right first buffer */ + .content = "buffer1", + .pts = 0, + .dts = 0, + .duration = 1, + .keyframe = TRUE, + .num_issues = 0 + }, + { NULL} + }); +/* *INDENT-ON* */ + + gst_segment_init (&segment, GST_FORMAT_TIME); + /* Segment start is 6, the 4th buffer is expected (first Keyframe) */ + segment.start = 6; + +/* *INDENT-OFF* */ + _check_media_info (&segment, + (BufferDesc []) { + { /* The right fourth buffer */ + .content = "buffer4", + .pts = 4, + .dts = 4, + .duration = 1, + .keyframe = TRUE, + .num_issues = 0 + }, + { NULL} + }); +/* *INDENT-ON* */ + + gst_segment_init (&segment, GST_FORMAT_TIME); + /* Segment start is 6, the 4th buffer is expected (first Keyframe) */ + segment.start = 6; + +/* *INDENT-OFF* */ + _check_media_info (&segment, + (BufferDesc []) { + { /* The sixth buffer... all wrong! */ + .content = "buffer6", + .pts = 6, + .dts = 6, + .duration = 1, + .keyframe = FALSE, + .num_issues = 1 + }, + { NULL} + }); +/* *INDENT-ON* */ +} GST_END_TEST; @@ -562,6 +817,7 @@ gst_validate_suite (void) tcase_add_test (tc_chain, first_buffer_running_time); tcase_add_test (tc_chain, flow_aggregation); tcase_add_test (tc_chain, issue_concatenation); + tcase_add_test (tc_chain, check_media_info); return s; } diff --git a/validate/tests/check/validate/test-utils.c b/validate/tests/check/validate/test-utils.c index c67f555515..5265d966aa 100644 --- a/validate/tests/check/validate/test-utils.c +++ b/validate/tests/check/validate/test-utils.c @@ -102,18 +102,8 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_CAPS ("something") ); -static void -fake_demuxer_dispose (FakeDemuxer * self) -{ -} - -static void -fake_demuxer_finalize (FakeDemuxer * self) -{ -} - static GstFlowReturn -_chain (GstPad * pad, GstObject * self, GstBuffer * buffer) +_demuxer_chain (GstPad * pad, GstObject * self, GstBuffer * buffer) { gst_buffer_unref (buffer); @@ -146,18 +136,14 @@ fake_demuxer_init (FakeDemuxer * self, gpointer * g_class) self->return_value = GST_FLOW_OK; - gst_pad_set_chain_function (pad, _chain); + gst_pad_set_chain_function (pad, _demuxer_chain); } static void fake_demuxer_class_init (FakeDemuxerClass * self_class) { - GObjectClass *object_class = G_OBJECT_CLASS (self_class); GstElementClass *gstelement_class = GST_ELEMENT_CLASS (self_class); - object_class->dispose = (void (*)(GObject * object)) fake_demuxer_dispose; - object_class->finalize = (void (*)(GObject * object)) fake_demuxer_finalize; - gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&fake_demuxer_src_template)); gst_element_class_add_pad_template (gstelement_class, @@ -222,3 +208,91 @@ free_element_monitor (GstElement *element) g_object_unref (G_OBJECT(monitor)); } + +static GstStaticPadTemplate fake_decoder_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("video/x-fake") + ); + +static GstStaticPadTemplate fake_decoder_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-fake") + ); + +static GstFlowReturn +_decoder_chain (GstPad * pad, GstObject * self, GstBuffer * buffer) +{ + gst_buffer_unref (buffer); + + return FAKE_DECODER (self)->return_value; +} + +static void +fake_decoder_init (FakeDecoder * self, gpointer * g_class) +{ + GstPad *pad; + GstElement *element = GST_ELEMENT (self); + GstPadTemplate *pad_template; + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src"); + pad = gst_pad_new_from_template (pad_template, "src"); + gst_element_add_pad (element, pad); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"); + pad = gst_pad_new_from_template (pad_template, "sink"); + gst_element_add_pad (element, pad); + + self->return_value = GST_FLOW_OK; + + gst_pad_set_chain_function (pad, _decoder_chain); +} + +static void +fake_decoder_class_init (FakeDecoderClass * self_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (self_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&fake_decoder_src_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&fake_decoder_sink_template)); + gst_element_class_set_static_metadata (gstelement_class, + "Fake Decoder", "Decoder", "Some decoder", "Thibault Saunier"); +} + +GType +fake_decoder_get_type (void) +{ + static volatile gsize type = 0; + + if (g_once_init_enter (&type)) { + GType _type; + static const GTypeInfo info = { + sizeof (FakeDecoderClass), + NULL, + NULL, + (GClassInitFunc) fake_decoder_class_init, + NULL, + NULL, + sizeof (FakeDecoder), + 0, + (GInstanceInitFunc) fake_decoder_init, + }; + + _type = g_type_register_static (GST_TYPE_ELEMENT, "FakeDecoder", &info, 0); + g_once_init_leave (&type, _type); + } + return type; +} + +GstElement * +fake_decoder_new (void) +{ + return GST_ELEMENT (g_object_new (FAKE_DECODER_TYPE, NULL)); +} diff --git a/validate/tests/check/validate/test-utils.h b/validate/tests/check/validate/test-utils.h index ac6a3a7db2..185404836b 100644 --- a/validate/tests/check/validate/test-utils.h +++ b/validate/tests/check/validate/test-utils.h @@ -54,6 +54,25 @@ typedef struct { GType fake_demuxer_get_type (void); GstElement * fake_demuxer_new (void); +typedef struct { + GstElement parent; + + GstFlowReturn return_value; +} FakeDecoder; + +typedef struct { + GstElementClass parent; +} FakeDecoderClass; + +#define FAKE_DECODER_TYPE (fake_decoder_get_type ()) +#define FAKE_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FAKE_DECODER_TYPE, FakeDecoder)) +#define FAKE_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FAKE_DECODER_TYPE, FakeDecoderClass)) +#define IS_FAKE_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FAKE_DECODER_TYPE)) +#define IS_FAKE_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FAKE_DECODER_TYPE)) +#define FAKE_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FAKE_DECODER_TYPE, FakeDecoderClass)) + +GType fake_decoder_get_type (void); +GstElement * fake_decoder_new (void); G_END_DECLS diff --git a/validate/tools/launcher/apps/gstvalidate.py b/validate/tools/launcher/apps/gstvalidate.py index ff8db20e7f..376d60c100 100644 --- a/validate/tools/launcher/apps/gstvalidate.py +++ b/validate/tools/launcher/apps/gstvalidate.py @@ -294,6 +294,8 @@ class GstValidateLaunchTest(GstValidateTest): def build_arguments(self): GstValidateTest.build_arguments(self) self.add_arguments(self.pipeline_desc) + if self.media_descriptor is not None: + self.add_arguments("--set-media-info", self.media_descriptor.get_path()) def get_current_value(self): if self.scenario: