+ * gst_segment_to_stream_time_full:
+ * @segment: a #GstSegment structure.
+ * @format: the format of the segment.
+ * @position: the position in the segment
+ * @stream_time: (out): result stream-time
+ *
+ * Translate @position to the total stream time using the currently configured
+ * segment. Compared to gst_segment_to_stream_time() this function can return
+ * negative stream-time.
+ *
+ * This function is typically used by elements that need to synchronize buffers
+ * against the clock or each other.
+ *
+ * @position can be any value and the result of this function for values outside
+ * of the segment is extrapolated.
+ *
+ * When 1 is returned, @position resulted in a positive stream-time returned
+ * in @stream_time.
+ *
+ * When this function returns -1, the returned @stream_time should be negated
+ * to get the real negative stream time.
+ *
+ * Returns: a 1 or -1 on success, 0 on failure.
+ *
+ * Since: 1.8
+ */
+gint
+gst_segment_to_stream_time_full (const GstSegment * segment, GstFormat format,
+ guint64 position, guint64 * stream_time)
+{
+ guint64 start, stop, time;
+ gdouble abs_applied_rate;
+ gint res;
+
+ /* format does not matter for -1 */
+ if (G_UNLIKELY (position == -1)) {
+ *stream_time = -1;
+ return 0;
+ }
+
+ g_return_val_if_fail (segment != NULL, 0);
+ g_return_val_if_fail (segment->format == format, 0);
+
+ stop = segment->stop;
+
+ start = segment->start;
+ time = segment->time;
+
+ /* time must be known */
+ if (G_UNLIKELY (time == -1))
+ return 0;
+
+ abs_applied_rate = ABS (segment->applied_rate);
+
+ /* add or subtract from segment time based on applied rate */
+ if (G_LIKELY (segment->applied_rate > 0.0)) {
+ if (G_LIKELY (position > start)) {
+ /* bring to uncorrected position in segment */
+ *stream_time = position - start;
+ /* correct for applied rate if needed */
+ if (G_UNLIKELY (abs_applied_rate != 1.0))
+ *stream_time *= abs_applied_rate;
+ /* correct for segment time */
+ *stream_time += time;
+ res = 1;
+ } else {
+ *stream_time = start - position;
+ if (G_UNLIKELY (abs_applied_rate != 1.0))
+ *stream_time *= abs_applied_rate;
+ if (*stream_time > time) {
+ *stream_time -= time;
+ res = -1;
+ } else {
+ *stream_time = time - *stream_time;
+ res = 1;
+ }
+ }
+ } else {
+ /* correct for segment time. Streams with a negative applied_rate
+ * have timestamps between start and stop, as usual, but have the
+ * time member starting high and going backwards. */
+ /* cannot continue without a known segment stop */
+ if (G_UNLIKELY (stop == -1))
+ return 0;
+ if (G_UNLIKELY (position > stop)) {
+ *stream_time = position - stop;
+ if (G_UNLIKELY (abs_applied_rate != 1.0))
+ *stream_time *= abs_applied_rate;
+ if (*stream_time > time) {
+ *stream_time -= time;
+ res = -1;
+ } else {
+ *stream_time = time - *stream_time;
+ res = 1;
+ }
+ } else {
+ *stream_time = stop - position;
+ if (G_UNLIKELY (abs_applied_rate != 1.0))
+ *stream_time *= abs_applied_rate;
+ *stream_time += time;
+ res = 1;
+ }
+ }
+
+ return res;
+}
+
+/**