mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-23 07:38:16 +00:00
segment: add helper to get negative running-time
Add a helper method to get a running-time with a little more features such as detecting if the value was before or after the segment and negative running-time. API: gst_segment_to_running_time_full() Fixes https://bugzilla.gnome.org/show_bug.cgi?id=740575
This commit is contained in:
parent
6e67ad7675
commit
8c8b3818e4
4 changed files with 205 additions and 62 deletions
199
gst/gstsegment.c
199
gst/gstsegment.c
|
@ -452,6 +452,138 @@ gst_segment_to_stream_time (const GstSegment * segment, GstFormat format,
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_segment_to_running_time_full:
|
||||
* @segment: a #GstSegment structure.
|
||||
* @format: the format of the segment.
|
||||
* @position: the position in the segment
|
||||
* @running_time: result running-time
|
||||
*
|
||||
* Translate @position to the total running time using the currently configured
|
||||
* segment. Position is a value between @segment start and stop time. Compared to
|
||||
* gst_segment_to_running_time() this function can return negative running-time
|
||||
* and specify if the position was before or after the segment incase it is outside
|
||||
* of the segment.
|
||||
*
|
||||
* This function is typically used by elements that need to synchronize buffers
|
||||
* against the clock or eachother.
|
||||
*
|
||||
* When #GST_SEGMENT_RESULT_OK is returned, @position is between start and stop of
|
||||
* @segment and thus resulted in a positive running-time returned in @running_time.
|
||||
*
|
||||
* When @position is outside of the segment start and stop values,
|
||||
* #GST_SEGMENT_RESULT_BEFORE or #GST_SEGMENT_RESULT_AFTER is returned depending
|
||||
* if @position is respectively before or after the segment.
|
||||
*
|
||||
* When this function returns #GST_SEGMENT_RESULT_NEGATIVE, the returned
|
||||
* @running_time should be negated to get the real negative running time.
|
||||
*
|
||||
* Returns: a #GstSegmentResult
|
||||
*
|
||||
* Since: 1.6
|
||||
*/
|
||||
GstSegmentResult
|
||||
gst_segment_to_running_time_full (const GstSegment * segment, GstFormat format,
|
||||
guint64 position, guint64 * running_time)
|
||||
{
|
||||
GstSegmentResult res;
|
||||
guint64 result;
|
||||
guint64 start, stop, offset;
|
||||
gdouble abs_rate;
|
||||
|
||||
if (G_UNLIKELY (position == -1)) {
|
||||
GST_DEBUG ("invalid position (-1)");
|
||||
res = GST_SEGMENT_RESULT_INVALID;
|
||||
goto done;
|
||||
}
|
||||
|
||||
g_return_val_if_fail (segment != NULL, GST_SEGMENT_RESULT_INVALID);
|
||||
g_return_val_if_fail (segment->format == format, GST_SEGMENT_RESULT_INVALID);
|
||||
|
||||
start = segment->start;
|
||||
/* before the segment boundary */
|
||||
if (G_UNLIKELY (position < start)) {
|
||||
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT
|
||||
")", position, start);
|
||||
if (G_LIKELY (segment->rate > 0.0))
|
||||
res = GST_SEGMENT_RESULT_BEFORE;
|
||||
else
|
||||
res = GST_SEGMENT_RESULT_AFTER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
stop = segment->stop;
|
||||
/* after the segment boundary */
|
||||
if (G_UNLIKELY (stop != -1 && position > stop)) {
|
||||
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
|
||||
")", position, stop);
|
||||
if (G_LIKELY (segment->rate > 0.0))
|
||||
res = GST_SEGMENT_RESULT_AFTER;
|
||||
else
|
||||
res = GST_SEGMENT_RESULT_BEFORE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
offset = segment->offset;
|
||||
|
||||
if (G_LIKELY (segment->rate > 0.0)) {
|
||||
/* bring to uncorrected position in segment */
|
||||
if (position < start + offset) {
|
||||
/* negative value */
|
||||
result = (start + offset) - position;
|
||||
res = GST_SEGMENT_RESULT_NEGATIVE;
|
||||
} else {
|
||||
result = position - (start + offset);
|
||||
res = GST_SEGMENT_RESULT_OK;
|
||||
}
|
||||
} else {
|
||||
/* cannot continue if no stop position set or invalid offset */
|
||||
g_return_val_if_fail (stop != -1, GST_SEGMENT_RESULT_INVALID);
|
||||
g_return_val_if_fail (stop >= segment->offset, GST_SEGMENT_RESULT_INVALID);
|
||||
|
||||
/* bring to uncorrected position in segment */
|
||||
if (position > stop - offset) {
|
||||
/* negative value */
|
||||
result = position - (stop - offset);
|
||||
res = GST_SEGMENT_RESULT_NEGATIVE;
|
||||
} else {
|
||||
result = (stop - offset) - position;
|
||||
res = GST_SEGMENT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (running_time) {
|
||||
/* scale based on the rate, avoid division by and conversion to
|
||||
* float when not needed */
|
||||
abs_rate = ABS (segment->rate);
|
||||
if (G_UNLIKELY (abs_rate != 1.0))
|
||||
result /= abs_rate;
|
||||
|
||||
/* correct for base of the segment */
|
||||
if (res == GST_SEGMENT_RESULT_OK)
|
||||
/* positive, add base */
|
||||
*running_time = result + segment->base;
|
||||
else if (segment->base >= result) {
|
||||
/* negative and base is bigger, subtract from base and we have a
|
||||
* positive value again */
|
||||
*running_time = segment->base - result;
|
||||
res = GST_SEGMENT_RESULT_OK;
|
||||
} else {
|
||||
/* negative and base is smaller, subtract base and remainder is
|
||||
* negative */
|
||||
*running_time = result - segment->base;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
done:
|
||||
{
|
||||
if (running_time)
|
||||
*running_time = -1;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_segment_to_running_time:
|
||||
* @segment: a #GstSegment structure.
|
||||
|
@ -476,70 +608,13 @@ gst_segment_to_running_time (const GstSegment * segment, GstFormat format,
|
|||
guint64 position)
|
||||
{
|
||||
guint64 result;
|
||||
guint64 start, stop;
|
||||
gdouble abs_rate;
|
||||
GstSegmentResult res;
|
||||
|
||||
if (G_UNLIKELY (position == -1)) {
|
||||
GST_DEBUG ("invalid position (-1)");
|
||||
return -1;
|
||||
}
|
||||
res = gst_segment_to_running_time_full (segment, format, position, &result);
|
||||
if (res == GST_SEGMENT_RESULT_OK)
|
||||
return result;
|
||||
|
||||
g_return_val_if_fail (segment != NULL, -1);
|
||||
g_return_val_if_fail (segment->format == format, -1);
|
||||
|
||||
start = segment->start;
|
||||
|
||||
if (segment->rate > 0.0)
|
||||
start += segment->offset;
|
||||
|
||||
/* before the segment boundary */
|
||||
if (G_UNLIKELY (position < start)) {
|
||||
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT
|
||||
")", position, start);
|
||||
return -1;
|
||||
}
|
||||
|
||||
stop = segment->stop;
|
||||
|
||||
if (G_LIKELY (segment->rate > 0.0)) {
|
||||
/* after of the segment boundary */
|
||||
if (G_UNLIKELY (stop != -1 && position > stop)) {
|
||||
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
|
||||
")", position, stop);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* bring to uncorrected position in segment */
|
||||
result = position - start;
|
||||
} else {
|
||||
/* cannot continue if no stop position set or outside of
|
||||
* the segment. */
|
||||
if (G_UNLIKELY (stop == -1)) {
|
||||
GST_DEBUG ("invalid stop (-1)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
stop -= segment->offset;
|
||||
if (G_UNLIKELY (position > stop)) {
|
||||
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
|
||||
")", position, stop);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* bring to uncorrected position in segment */
|
||||
result = stop - position;
|
||||
}
|
||||
|
||||
/* scale based on the rate, avoid division by and conversion to
|
||||
* float when not needed */
|
||||
abs_rate = ABS (segment->rate);
|
||||
if (G_UNLIKELY (abs_rate != 1.0))
|
||||
result /= abs_rate;
|
||||
|
||||
/* correct for base of the segment */
|
||||
result += segment->base;
|
||||
|
||||
return result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -168,6 +168,27 @@ typedef enum { /*< flags >*/
|
|||
GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO = GST_SEEK_FLAG_TRICKMODE_NO_AUDIO
|
||||
} GstSegmentFlags;
|
||||
|
||||
/**
|
||||
* GstSegmentResult:
|
||||
* @GST_SEGMENT_RESULT_INVALID: input value is invalid and no output value can
|
||||
* be calculated.
|
||||
* @GST_SEGMENT_RESULT_OK: value is within the segment and positive.
|
||||
* @GST_SEGMENT_RESULT_NEGATIVE: value is within the segment but negative.
|
||||
* @GST_SEGMENT_RESULT_BEFORE: value is outside before the segment.
|
||||
* @GST_SEGMENT_RESULT_AFTER: value is outside after the segment.
|
||||
*
|
||||
* Possible return values from gst_segment_to_running_time_full().
|
||||
*
|
||||
* Since: 1.6
|
||||
*/
|
||||
typedef enum {
|
||||
GST_SEGMENT_RESULT_INVALID = 0,
|
||||
GST_SEGMENT_RESULT_OK = 1,
|
||||
GST_SEGMENT_RESULT_NEGATIVE = -1,
|
||||
GST_SEGMENT_RESULT_BEFORE = -2,
|
||||
GST_SEGMENT_RESULT_AFTER = -3
|
||||
} GstSegmentResult;
|
||||
|
||||
/**
|
||||
* GstSegment:
|
||||
* @flags: flags for this segment
|
||||
|
@ -217,6 +238,9 @@ void gst_segment_init (GstSegment *segment, GstFormat for
|
|||
|
||||
guint64 gst_segment_to_stream_time (const GstSegment *segment, GstFormat format, guint64 position);
|
||||
guint64 gst_segment_to_running_time (const GstSegment *segment, GstFormat format, guint64 position);
|
||||
GstSegmentResult
|
||||
gst_segment_to_running_time_full (const GstSegment *segment, GstFormat format, guint64 position,
|
||||
guint64 * running_time);
|
||||
guint64 gst_segment_to_position (const GstSegment *segment, GstFormat format, guint64 running_time);
|
||||
|
||||
gboolean gst_segment_set_running_time (GstSegment *segment, GstFormat format, guint64 running_time);
|
||||
|
|
|
@ -30,6 +30,8 @@ check_times (GstSegment * segment, guint64 position, guint64 stream_time,
|
|||
|
||||
st = gst_segment_to_stream_time (segment, segment->format, position);
|
||||
rt = gst_segment_to_running_time (segment, segment->format, position);
|
||||
GST_DEBUG ("position %" G_GUINT64_FORMAT ", st %" G_GUINT64_FORMAT ", rt %"
|
||||
G_GUINT64_FORMAT, position, stream_time, running_time);
|
||||
|
||||
fail_unless_equals_int64 (st, stream_time);
|
||||
fail_unless_equals_int64 (rt, running_time);
|
||||
|
@ -744,6 +746,45 @@ GST_START_TEST (segment_offset)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (segment_full)
|
||||
{
|
||||
GstSegment segment;
|
||||
guint64 rt;
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
|
||||
segment.start = 50;
|
||||
segment.position = 150;
|
||||
segment.stop = 200;
|
||||
segment.time = 0;
|
||||
|
||||
check_times (&segment, 100, 50, 50);
|
||||
check_times (&segment, 220, -1, -1);
|
||||
|
||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
||||
50, &rt) == GST_SEGMENT_RESULT_OK);
|
||||
fail_unless (rt == 0);
|
||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
||||
200, &rt) == GST_SEGMENT_RESULT_OK);
|
||||
fail_unless (rt == 150);
|
||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
||||
40, &rt) == GST_SEGMENT_RESULT_BEFORE);
|
||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
||||
49, &rt) == GST_SEGMENT_RESULT_BEFORE);
|
||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
||||
201, &rt) == GST_SEGMENT_RESULT_AFTER);
|
||||
|
||||
fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
|
||||
-50) == TRUE);
|
||||
fail_unless (segment.offset == 50);
|
||||
|
||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
||||
50, &rt) == GST_SEGMENT_RESULT_NEGATIVE);
|
||||
GST_DEBUG ("%" G_GUINT64_FORMAT, rt);
|
||||
fail_unless (rt == 50);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
gst_segment_suite (void)
|
||||
|
@ -761,6 +802,7 @@ gst_segment_suite (void)
|
|||
tcase_add_test (tc_chain, segment_copy);
|
||||
tcase_add_test (tc_chain, segment_seek_noupdate);
|
||||
tcase_add_test (tc_chain, segment_offset);
|
||||
tcase_add_test (tc_chain, segment_full);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -1124,9 +1124,11 @@ EXPORTS
|
|||
gst_segment_init
|
||||
gst_segment_new
|
||||
gst_segment_offset_running_time
|
||||
gst_segment_result_get_type
|
||||
gst_segment_set_running_time
|
||||
gst_segment_to_position
|
||||
gst_segment_to_running_time
|
||||
gst_segment_to_running_time_full
|
||||
gst_segment_to_stream_time
|
||||
gst_segtrap_is_enabled
|
||||
gst_segtrap_set_enabled
|
||||
|
|
Loading…
Reference in a new issue