segment: take offset into account in _to_position()
[platform/upstream/gstreamer.git] / gst / gstsegment.c
index 9890be5..590218e 100644 (file)
@@ -268,7 +268,7 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
   if (segment->duration != -1)
     start = MIN (start, segment->duration);
   else
-    start = MAX (start, 0);
+    start = MAX ((gint64) start, 0);
 
   /* stop can be -1 if we have not configured a stop. */
   switch (stop_type) {
@@ -292,17 +292,17 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
   /* if we have a valid stop time, make sure it is clipped */
   if (stop != -1) {
     if (segment->duration != -1)
-      stop = CLAMP (stop, 0, segment->duration);
+      stop = CLAMP ((gint64) stop, 0, (gint64) segment->duration);
     else
-      stop = MAX (stop, 0);
+      stop = MAX ((gint64) stop, 0);
   }
 
   /* we can't have stop before start */
   if (stop != -1) {
     if (start > stop) {
-      g_return_val_if_fail (start <= stop, FALSE);
       GST_WARNING ("segment update failed: start(%" G_GUINT64_FORMAT
           ") > stop(%" G_GUINT64_FORMAT ")", start, stop);
+      g_return_val_if_fail (start <= stop, FALSE);
       return FALSE;
     }
   }
@@ -311,6 +311,9 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
     /* flush resets the running_time */
     base = 0;
   } else {
+    /* make sure the position is inside the segment start/stop */
+    position = CLAMP (position, segment->start, segment->stop);
+
     /* remember the elapsed time */
     base = gst_segment_to_running_time (segment, format, position);
     GST_DEBUG ("updated segment.base: %" G_GUINT64_FORMAT, base);
@@ -457,7 +460,7 @@ gst_segment_to_stream_time (const GstSegment * segment, GstFormat format,
  * segment. Position is a value between @segment start and stop time.
  *
  * This function is typically used by elements that need to synchronize to the
- * global clock in a pipeline. The runnning time is a constantly increasing value
+ * global clock in a pipeline. The running time is a constantly increasing value
  * starting from 0. When gst_segment_init() is called, this value will reset to
  * 0.
  *
@@ -475,7 +478,7 @@ gst_segment_to_running_time (const GstSegment * segment, GstFormat format,
   gdouble abs_rate;
 
   if (G_UNLIKELY (position == -1)) {
-    GST_WARNING ("invalid position (-1)");
+    GST_DEBUG ("invalid position (-1)");
     return -1;
   }
 
@@ -489,7 +492,7 @@ gst_segment_to_running_time (const GstSegment * segment, GstFormat format,
 
   /* before the segment boundary */
   if (G_UNLIKELY (position < start)) {
-    GST_WARNING ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT
+    GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT
         ")", position, start);
     return -1;
   }
@@ -499,7 +502,7 @@ gst_segment_to_running_time (const GstSegment * segment, GstFormat format,
   if (G_LIKELY (segment->rate > 0.0)) {
     /* after of the segment boundary */
     if (G_UNLIKELY (stop != -1 && position > stop)) {
-      GST_WARNING ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
+      GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
           ")", position, stop);
       return -1;
     }
@@ -510,13 +513,13 @@ gst_segment_to_running_time (const GstSegment * segment, GstFormat format,
     /* cannot continue if no stop position set or outside of
      * the segment. */
     if (G_UNLIKELY (stop == -1)) {
-      GST_WARNING ("invalid stop (-1)");
+      GST_DEBUG ("invalid stop (-1)");
       return -1;
     }
 
     stop -= segment->offset;
     if (G_UNLIKELY (position > stop)) {
-      GST_WARNING ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
+      GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
           ")", position, stop);
       return -1;
     }
@@ -648,7 +651,7 @@ gst_segment_to_position (const GstSegment * segment, GstFormat format,
 
   if (G_LIKELY (segment->rate > 0.0)) {
     /* bring to corrected position in segment */
-    result += start;
+    result += start + segment->offset;
 
     /* outside of the segment boundary stop */
     if (G_UNLIKELY (stop != -1 && result > stop))
@@ -660,12 +663,11 @@ gst_segment_to_position (const GstSegment * segment, GstFormat format,
       return -1;
 
     /* bring to corrected position in segment */
-    result = stop - result;
+    result = stop - result - segment->offset;
   }
   return result;
 }
 
-
 /**
  * gst_segment_set_running_time:
  * @segment: a #GstSegment structure.
@@ -710,3 +712,51 @@ gst_segment_set_running_time (GstSegment * segment, GstFormat format,
 
   return TRUE;
 }
+
+/**
+ * gst_segment_offset_running_time:
+ * @segment: a #GstSegment structure.
+ * @format: the format of the segment.
+ * @offset: the offset to apply in the segment
+ *
+ * Adjust the values in @segment so that @offset is applied to all
+ * future running-time calculations.
+ *
+ * Since: 1.4
+ *
+ * Returns: %TRUE if the segment could be updated successfully. If %FALSE is
+ * returned, @offset is not in @segment.
+ */
+gboolean
+gst_segment_offset_running_time (GstSegment * segment, GstFormat format,
+    gint64 offset)
+{
+  g_return_val_if_fail (segment != NULL, FALSE);
+  g_return_val_if_fail (segment->format == format, FALSE);
+
+  if (offset == 0)
+    return TRUE;
+
+  if (offset > 0) {
+    /* positive offset, we can simply apply to the base time */
+    segment->base += offset;
+  } else {
+    offset = -offset;
+    /* negative offset, first try to subtract from base */
+    if (segment->base > offset) {
+      segment->base -= offset;
+    } else {
+      guint64 position;
+
+      /* subtract all from segment.base, remainder in offset */
+      offset -= segment->base;
+      segment->base = 0;
+      position = gst_segment_to_position (segment, format, offset);
+      if (position == -1)
+        return FALSE;
+
+      segment->offset = position;
+    }
+  }
+  return TRUE;
+}