#define JBUF_WAIT_TIMER(priv) G_STMT_START { \
GST_DEBUG ("waiting timer"); \
- (priv)->waiting_timer = TRUE; \
+ (priv)->waiting_timer++; \
g_cond_wait (&(priv)->jbuf_timer, &(priv)->jbuf_lock); \
- (priv)->waiting_timer = FALSE; \
+ (priv)->waiting_timer--; \
GST_DEBUG ("waiting timer done"); \
} G_STMT_END
#define JBUF_SIGNAL_TIMER(priv) G_STMT_START { \
if (G_UNLIKELY ((priv)->waiting_timer)) { \
- GST_DEBUG ("signal timer"); \
+ GST_DEBUG ("signal timer, %d waiters", (priv)->waiting_timer); \
g_cond_signal (&(priv)->jbuf_timer); \
} \
} G_STMT_END
GST_DEBUG_OBJECT (jitterbuffer, "removed index %d", idx);
g_array_remove_index_fast (priv->timers, idx);
timer->idx = idx;
+
+ JBUF_SIGNAL_TIMER (priv);
}
static void
GST_DEBUG_OBJECT (jitterbuffer, "removed all timers");
g_array_set_size (priv->timers, 0);
unschedule_current_timer (jitterbuffer);
+ JBUF_SIGNAL_TIMER (priv);
}
/* get the extra delay to wait before sending RTX */
priv->next_seqnum = (seqnum + item->count) & 0xffff;
}
msg = check_buffering_percent (jitterbuffer, percent);
+
+ if (type == ITEM_TYPE_EVENT && outevent &&
+ GST_EVENT_TYPE (outevent) == GST_EVENT_EOS) {
+ g_assert (priv->eos);
+ while (priv->timers->len > 0) {
+ /* Stopping timers */
+ unschedule_current_timer (jitterbuffer);
+ JBUF_WAIT_TIMER (priv);
+ }
+ }
+
JBUF_UNLOCK (priv);
item->data = NULL;
* otherwise always be 0
*/
GST_OBJECT_LOCK (jitterbuffer);
- if (GST_ELEMENT_CLOCK (jitterbuffer)) {
+ if (priv->eos) {
+ now = GST_CLOCK_TIME_NONE;
+ } else if (GST_ELEMENT_CLOCK (jitterbuffer)) {
now =
gst_clock_get_time (GST_ELEMENT_CLOCK (jitterbuffer)) -
GST_ELEMENT_CAST (jitterbuffer)->base_time;
GstClockReturn ret;
GstClockTimeDiff clock_jitter;
- if (timer_timeout == -1 || timer_timeout <= now) {
+ if (timer_timeout == -1 || timer_timeout <= now || priv->eos) {
/* We have normally removed all lost timers in the loop above */
g_assert (timer->type != TIMER_TYPE_LOST);
GST_END_TEST;
+gboolean is_eos;
+
+static gboolean
+eos_event_function (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+ if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
+ g_mutex_lock (&check_mutex);
+ is_eos = TRUE;
+ g_cond_signal (&check_cond);
+ g_mutex_unlock (&check_mutex);
+ }
+
+ return TRUE;
+}
+
+GST_START_TEST (test_push_eos)
+{
+ GstElement *jitterbuffer;
+ const guint num_buffers = 5;
+ GstBuffer *buffer;
+ GList *node;
+ GstStructure *stats;
+ guint64 pushed, lost, late, duplicates;
+ int n = 0;
+
+ is_eos = FALSE;
+
+ jitterbuffer = setup_jitterbuffer (num_buffers);
+ gst_pad_set_event_function (mysinkpad, eos_event_function);
+
+ g_object_set (jitterbuffer, "latency", 1, NULL);
+
+ fail_unless (start_jitterbuffer (jitterbuffer)
+ == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
+
+ /* push buffers: 0,1,2, */
+ for (node = inbuffers; node; node = g_list_next (node)) {
+ n++;
+ /* Skip 1 */
+ if (n == 2) {
+ continue;
+ }
+ buffer = (GstBuffer *) node->data;
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ }
+
+ gst_pad_push_event (mysrcpad, gst_event_new_eos ());
+
+ g_mutex_lock (&check_mutex);
+ while (!is_eos)
+ g_cond_wait (&check_cond, &check_mutex);
+ g_mutex_unlock (&check_mutex);
+
+ /* Verify statistics */
+ g_object_get (jitterbuffer, "stats", &stats, NULL);
+ gst_structure_get (stats, "num-pushed", G_TYPE_UINT64, &pushed,
+ "num-lost", G_TYPE_UINT64, &lost,
+ "num-late", G_TYPE_UINT64, &late,
+ "num-duplicates", G_TYPE_UINT64, &duplicates, NULL);
+ fail_unless_equals_int (pushed, g_list_length (inbuffers) - 1);
+ fail_unless_equals_int (lost, 1);
+ fail_unless_equals_int (late, 0);
+ fail_unless_equals_int (duplicates, 0);
+ gst_structure_free (stats);
+
+ /* cleanup */
+ cleanup_jitterbuffer (jitterbuffer);
+}
+
+GST_END_TEST;
+
GST_START_TEST (test_basetime)
{
GstElement *jitterbuffer;
tcase_add_test (tc_chain, test_push_forward_seq);
tcase_add_test (tc_chain, test_push_backward_seq);
tcase_add_test (tc_chain, test_push_unordered);
+ tcase_add_test (tc_chain, test_push_eos);
tcase_add_test (tc_chain, test_basetime);
tcase_add_test (tc_chain, test_clear_pt_map);