Allows writing tests that verify that events are correct.
Useful to monitor and check segments after seeks, for example.
return TRUE;
}
+static void
+testSeekAdaptiveAppSinkEvent (GstAdaptiveDemuxTestEngine * engine,
+ GstAdaptiveDemuxTestOutputStream * stream,
+ GstEvent * event, gpointer user_data)
+{
+ GstAdaptiveDemuxTestCase *testData = GST_ADAPTIVE_DEMUX_TEST_CASE (user_data);
+ GstAdaptiveDemuxTestExpectedOutput *testOutputStreamData;
+ guint index = 0;
+
+ testOutputStreamData =
+ gst_adaptive_demux_test_find_test_data_by_stream (testData, stream,
+ &index);
+ fail_unless (testOutputStreamData != NULL);
+
+ if (testData->seek_event && GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT
+ && testOutputStreamData->post_seek_segment.format != GST_FORMAT_UNDEFINED
+ && gst_event_get_seqnum (event) ==
+ gst_event_get_seqnum (testData->seek_event)) {
+ const GstSegment *seek_segment;
+
+ gst_event_parse_segment (event, &seek_segment);
+ fail_unless (seek_segment->format ==
+ testOutputStreamData->post_seek_segment.format);
+ fail_unless (seek_segment->rate ==
+ testOutputStreamData->post_seek_segment.rate);
+ fail_unless (seek_segment->start ==
+ testOutputStreamData->post_seek_segment.start);
+ fail_unless (seek_segment->stop ==
+ testOutputStreamData->post_seek_segment.stop);
+ fail_unless (seek_segment->base ==
+ testOutputStreamData->post_seek_segment.base);
+ fail_unless (seek_segment->time ==
+ testOutputStreamData->post_seek_segment.time);
+
+ testOutputStreamData->segment_verification_needed = FALSE;
+ }
+}
+
/* callback called when main_loop detects a state changed event */
static void
testSeekOnStateChanged (GstBus * bus, GstMessage * msg, gpointer user_data)
G_CALLBACK (testSeekOnStateChanged), testData);
}
+static void
+testSeekPostTestCallback (GstAdaptiveDemuxTestEngine * engine,
+ gpointer user_data)
+{
+ GstAdaptiveDemuxTestCase *testData = GST_ADAPTIVE_DEMUX_TEST_CASE (user_data);
+ for (GList * walk = testData->output_streams; walk; walk = g_list_next (walk)) {
+ GstAdaptiveDemuxTestExpectedOutput *td = walk->data;
+
+ fail_if (td->segment_verification_needed);
+ }
+}
+
/* function to check total size of data received by AppSink
* will be called when AppSink receives eos.
*/
GstAdaptiveDemuxTestCallbacks cb = { 0 };
cb.appsink_received_data = gst_adaptive_demux_test_check_received_data;
cb.appsink_eos = gst_adaptive_demux_test_check_size_of_received_data;
+ cb.appsink_event = testSeekAdaptiveAppSinkEvent;
cb.pre_test = testSeekPreTestCallback;
+ cb.post_test = testSeekPostTestCallback;
cb.demux_sent_data = testSeekAdaptiveDemuxSendsData;
gst_adaptive_demux_test_run (element_name, manifest_uri, &cb, testData);
/* the call to g_object_unref of testData will clean up the seek task */
guint64 expected_size;
/* the expected data on this stream (optional) */
const guint8* expected_data;
+
+ GstSegment post_seek_segment;
+ gboolean segment_verification_needed;
} GstAdaptiveDemuxTestExpectedOutput;
typedef struct _GstAdaptiveDemuxTestCaseClass GstAdaptiveDemuxTestCaseClass;
GCond test_task_state_cond;
/* seek test will wait for this amount of bytes to be sent by
- * demux to AppSink before triggering a seek request
+ * demux to AppSink before triggering a seek request
*/
guint64 threshold_for_seek;
GstEvent *seek_event;
GST_TEST_UNLOCK (priv);
}
+static GstPadProbeReturn
+on_appsink_event (GstPad * pad, GstPadProbeInfo * info, gpointer data)
+{
+ GstAdaptiveDemuxTestEnginePrivate *priv =
+ (GstAdaptiveDemuxTestEnginePrivate *) data;
+ GstAdaptiveDemuxTestOutputStream *stream = NULL;
+ GstEvent *event;
+
+ event = GST_PAD_PROBE_INFO_EVENT (info);
+ GST_DEBUG ("Received event %" GST_PTR_FORMAT " on pad %" GST_PTR_FORMAT,
+ event, pad);
+
+ if (priv->callbacks->appsink_event) {
+ GST_TEST_LOCK (priv);
+ stream = getTestOutputDataByPad (priv, pad, TRUE);
+ GST_TEST_UNLOCK (priv);
+ priv->callbacks->appsink_event (&priv->engine, stream, event,
+ priv->user_data);
+ }
+
+ return GST_PAD_PROBE_OK;
+}
+
+
/* callback called when demux sends data to AppSink */
static GstPadProbeReturn
on_demux_sent_data (GstPad * pad, GstPadProbeInfo * info, gpointer data)
GST_TEST_LOCK (priv);
stream = getTestOutputDataByPad (priv, pad, TRUE);
+ GST_TEST_UNLOCK (priv);
if (priv->callbacks->demux_sent_data) {
(*priv->callbacks->demux_sent_data) (&priv->engine,
stream, buffer, priv->user_data);
}
- GST_TEST_UNLOCK (priv);
return GST_PAD_PROBE_OK;
}
GstElement *sink;
gboolean ret;
gchar *name;
- GstPad *internal_pad;
+ GstPad *internal_pad, *appsink_pad;
GstAppSinkCallbacks appSinkCallbacks;
GstAdaptiveDemuxTestOutputStream *stream;
GObjectClass *gobject_class;
gst_app_sink_set_callbacks (GST_APP_SINK (sink), &appSinkCallbacks, priv,
NULL);
+ appsink_pad = gst_element_get_static_pad (sink, "sink");
+ gst_pad_add_probe (pad,
+ GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_FLUSH,
+ (GstPadProbeCallback) on_appsink_event, priv, NULL);
+ gst_object_unref (appsink_pad);
+
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
(GstPadProbeCallback) on_demux_sent_data, priv, NULL);
GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data);
/**
+ * appsink_event: called when an event is received by appsink
+ * @engine: #GstAdaptiveDemuxTestEngine
+ * @stream: #GstAdaptiveDemuxTestOutputStream
+ * @event: the #GstEvent that was pushed in the demuxer pad
+ * @user_data: the user_data passed to gst_adaptive_demux_test_run()
+ *
+ * Can be used by a test to do some checks on the events
+ */
+ void (*appsink_event) (GstAdaptiveDemuxTestEngine *engine,
+ GstAdaptiveDemuxTestOutputStream * stream,
+ GstEvent * event, gpointer user_data);
+
+ /**
* demux_pad_added: called each time the demux creates a new pad
* @engine: #GstAdaptiveDemuxTestEngine
* @stream: the #GstAdaptiveDemuxTestOutputStream that has been created