queue: apply sink segment on the source if queue is empty
authorOgnyan Tonchev <ognyan@axis.com>
Mon, 11 Oct 2010 08:27:52 +0000 (10:27 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 11 Oct 2010 13:56:31 +0000 (15:56 +0200)
Apply the sink segment on the source immediatly when it is received
and there is nothing in the queue.

Solves #482147

plugins/elements/gstqueue.c
plugins/elements/gstqueue.h
tests/check/elements/queue.c

index 6bf1c48..72c8e0b 100644 (file)
@@ -430,6 +430,8 @@ gst_queue_init (GstQueue * queue, GstQueueClass * g_class)
   queue->sink_tainted = TRUE;
   queue->src_tainted = TRUE;
 
+  queue->newseg_applied_to_src = FALSE;
+
   GST_DEBUG_OBJECT (queue,
       "initialized queue's not_empty & not_full conditions");
 }
@@ -680,15 +682,6 @@ gst_queue_locked_enqueue_buffer (GstQueue * queue, gpointer item)
   queue->cur_level.bytes += GST_BUFFER_SIZE (buffer);
   apply_buffer (queue, buffer, &queue->sink_segment, TRUE, TRUE);
 
-  /* if this is the first buffer update the end side as well, but without the
-   * duration. */
-  /* FIXME : This will only be useful for current time level if the
-   * source task is running, which is not the case for ex in
-   * gstplaybasebin when pre-rolling.
-   * See #482147 */
-  /*     if (queue->cur_level.buffers == 1) */
-  /*       apply_buffer (queue, buffer, &queue->src_segment, FALSE); */
-
   g_queue_push_tail (queue->queue, item);
   GST_QUEUE_SIGNAL_ADD (queue);
 }
@@ -709,6 +702,11 @@ gst_queue_locked_enqueue_event (GstQueue * queue, gpointer item)
       break;
     case GST_EVENT_NEWSEGMENT:
       apply_segment (queue, event, &queue->sink_segment, TRUE);
+      /* if the queue is empty, apply sink segment on the source */
+      if (queue->queue->length == 0) {
+        apply_segment (queue, event, &queue->src_segment, FALSE);
+        queue->newseg_applied_to_src = TRUE;
+      }
       /* a new segment allows us to accept more buffers if we got UNEXPECTED
        * from downstream */
       queue->unexpected = FALSE;
@@ -758,7 +756,12 @@ gst_queue_locked_dequeue (GstQueue * queue, gboolean * is_buffer)
         GST_QUEUE_CLEAR_LEVEL (queue->cur_level);
         break;
       case GST_EVENT_NEWSEGMENT:
-        apply_segment (queue, event, &queue->src_segment, FALSE);
+        /* apply newsegment if it has not already been applied */
+        if (G_LIKELY (!queue->newseg_applied_to_src)) {
+          apply_segment (queue, event, &queue->src_segment, FALSE);
+        } else {
+          queue->newseg_applied_to_src = FALSE;
+        }
         break;
       default:
         break;
index 203b508..72ea814 100644 (file)
@@ -115,6 +115,9 @@ struct _GstQueue {
   gboolean push_newsegment;
   
   gboolean silent;      /* don't emit signals */ 
+
+  /* whether the first new segment has been applied to src */
+  gboolean newseg_applied_to_src;
 };
 
 struct _GstQueueClass {
index 699382e..3a6e4e4 100644 (file)
@@ -537,6 +537,38 @@ GST_START_TEST (test_time_level)
 
 GST_END_TEST;
 
+GST_START_TEST (test_time_level_task_not_started)
+{
+  GstEvent *event;
+  GstClockTime time;
+
+  GST_DEBUG ("starting");
+
+  fail_unless (gst_element_set_state (queue,
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+      "could not set to playing");
+
+  event = gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME,
+      1 * GST_SECOND, 5 * GST_SECOND, 0);
+  gst_pad_push_event (mysrcpad, event);
+
+  g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
+  fail_if (time != 0 * GST_SECOND);
+
+  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+      1 * GST_SECOND, 5 * GST_SECOND, 0);
+  gst_pad_push_event (mysrcpad, event);
+
+  g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
+  fail_if (time != 4 * GST_SECOND);
+
+  GST_DEBUG ("stopping");
+  fail_unless (gst_element_set_state (queue,
+          GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
+}
+
+GST_END_TEST;
+
 static gboolean
 event_equals_newsegment (GstEvent * event, gboolean update, gdouble rate,
     GstFormat format, gint64 start, gint64 stop, gint64 position)
@@ -674,6 +706,7 @@ queue_suite (void)
   tcase_add_test (tc_chain, test_leaky_upstream);
   tcase_add_test (tc_chain, test_leaky_downstream);
   tcase_add_test (tc_chain, test_time_level);
+  tcase_add_test (tc_chain, test_time_level_task_not_started);
   tcase_add_test (tc_chain, test_newsegment);
 
   return s;