GST_END_TEST;
+static gint current_rate = 0;
+
+static gboolean
+live_switch_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_ACCEPT_CAPS:{
+ GstCaps *acceptable_caps;
+ GstCaps *caps;
+
+ acceptable_caps = gst_pad_get_current_caps (mysrcpad);
+ acceptable_caps = gst_caps_make_writable (acceptable_caps);
+ gst_caps_set_simple (acceptable_caps, "rate", G_TYPE_INT, current_rate,
+ NULL);
+
+ gst_query_parse_accept_caps (query, &caps);
+
+ gst_query_set_accept_caps_result (query, gst_caps_can_intersect (caps,
+ acceptable_caps));
+
+ gst_caps_unref (acceptable_caps);
+
+ return TRUE;
+ }
+ case GST_QUERY_CAPS:{
+ GstCaps *acceptable_caps;
+ GstCaps *filter;
+ GstCaps *caps;
+
+ acceptable_caps = gst_pad_get_current_caps (mysrcpad);
+ acceptable_caps = gst_caps_make_writable (acceptable_caps);
+ gst_caps_set_simple (acceptable_caps, "rate", G_TYPE_INT, current_rate,
+ NULL);
+
+ gst_query_parse_caps (query, &filter);
+
+ if (filter)
+ caps =
+ gst_caps_intersect_full (filter, acceptable_caps,
+ GST_CAPS_INTERSECT_FIRST);
+ else
+ caps = gst_caps_ref (acceptable_caps);
+
+ gst_query_set_caps_result (query, caps);
+
+ gst_caps_unref (caps);
+ gst_caps_unref (acceptable_caps);
+
+ return TRUE;
+ }
+ default:
+ return gst_pad_query_default (pad, parent, query);
+ }
+}
+
+static void
+live_switch_push_downstream (gint pts, gint rate)
+{
+ GstBuffer *inbuffer;
+
+ current_rate = rate;
+ gst_pad_push_event (mysinkpad, gst_event_new_reconfigure ());
+
+ inbuffer = gst_buffer_new_and_alloc (48000 * 4 * 2);
+ gst_buffer_memset (inbuffer, 0, 0, 48000 * 4 * 2);
+
+ GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
+ GST_BUFFER_TIMESTAMP (inbuffer) = pts * GST_SECOND;
+ GST_BUFFER_OFFSET (inbuffer) = 0;
+ GST_BUFFER_OFFSET_END (inbuffer) = 47999;
+
+ /* pushing gives away my reference ... */
+ fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
+
+ /* ... but it ends up being collected on the global buffer list */
+}
+
+GST_START_TEST (test_live_switch_downstream)
+{
+ GstElement *audioresample;
+ GstEvent *newseg;
+ GstCaps *caps;
+ GstSegment segment;
+ GList *l;
+ guint i;
+
+ audioresample =
+ setup_audioresample (4, 0xf, 48000, 48000, GST_AUDIO_NE (S16));
+
+ gst_pad_set_query_function (mysinkpad, live_switch_sink_query);
+
+ caps = gst_pad_get_current_caps (mysrcpad);
+ fail_unless (gst_caps_is_fixed (caps));
+
+ fail_unless (gst_element_set_state (audioresample,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ newseg = gst_event_new_segment (&segment);
+ fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
+
+ /* buffer is directly passed through */
+ live_switch_push_downstream (0, 48000);
+ fail_unless_equals_int (g_list_length (buffers), 1);
+
+ /* Reconfigure downstream to 40000 Hz */
+ live_switch_push_downstream (1, 40000);
+
+ /* one additional buffer is provided with the new sample rate */
+ fail_unless_equals_int (g_list_length (buffers), 2);
+
+ /* Reconfigure downstream to 50000 Hz */
+ live_switch_push_downstream (2, 50000);
+
+ /* two additional buffers are provided. One is the drained remainder of
+ * the previous sample rate, the second is the buffer with the new sample
+ * rate */
+ fail_unless_equals_int (g_list_length (buffers), 4);
+
+ /* Send EOS to drain the remaining samples */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
+ fail_unless_equals_int (g_list_length (buffers), 5);
+
+ /* Now test that each buffer has the expected samples. We simply check this
+ * by checking whether the timestamps, durations and sizes are matching */
+ for (l = buffers, i = 0; l; l = l->next, i++) {
+ GstBuffer *buffer = GST_BUFFER (l->data);
+
+ switch (i) {
+ case 0:
+ fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 0 * GST_SECOND);
+ fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer),
+ 1 * GST_SECOND);
+ fail_unless_equals_int (gst_buffer_get_size (buffer), 48000 * 4 * 2);
+ break;
+ case 1:
+ fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 1 * GST_SECOND);
+ fail_unless_equals_int (gst_buffer_get_size (buffer), 39966 * 4 * 2);
+ break;
+ case 2:
+ fail_unless (G_APPROX_VALUE (GST_BUFFER_PTS (buffer) +
+ GST_BUFFER_DURATION (buffer), 2 * GST_SECOND,
+ GST_SECOND / 40000 + 1));
+ fail_unless_equals_int (gst_buffer_get_size (buffer), 34 * 4 * 2);
+ break;
+ case 3:
+ fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 2 * GST_SECOND);
+ fail_unless_equals_int (gst_buffer_get_size (buffer), 49966 * 4 * 2);
+ break;
+ case 4:
+ fail_unless (G_APPROX_VALUE (GST_BUFFER_PTS (buffer) +
+ GST_BUFFER_DURATION (buffer), 3 * GST_SECOND,
+ GST_SECOND / 50000 + 1));
+ fail_unless_equals_int (gst_buffer_get_size (buffer), 33 * 4 * 2);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ gst_buffer_unref (buffer);
+ }
+
+ g_list_free (buffers);
+ buffers = NULL;
+
+ cleanup_audioresample (audioresample);
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
#ifndef GST_DISABLE_PARSE
static GMainLoop *loop;
tcase_add_test (tc_chain, test_reuse);
tcase_add_test (tc_chain, test_shutdown);
tcase_add_test (tc_chain, test_live_switch);
+ tcase_add_test (tc_chain, test_live_switch_downstream);
tcase_add_test (tc_chain, test_timestamp_drift);
tcase_add_test (tc_chain, test_fft);