+2005-11-21 Wim Taymans <wim@fluendo.com>
+
+ * check/gst/gstsegment.c: (GST_START_TEST):
+ * docs/design/part-TODO.txt:
+ * gst/base/gstbasesink.c: (gst_base_sink_handle_object),
+ (gst_base_sink_event), (gst_base_sink_do_sync),
+ (gst_base_sink_activate_pull), (gst_base_sink_get_position),
+ (gst_base_sink_query), (gst_base_sink_change_state):
+ * gst/base/gstbasesink.h:
+ * gst/base/gstbasesrc.c: (gst_base_src_init), (gst_base_src_query),
+ (gst_base_src_default_newsegment),
+ (gst_base_src_configure_segment), (gst_base_src_do_seek),
+ (gst_base_src_get_range), (gst_base_src_loop),
+ (gst_base_src_change_state):
+ * gst/base/gstbasesrc.h:
+ * gst/base/gstbasetransform.c:
+ (gst_base_transform_prepare_output_buf),
+ (gst_base_transform_event), (gst_base_transform_change_state):
+ * gst/base/gstbasetransform.h:
+ * gst/base/gstcollectpads.c: (gst_collect_pads_add_pad),
+ (gst_collect_pads_event):
+ * gst/base/gstcollectpads.h:
+ * gst/elements/gstfakesrc.c: (gst_fake_src_init),
+ (gst_fake_src_create):
+ * gst/elements/gstfakesrc.h:
+ * gst/elements/gstidentity.c: (gst_identity_transform_ip):
+ * gst/gstsegment.c: (gst_segment_init), (gst_segment_set_duration),
+ (gst_segment_set_last_stop), (gst_segment_set_seek),
+ (gst_segment_set_newsegment), (gst_segment_to_stream_time),
+ (gst_segment_to_running_time), (gst_segment_clip):
+ * gst/gstsegment.h:
+ More segment updates, replace code in plugins with segment
+ helper functions.
+
2005-11-21 Jan Schmidt <thaytan@mad.scientist.com>
* gst/elements/gstfdsrc.c: (gst_fdsrc_uri_set_uri):
GstSegment segment;
gboolean res;
gint64 cstart, cstop;
+ gboolean update;
gst_segment_init (&segment, GST_FORMAT_BYTES);
/* configure segment to start 100 */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == -1);
* size is unknown. */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == -1);
/* add 100 to start, set stop to 300 */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
fail_unless (segment.start == 200);
fail_unless (segment.stop == 300);
* nothing should be updated in the segment. */
ASSERT_CRITICAL (gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200));
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update));
fail_unless (segment.start == 200);
fail_unless (segment.stop == 300);
* unknown. */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update);
fail_unless (segment.start == 200);
fail_unless (segment.stop == 300);
GstSegment segment;
gboolean res;
gint64 cstart, cstop;
+ gboolean update;
gst_segment_init (&segment, GST_FORMAT_BYTES);
gst_segment_set_duration (&segment, GST_FORMAT_BYTES, 200);
/* configure segment to start 100 */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == -1);
* since we did not set it before. */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == -1);
/* add 100 to start, set stop to 300, stop clips to 200 */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
fail_unless (segment.start == 200);
fail_unless (segment.stop == 200);
* to duration */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update);
fail_unless (segment.start == 200);
fail_unless (segment.stop == 200);
/* seek relative to end */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == 180);
- unblocking while seeking. gst_element_flush_pads (GstElement, gboolean);
-- make GstCapsFlags instead of the #define for GST_CAPS_FLAGS_ANY.
-
- query POSITION/DURATION return accuracy. Just a flag or accuracy percentage.
- add some sort of time/frame stepping functionality, either with a flag on the seek
N frames/time, sending more complicated queries upstream which can ideally handle
those cases more efficiently too.
-- GstClockFlags should use the gstobject flags field instead of inventing its own.
-
-- Add gstsegment.[ch].
-
IMPLEMENTATION
--------------
gboolean update;
gdouble rate;
GstFormat format;
- gint64 segment_start;
- gint64 segment_stop;
- gint64 segment_time;
- GstClockTime duration;
+ gint64 start;
+ gint64 stop;
+ gint64 time;
/* the newsegment event is needed to bring the buffer timestamps to the
* stream time and to drop samples outside of the playback segment. */
gst_event_parse_newsegment (event, &update, &rate, &format,
- &segment_start, &segment_stop, &segment_time);
+ &start, &stop, &time);
basesink->have_newsegment = TRUE;
- /* any other format with 0 also gives time 0, the other values are
- * invalid as time though. */
- if (format != GST_FORMAT_TIME && segment_start == 0) {
- GST_DEBUG_OBJECT (basesink,
- "non-time newsegment with start 0, coaxing into FORMAT_TIME");
- format = GST_FORMAT_TIME;
- if (segment_stop != 0)
- segment_stop = -1;
- if (segment_time != 0)
- segment_time = -1;
- }
-
- if (format != GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (basesink,
- "received non time %d NEW_SEGMENT %" G_GINT64_FORMAT
- " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT,
- format, segment_start, segment_stop, segment_time);
-
- /* this means this sink will not be able to clip or drop samples
- * and timestamps have to start from 0. */
- basesink->segment_start = -1;
- basesink->segment_stop = -1;
- basesink->segment_time = -1;
- goto done_newsegment;
- }
- /* check if we really have a new segment or the previous one is
- * closed */
- if (!update) {
- /* the new segment has to be aligned with the old segment.
- * We first update the accumulated time of the previous
- * segment. the accumulated time is used when syncing to the
- * clock. A flush event sets the accumulated time back to 0
- */
- if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
- duration = basesink->segment_stop - basesink->segment_start;
- } else if (GST_CLOCK_TIME_IS_VALID (basesink->current_end)) {
- /* else use last seen timestamp as segment stop */
- duration = basesink->current_end - basesink->segment_start;
- } else {
- duration = 0;
- }
- } else {
- duration = segment_start - basesink->segment_start;
- }
-
- /* use previous rate to calculate duration */
- basesink->segment_accum += gst_gdouble_to_guint64 (
- (gst_guint64_to_gdouble (duration) / ABS (basesink->segment_rate)));
- /* then update the current segment */
- basesink->segment_rate = rate;
- basesink->segment_start = segment_start;
- basesink->segment_stop = segment_stop;
- basesink->segment_time = segment_time;
+ gst_segment_set_newsegment (&basesink->segment, update, rate, format,
+ start, stop, time);
GST_DEBUG_OBJECT (basesink,
"received NEWSEGMENT %" GST_TIME_FORMAT " -- %"
GST_TIME_FORMAT ", time %" GST_TIME_FORMAT ", accum %"
GST_TIME_FORMAT,
- GST_TIME_ARGS (basesink->segment_start),
- GST_TIME_ARGS (basesink->segment_stop),
- GST_TIME_ARGS (basesink->segment_time),
- GST_TIME_ARGS (basesink->segment_accum));
- done_newsegment:
+ GST_TIME_ARGS (basesink->segment.start),
+ GST_TIME_ARGS (basesink->segment.stop),
+ GST_TIME_ARGS (basesink->segment.time),
+ GST_TIME_ARGS (basesink->segment.accum));
break;
}
default:
("Received buffer without a new-segment. Cannot sync to clock."));
basesink->have_newsegment = TRUE;
/* this means this sink will not be able to sync to the clock */
- basesink->segment_start = -1;
- basesink->segment_stop = -1;
+ basesink->segment.start = -1;
+ basesink->segment.stop = -1;
}
/* check if the buffer needs to be dropped */
", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
GST_TIME_ARGS (end));
- /* need to drop if the timestamp is not between segment_start and
- * segment_stop. we check if the complete sample is outside of the
- * range since the sink might be able to clip the sample. */
- if (GST_CLOCK_TIME_IS_VALID (end) &&
- GST_CLOCK_TIME_IS_VALID (basesink->segment_start)) {
- if (end <= basesink->segment_start) {
- GST_DEBUG_OBJECT (basesink,
- "buffer end %" GST_TIME_FORMAT " <= segment start %"
- GST_TIME_FORMAT ", dropping buffer", GST_TIME_ARGS (end),
- GST_TIME_ARGS (basesink->segment_start));
+ if (GST_CLOCK_TIME_IS_VALID (start)) {
+ if (!gst_segment_clip (&basesink->segment, GST_FORMAT_TIME,
+ (gint64) start, (gint64) end, NULL, NULL))
goto dropping;
- }
- }
- if (GST_CLOCK_TIME_IS_VALID (start) &&
- GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
- if (basesink->segment_stop <= start) {
- GST_DEBUG_OBJECT (basesink,
- "buffer start %" GST_TIME_FORMAT " >= segment stop %"
- GST_TIME_FORMAT ", dropping buffer", GST_TIME_ARGS (start),
- GST_TIME_ARGS (basesink->segment_stop));
- goto dropping;
- }
}
}
basesink->preroll_queued++;
basesink->flushing = FALSE;
GST_OBJECT_UNLOCK (basesink);
/* we need new segment info after the flush. */
- basesink->segment_start = -1;
- basesink->segment_stop = -1;
- basesink->current_start = -1;
- basesink->current_end = -1;
- GST_DEBUG_OBJECT (basesink, "reset accum %" GST_TIME_FORMAT,
- GST_TIME_ARGS (basesink->segment_accum));
- basesink->segment_accum = 0;
+ gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
GST_STREAM_UNLOCK (pad);
GST_DEBUG_OBJECT (basesink, "event unref %p %p", basesink, event);
{
GstClockReturn result = GST_CLOCK_OK;
GstClockTime start, end;
- GstClockTimeDiff stream_start, stream_end;
+ gint64 cstart, cend;
GstBaseSinkClass *bclass;
- gboolean start_valid, end_valid;
bclass = GST_BASE_SINK_GET_CLASS (basesink);
if (bclass->get_times)
bclass->get_times (basesink, buffer, &start, &end);
- start_valid = GST_CLOCK_TIME_IS_VALID (start);
- end_valid = GST_CLOCK_TIME_IS_VALID (end);
-
GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT
", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end));
/* if we don't have a timestamp, we don't sync */
- if (!start_valid) {
+ if (!GST_CLOCK_TIME_IS_VALID (start)) {
GST_DEBUG_OBJECT (basesink, "start not valid");
goto done;
}
/* save last times seen. */
- basesink->current_start = start;
- if (end_valid)
- basesink->current_end = end;
+ if (GST_CLOCK_TIME_IS_VALID (end))
+ gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_TIME,
+ (gint64) end);
else
- basesink->current_end = start;
+ gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_TIME,
+ (gint64) start);
- if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
- /* check if not outside of the segment range, start is
- * always valid here. */
- if (start > basesink->segment_stop)
- goto out_of_segment;
- }
-
- /* bring timestamp to stream time using last segment offset. */
- if (GST_CLOCK_TIME_IS_VALID (basesink->segment_start)) {
- /* check if not outside of the segment range */
- if (end_valid && end < basesink->segment_start)
- goto out_of_segment;
-
- stream_start = (gint64) start - basesink->segment_start;
- stream_end = (gint64) end - basesink->segment_start;
-
- if (stream_start < 0) {
- GST_DEBUG_OBJECT (basesink, "stream_start negative, invalid");
- goto done;
- }
- } else {
- stream_start = (gint64) start;
- stream_end = (gint64) end;
- }
-
-
- /* correct for rate */
- if (basesink->segment_rate != 0.0) {
- stream_start /= ABS (basesink->segment_rate);
- if (end_valid)
- stream_end /= ABS (basesink->segment_rate);
- }
-
- stream_start += basesink->segment_accum;
- if (end_valid)
- stream_end += basesink->segment_accum;
+ /* clip */
+ if (!gst_segment_clip (&basesink->segment, GST_FORMAT_TIME,
+ (gint64) start, (gint64) end, &cstart, &cend))
+ goto out_of_segment;
if (!basesink->sync) {
GST_DEBUG_OBJECT (basesink, "no need to sync");
/* now do clocking */
if (basesink->clock) {
GstClockTime base_time;
+ GstClockTimeDiff stream_start, stream_end;
+
+ stream_start =
+ gst_segment_to_running_time (&basesink->segment, GST_FORMAT_TIME,
+ cstart);
+ stream_end =
+ gst_segment_to_running_time (&basesink->segment, GST_FORMAT_TIME, cend);
GST_OBJECT_LOCK (basesink);
/* also save end_time of this buffer so that we can wait
* to signal EOS */
- if (end_valid)
+ if (GST_CLOCK_TIME_IS_VALID (stream_end))
basesink->end_time = stream_end + base_time;
else
basesink->end_time = GST_CLOCK_TIME_NONE;
} else {
if (gst_pad_activate_pull (peer, TRUE)) {
basesink->have_newsegment = TRUE;
- basesink->segment_start = basesink->segment_stop = 0;
+ gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
/* set the pad mode before starting the task so that it's in the
correct state for the new thread... */
GST_OBJECT_LOCK (basesink);
if ((clock = GST_ELEMENT_CLOCK (basesink))) {
GstClockTime now;
- gint64 segment_time;
+ gint64 time;
gst_object_ref (clock);
GST_OBJECT_UNLOCK (basesink);
now = gst_clock_get_time (clock);
GST_OBJECT_LOCK (basesink);
- if (GST_CLOCK_TIME_IS_VALID (basesink->segment_time))
- segment_time = basesink->segment_time;
+ if (GST_CLOCK_TIME_IS_VALID (basesink->segment.time))
+ time = basesink->segment.time;
else
- segment_time = 0;
+ time = 0;
*cur = now - GST_ELEMENT_CAST (basesink)->base_time -
- basesink->segment_accum + segment_time;
+ basesink->segment.accum + time;
GST_DEBUG_OBJECT (basesink,
"now %" GST_TIME_FORMAT " + segment_time %" GST_TIME_FORMAT " = %"
GST_TIME_FORMAT, GST_TIME_ARGS (now),
- GST_TIME_ARGS (segment_time), GST_TIME_ARGS (*cur));
+ GST_TIME_ARGS (time), GST_TIME_ARGS (*cur));
gst_object_unref (clock);
case GST_QUERY_SEGMENT:
{
/* FIXME, bring start/stop to stream time */
- gst_query_set_segment (query, basesink->segment_rate,
- GST_FORMAT_TIME, basesink->segment_start, basesink->segment_stop);
+ gst_query_set_segment (query, basesink->segment.rate,
+ GST_FORMAT_TIME, basesink->segment.start, basesink->segment.stop);
break;
}
case GST_QUERY_SEEKING:
GST_DEBUG_OBJECT (basesink, "READY to PAUSED, need preroll to FALSE");
basesink->need_preroll = TRUE;
GST_PREROLL_UNLOCK (basesink->sinkpad);
+ gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
basesink->have_newsegment = FALSE;
- basesink->segment_rate = 1.0;
- basesink->segment_start = 0;
- basesink->segment_stop = -1;
- basesink->segment_time = 0;
- basesink->current_start = -1;
- basesink->current_duration = -1;
- basesink->current_end = -1;
- basesink->segment_accum = 0;
ret = GST_STATE_CHANGE_ASYNC;
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
/*< protected >*/ /* with STREAM_LOCK */
gboolean have_newsegment;
- gdouble segment_rate;
- gint64 segment_start;
- gint64 segment_stop;
- gint64 segment_time;
- gint64 segment_accum;
-
- gint64 current_start;
- gint64 current_duration;
- gint64 current_end;
+ GstSegment segment;
/*< private >*/ /* with LOCK */
GstClock *clock;
basesrc->blocksize = DEFAULT_BLOCKSIZE;
basesrc->clock_id = NULL;
- basesrc->segment_start = 0;
- basesrc->segment_end = -1;
+ gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
{
gint64 start, stop;
- start = src->segment_start;
+ start = src->segment.start;
/* no end segment configured, current size then */
- if ((stop = src->segment_end) == -1)
+ if ((stop = src->segment.stop) == -1)
stop = src->size;
/* FIXME, we can't report our rate as we did not store it, d'oh!.
GstEvent *event;
GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
+ " to %" G_GINT64_FORMAT, src->segment.start, src->segment.stop);
event = gst_event_new_newsegment (FALSE, 1.0,
- GST_FORMAT_BYTES, src->segment_start, src->segment_end,
- src->segment_start);
+ GST_FORMAT_BYTES, src->segment.start, src->segment.stop,
+ src->segment.start);
return gst_pad_push_event (src->srcpad, event);
}
return result;
}
-/* based on the event parameters configure the segment_start/stop
+/* based on the event parameters configure the segment.start/stop
* times. Called with STREAM_LOCK.
*/
static gboolean
GstSeekFlags flags;
GstSeekType cur_type, stop_type;
gint64 cur, stop;
- gboolean update_stop, update_start;
+ gboolean update;
gst_event_parse_seek (event, &rate, &format, &flags,
&cur_type, &cur, &stop_type, &stop);
- /* parse the loop flag */
- /* FIXME, need to store other flags and rate too */
- src->segment_loop = (flags & GST_SEEK_FLAG_SEGMENT) != 0;
-
- /* assume we'll update both start and stop values */
- update_start = TRUE;
- update_stop = TRUE;
-
- /* perform the seek, segment_start is never invalid */
- switch (cur_type) {
- case GST_SEEK_TYPE_NONE:
- /* no update to segment */
- cur = src->segment_start;
- update_start = FALSE;
- break;
- case GST_SEEK_TYPE_SET:
- /* cur holds desired position */
- break;
- case GST_SEEK_TYPE_CUR:
- /* add cur to currently configure segment */
- cur = src->segment_start + cur;
- break;
- case GST_SEEK_TYPE_END:
- /* add cur to total length */
- cur = src->size + cur;
- break;
- }
- /* bring in sane range */
- if (src->size != -1)
- cur = CLAMP (cur, 0, src->size);
- else
- cur = MAX (cur, 0);
-
- /* segment_end can be -1 if we have not configured a stop. */
- switch (stop_type) {
- case GST_SEEK_TYPE_NONE:
- stop = src->segment_end;
- update_stop = FALSE;
- break;
- case GST_SEEK_TYPE_SET:
- /* stop folds required value */
- break;
- case GST_SEEK_TYPE_CUR:
- if (src->segment_end != -1)
- stop = src->segment_end + stop;
- else
- stop = -1;
- break;
- case GST_SEEK_TYPE_END:
- if (src->size != -1)
- stop = src->size + stop;
- else
- stop = -1;
- break;
- }
-
- /* if we have a valid stop time, make sure it is clipped */
- if (stop != -1) {
- if (src->size != -1)
- stop = CLAMP (stop, 0, src->size);
- else
- stop = MAX (stop, 0);
- }
-
- src->segment_start = cur;
- src->segment_end = stop;
+ gst_segment_set_seek (&src->segment, rate, format, flags,
+ cur_type, cur, stop_type, stop, &update);
/* update our offset if it was updated */
- if (update_start)
+ if (update)
src->offset = cur;
GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
+ " to %" G_GINT64_FORMAT, src->segment.start, src->segment.stop);
return TRUE;
}
/* this code implements the seeking. It is a good example
* handling all cases (modulo the FIXMEs).
*
- * A seek updates the currently configured segment_start
- * and segment_stop values based on the SEEK_TYPE. If the
- * segment_start value is updated, a seek to this new position
+ * A seek updates the currently configured segment.start
+ * and segment.stop values based on the SEEK_TYPE. If the
+ * segment.start value is updated, a seek to this new position
* should be performed.
*
* The seek can only be executed when we are not currently
* can continue the seek. A non-flushing seek is normally done in a
* running pipeline to perform seamless playback.
*
- * After updating the segment_start/stop values, we prepare for
+ * After updating the segment.start/stop values, we prepare for
* streaming again. We push out a FLUSH_STOP to make the peer pad
* accept data again and we start our task again.
*
* A segment seek posts a message on the bus saying that the playback
* of the segment started. We store the segment flag internally because
- * when we reach the segment_stop we have to post a segment_done
+ * when we reach the segment.stop we have to post a segment.done
* instead of EOS when doing a segment seek.
*/
static gboolean
* thread. We could opt to send it here too. */
src->need_newsegment = TRUE;
- if (src->segment_loop) {
+ if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
/* FIXME subclasses should be able to provide other formats */
gst_element_post_message (GST_ELEMENT (src),
gst_message_new_segment_start (GST_OBJECT (src), GST_FORMAT_BYTES,
- src->segment_start));
+ src->segment.start));
}
/* and restart the task in case it got paused explicitely or by
goto no_function;
/* the max amount of bytes to read is the total size or
- * up to the segment_end if present. */
- if (src->segment_end != -1)
- maxsize = MIN (src->size, src->segment_end);
+ * up to the segment.stop if present. */
+ if (src->segment.stop != -1)
+ maxsize = MIN (src->size, src->segment.stop);
else
maxsize = src->size;
GST_DEBUG_OBJECT (src,
"reading offset %" G_GUINT64_FORMAT ", length %u, size %" G_GINT64_FORMAT
- ", segment_end %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
- length, src->size, src->segment_end, maxsize);
+ ", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
+ length, src->size, src->segment.stop, maxsize);
/* check size */
if (maxsize != -1) {
if (bclass->get_size)
bclass->get_size (src, &src->size);
- if (src->segment_end != -1)
- maxsize = MIN (src->size, src->segment_end);
+ if (src->segment.stop != -1)
+ maxsize = MIN (src->size, src->segment.stop);
else
maxsize = src->size;
{
GST_DEBUG_OBJECT (src, "going to EOS, getrange returned UNEXPECTED");
gst_pad_pause_task (pad);
- if (src->segment_loop) {
+ if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
/* FIXME, subclass might want to use another format */
gst_element_post_message (GST_ELEMENT (src),
gst_message_new_segment_done (GST_OBJECT (src),
- GST_FORMAT_BYTES, src->segment_end));
+ GST_FORMAT_BYTES, src->segment.stop));
} else {
gst_pad_push_event (pad, gst_event_new_eos ());
}
/* we always run from start to end when in READY, after putting
* the element to READY a seek can be done on the element to
* configure the segment when going to PAUSED. */
- basesrc->segment_loop = FALSE;
- basesrc->segment_start = 0;
- basesrc->segment_end = -1;
+ gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
basesrc->offset = 0;
break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
if (!gst_base_src_stop (basesrc))
goto error_stop;
/* we always run from start to end when in READY */
- basesrc->segment_loop = FALSE;
- basesrc->segment_start = 0;
- basesrc->segment_end = -1;
+ gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
basesrc->offset = 0;
break;
case GST_STATE_CHANGE_READY_TO_NULL:
GstClockTime end_time;
/* MT-protected (with STREAM_LOCK) */
- gint64 segment_start; /* start and end positions for seeking */
- gint64 segment_end;
- gboolean segment_loop;
+ GstSegment segment;
gboolean need_newsegment;
guint64 offset; /* current offset in the resource */
if (G_UNLIKELY (!gst_caps_is_equal (out_caps, GST_BUFFER_CAPS (*out_buf)))) {
/* FIXME, it is possible we can reconfigure the transform with new caps at this
* point but for now we just create a buffer ourselves */
+ gst_buffer_unref (*out_buf);
*out_buf = gst_buffer_new_and_alloc (out_size);
gst_buffer_set_caps (*out_buf, out_caps);
}
GST_STREAM_LOCK (pad);
unlock = TRUE;
/* we need new segment info after the flush. */
- trans->segment_rate = 1.0;
- trans->segment_start = -1;
- trans->segment_stop = -1;
- trans->segment_base = -1;
- GST_DEBUG_OBJECT (trans, "reset accum %" GST_TIME_FORMAT,
- GST_TIME_ARGS (trans->segment_accum));
- trans->segment_accum = 0;
+ gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
break;
case GST_EVENT_EOS:
GST_STREAM_LOCK (pad);
{
GstFormat format;
gdouble rate;
- gint64 start, stop, time, duration;
+ gint64 start, stop, time;
gboolean update;
GST_STREAM_LOCK (pad);
gst_event_parse_newsegment (event, &update, &rate, &format, &start, &stop,
&time);
- /* any other format with 0 also gives time 0, the other values are
- * invalid as time though. */
- if (format != GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (trans,
- "non-time newsegment with start 0, coaxing into FORMAT_TIME");
- format = GST_FORMAT_TIME;
- if (start != 0)
- start = -1;
- if (stop != 0)
- stop = -1;
- if (time != 0)
- time = -1;
- }
-
- /* check if we really have a new segment or the previous one is
- * closed */
- if (!update) {
- /* the new segment has to be aligned with the old segment.
- * We first update the accumulated time of the previous
- * segment. the accumulated time is used when syncing to the
- * clock. A flush event sets the accumulated time back to 0
- */
- if (GST_CLOCK_TIME_IS_VALID (trans->segment_stop)) {
- duration = trans->segment_stop - trans->segment_start;
- } else {
- duration = 0;
- }
- } else {
- if (GST_CLOCK_TIME_IS_VALID (start))
- duration = start - trans->segment_start;
- else
- duration = 0;
- }
+ gst_segment_set_newsegment (&trans->segment, update, rate, format, start,
+ stop, time);
trans->have_newsegment = TRUE;
- trans->segment_accum += gst_gdouble_to_guint64 (
- (gst_guint64_to_gdouble (duration) / ABS (trans->segment_rate)));;
- trans->segment_rate = rate;
- trans->segment_start = start;
- trans->segment_stop = stop;
- trans->segment_base = time;
-
if (format == GST_FORMAT_TIME) {
GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" GST_TIME_FORMAT
" -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
", accum %" GST_TIME_FORMAT,
- GST_TIME_ARGS (trans->segment_start),
- GST_TIME_ARGS (trans->segment_stop),
- GST_TIME_ARGS (trans->segment_base),
- GST_TIME_ARGS (trans->segment_accum));
+ GST_TIME_ARGS (trans->segment.start),
+ GST_TIME_ARGS (trans->segment.stop),
+ GST_TIME_ARGS (trans->segment.time),
+ GST_TIME_ARGS (trans->segment.accum));
} else {
GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" G_GINT64_FORMAT
" -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
", accum %" G_GINT64_FORMAT,
- trans->segment_start, trans->segment_stop,
- trans->segment_base, trans->segment_accum);
+ trans->segment.start, trans->segment.stop,
+ trans->segment.time, trans->segment.accum);
}
break;
}
GST_DEBUG_OBJECT (trans, "have_same_caps %d", trans->have_same_caps);
trans->negotiated = FALSE;
trans->have_newsegment = FALSE;
- trans->segment_rate = 1.0;
- trans->segment_start = 0;
- trans->segment_stop = -1;
- trans->segment_base = 0;
- trans->segment_accum = 0;
+ gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
GST_OBJECT_UNLOCK (trans);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
guint cache_caps1_size;
GstCaps *cache_caps2;
guint cache_caps2_size;
+ gboolean have_same_caps;
gboolean delay_configure;
gboolean pending_configure;
gboolean have_newsegment;
/* MT-protected (with STREAM_LOCK) */
- gdouble segment_rate;
- gint64 segment_start;
- gint64 segment_stop;
- gint64 segment_base;
-
- union {
- /* FIXME: When adjusting the padding, move this to a nice place in the structure */
- /* Set if caps on each pad are equal */
- struct {
- gboolean have_same_caps;
- GMutex *transform_lock;
- gint64 segment_accum;
- };
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING-1+1];
- };
+ GstSegment segment;
+
+ GMutex *transform_lock;
+
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING];
};
/**
gpointer _gst_reserved[GST_PADDING - 2];
};
-void gst_base_transform_set_passthrough (GstBaseTransform *trans,
- gboolean passthrough);
-gboolean gst_base_transform_is_passthrough (GstBaseTransform *trans);
+GType gst_base_transform_get_type (void);
+
+void gst_base_transform_set_passthrough (GstBaseTransform *trans,
+ gboolean passthrough);
+gboolean gst_base_transform_is_passthrough (GstBaseTransform *trans);
-void gst_base_transform_set_in_place (GstBaseTransform *trans,
- gboolean in_place);
-gboolean gst_base_transform_is_in_place (GstBaseTransform *trans);
+void gst_base_transform_set_in_place (GstBaseTransform *trans,
+ gboolean in_place);
+gboolean gst_base_transform_is_in_place (GstBaseTransform *trans);
-GType gst_base_transform_get_type (void);
G_END_DECLS
data->collect = pads;
data->pad = pad;
data->buffer = NULL;
+ gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
GST_OBJECT_LOCK (pads);
pads->data = g_slist_append (pads->data, data);
}
case GST_EVENT_NEWSEGMENT:
{
- gint64 segment_start, segment_stop, stream_time;
- gdouble segment_rate;
+ gint64 start, stop, time;
+ gdouble rate;
GstFormat format;
gboolean update;
- gst_event_parse_newsegment (event, &update, &segment_rate, &format,
- &segment_start, &segment_stop, &stream_time);
-
- if (format == GST_FORMAT_TIME) {
- data->segment_start = segment_start;
- data->segment_stop = segment_stop;
- data->stream_time = stream_time;
- }
+ gst_event_parse_newsegment (event, &update, &rate, &format,
+ &start, &stop, &time);
+ gst_segment_set_newsegment (&data->segment, update, rate, format,
+ start, stop, time);
goto beach;
}
default:
GstPad *pad;
GstBuffer *buffer;
guint pos;
- gint64 segment_start;
- gint64 segment_stop;
- gint64 stream_time;
+ GstSegment segment;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
gst_fake_src_init (GstFakeSrc * fakesrc, GstFakeSrcClass * g_class)
{
fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
- fakesrc->segment_start = -1;
- fakesrc->segment_end = -1;
fakesrc->buffer_count = 0;
fakesrc->silent = DEFAULT_SILENT;
fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
src = GST_FAKE_SRC (basesrc);
- if (src->buffer_count == src->segment_end) {
- GST_INFO ("buffer_count reaches segment_end %d %d", src->buffer_count,
- src->segment_end);
- return GST_FLOW_UNEXPECTED;
- }
-
buf = gst_fake_src_create_buffer (src);
GST_BUFFER_OFFSET (buf) = src->buffer_count++;
gint datarate;
gboolean sync;
GstClock *clock;
- gint64 segment_start;
- gint64 segment_end;
- gboolean segment_loop;
+
gint num_buffers;
gint rt_num_buffers; /* we are going to change this at runtime */
gint64 buffer_count;
GstClockReturn cret;
GstClockTime timestamp;
- timestamp = GST_BUFFER_TIMESTAMP (buf) - trans->segment_start;
- timestamp += trans->segment_accum;
+ timestamp = gst_segment_to_running_time (&trans->segment,
+ GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
timestamp += GST_ELEMENT (identity)->base_time;
/* save id if we need to unlock */
gint64 duration)
{
g_return_if_fail (segment != NULL);
- g_return_if_fail (segment->format == format);
+
+ if (segment->format == GST_FORMAT_UNDEFINED)
+ segment->format = format;
+ else
+ g_return_if_fail (segment->format == format);
segment->duration = duration;
}
gint64 position)
{
g_return_if_fail (segment != NULL);
- g_return_if_fail (segment->format == format);
+
+ if (segment->format == GST_FORMAT_UNDEFINED)
+ segment->format = format;
+ else
+ g_return_if_fail (segment->format == format);
segment->last_stop = position;
}
* @cur: the seek start value
* @stop_type: the seek method
* @stop: the seek stop value
+ * @update: boolean holding whether an update the current segment is
+ * needed.
*
* Update the segment structure with the field values of a seek event.
*/
void
gst_segment_set_seek (GstSegment * segment, gdouble rate,
GstFormat format, GstSeekFlags flags,
- GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
+ GstSeekType cur_type, gint64 cur,
+ GstSeekType stop_type, gint64 stop, gboolean * update)
{
gboolean update_stop, update_start;
g_return_if_fail (rate != 0.0);
g_return_if_fail (segment != NULL);
- g_return_if_fail (segment->format == format);
+
+ if (segment->format == GST_FORMAT_UNDEFINED)
+ segment->format = format;
+ else
+ g_return_if_fail (segment->format == format);
update_stop = update_start = TRUE;
segment->flags = flags;
segment->start = cur;
segment->stop = stop;
+
+ if (update)
+ *update = update_start || update_stop;
}
/**
g_return_if_fail (rate != 0.0);
g_return_if_fail (segment != NULL);
+ if (segment->format == GST_FORMAT_UNDEFINED)
+ segment->format = format;
+
/* any other format with 0 also gives time 0, the other values are
* invalid in the format though. */
if (format != segment->format && start == 0) {
gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
gint64 position)
{
- gint64 result;
+ gint64 result, time;
g_return_val_if_fail (segment != NULL, FALSE);
- g_return_val_if_fail (segment->format == format, FALSE);
- result = ((position - segment->start) / segment->abs_rate) + segment->time;
+ if (segment->format == GST_FORMAT_UNDEFINED)
+ segment->format = format;
+ else
+ g_return_val_if_fail (segment->format == format, FALSE);
+
+ if ((time = segment->time) == -1)
+ time = 0;
+
+ if (position != -1)
+ result = ((position - segment->start) / segment->abs_rate) + time;
+ else
+ result = -1;
return result;
}
{
gint64 result;
- g_return_val_if_fail (segment != NULL, FALSE);
- g_return_val_if_fail (segment->format == format, FALSE);
+ g_return_val_if_fail (segment != NULL, -1);
- result = ((position - segment->start) / segment->abs_rate) + segment->accum;
+ if (segment->format == GST_FORMAT_UNDEFINED)
+ segment->format = format;
+ else
+ g_return_val_if_fail (segment->format == format, -1);
+
+ if (position != -1)
+ result = ((position - segment->start) / segment->abs_rate) + segment->accum;
+ else
+ result = -1;
return result;
}
gint64 stop, gint64 * clip_start, gint64 * clip_stop)
{
g_return_val_if_fail (segment != NULL, FALSE);
- g_return_val_if_fail (segment->format == format, FALSE);
+
+ if (segment->format == GST_FORMAT_UNDEFINED)
+ segment->format = format;
+ else
+ g_return_val_if_fail (segment->format == format, FALSE);
/* we need a valid start position */
if (start == -1)
void gst_segment_set_seek (GstSegment *segment, gdouble rate,
GstFormat format, GstSeekFlags flags,
GstSeekType cur_type, gint64 cur,
- GstSeekType stop_type, gint64 stop);
+ GstSeekType stop_type, gint64 stop,
+ gboolean *update);
void gst_segment_set_newsegment (GstSegment *segment, gboolean update, gdouble rate,
GstFormat format, gint64 start, gint64 stop, gint64 time);
gboolean update;
gdouble rate;
GstFormat format;
- gint64 segment_start;
- gint64 segment_stop;
- gint64 segment_time;
- GstClockTime duration;
+ gint64 start;
+ gint64 stop;
+ gint64 time;
/* the newsegment event is needed to bring the buffer timestamps to the
* stream time and to drop samples outside of the playback segment. */
gst_event_parse_newsegment (event, &update, &rate, &format,
- &segment_start, &segment_stop, &segment_time);
+ &start, &stop, &time);
basesink->have_newsegment = TRUE;
- /* any other format with 0 also gives time 0, the other values are
- * invalid as time though. */
- if (format != GST_FORMAT_TIME && segment_start == 0) {
- GST_DEBUG_OBJECT (basesink,
- "non-time newsegment with start 0, coaxing into FORMAT_TIME");
- format = GST_FORMAT_TIME;
- if (segment_stop != 0)
- segment_stop = -1;
- if (segment_time != 0)
- segment_time = -1;
- }
-
- if (format != GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (basesink,
- "received non time %d NEW_SEGMENT %" G_GINT64_FORMAT
- " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT,
- format, segment_start, segment_stop, segment_time);
-
- /* this means this sink will not be able to clip or drop samples
- * and timestamps have to start from 0. */
- basesink->segment_start = -1;
- basesink->segment_stop = -1;
- basesink->segment_time = -1;
- goto done_newsegment;
- }
- /* check if we really have a new segment or the previous one is
- * closed */
- if (!update) {
- /* the new segment has to be aligned with the old segment.
- * We first update the accumulated time of the previous
- * segment. the accumulated time is used when syncing to the
- * clock. A flush event sets the accumulated time back to 0
- */
- if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
- duration = basesink->segment_stop - basesink->segment_start;
- } else if (GST_CLOCK_TIME_IS_VALID (basesink->current_end)) {
- /* else use last seen timestamp as segment stop */
- duration = basesink->current_end - basesink->segment_start;
- } else {
- duration = 0;
- }
- } else {
- duration = segment_start - basesink->segment_start;
- }
-
- /* use previous rate to calculate duration */
- basesink->segment_accum += gst_gdouble_to_guint64 (
- (gst_guint64_to_gdouble (duration) / ABS (basesink->segment_rate)));
- /* then update the current segment */
- basesink->segment_rate = rate;
- basesink->segment_start = segment_start;
- basesink->segment_stop = segment_stop;
- basesink->segment_time = segment_time;
+ gst_segment_set_newsegment (&basesink->segment, update, rate, format,
+ start, stop, time);
GST_DEBUG_OBJECT (basesink,
"received NEWSEGMENT %" GST_TIME_FORMAT " -- %"
GST_TIME_FORMAT ", time %" GST_TIME_FORMAT ", accum %"
GST_TIME_FORMAT,
- GST_TIME_ARGS (basesink->segment_start),
- GST_TIME_ARGS (basesink->segment_stop),
- GST_TIME_ARGS (basesink->segment_time),
- GST_TIME_ARGS (basesink->segment_accum));
- done_newsegment:
+ GST_TIME_ARGS (basesink->segment.start),
+ GST_TIME_ARGS (basesink->segment.stop),
+ GST_TIME_ARGS (basesink->segment.time),
+ GST_TIME_ARGS (basesink->segment.accum));
break;
}
default:
("Received buffer without a new-segment. Cannot sync to clock."));
basesink->have_newsegment = TRUE;
/* this means this sink will not be able to sync to the clock */
- basesink->segment_start = -1;
- basesink->segment_stop = -1;
+ basesink->segment.start = -1;
+ basesink->segment.stop = -1;
}
/* check if the buffer needs to be dropped */
", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
GST_TIME_ARGS (end));
- /* need to drop if the timestamp is not between segment_start and
- * segment_stop. we check if the complete sample is outside of the
- * range since the sink might be able to clip the sample. */
- if (GST_CLOCK_TIME_IS_VALID (end) &&
- GST_CLOCK_TIME_IS_VALID (basesink->segment_start)) {
- if (end <= basesink->segment_start) {
- GST_DEBUG_OBJECT (basesink,
- "buffer end %" GST_TIME_FORMAT " <= segment start %"
- GST_TIME_FORMAT ", dropping buffer", GST_TIME_ARGS (end),
- GST_TIME_ARGS (basesink->segment_start));
+ if (GST_CLOCK_TIME_IS_VALID (start)) {
+ if (!gst_segment_clip (&basesink->segment, GST_FORMAT_TIME,
+ (gint64) start, (gint64) end, NULL, NULL))
goto dropping;
- }
- }
- if (GST_CLOCK_TIME_IS_VALID (start) &&
- GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
- if (basesink->segment_stop <= start) {
- GST_DEBUG_OBJECT (basesink,
- "buffer start %" GST_TIME_FORMAT " >= segment stop %"
- GST_TIME_FORMAT ", dropping buffer", GST_TIME_ARGS (start),
- GST_TIME_ARGS (basesink->segment_stop));
- goto dropping;
- }
}
}
basesink->preroll_queued++;
basesink->flushing = FALSE;
GST_OBJECT_UNLOCK (basesink);
/* we need new segment info after the flush. */
- basesink->segment_start = -1;
- basesink->segment_stop = -1;
- basesink->current_start = -1;
- basesink->current_end = -1;
- GST_DEBUG_OBJECT (basesink, "reset accum %" GST_TIME_FORMAT,
- GST_TIME_ARGS (basesink->segment_accum));
- basesink->segment_accum = 0;
+ gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
GST_STREAM_UNLOCK (pad);
GST_DEBUG_OBJECT (basesink, "event unref %p %p", basesink, event);
{
GstClockReturn result = GST_CLOCK_OK;
GstClockTime start, end;
- GstClockTimeDiff stream_start, stream_end;
+ gint64 cstart, cend;
GstBaseSinkClass *bclass;
- gboolean start_valid, end_valid;
bclass = GST_BASE_SINK_GET_CLASS (basesink);
if (bclass->get_times)
bclass->get_times (basesink, buffer, &start, &end);
- start_valid = GST_CLOCK_TIME_IS_VALID (start);
- end_valid = GST_CLOCK_TIME_IS_VALID (end);
-
GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT
", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end));
/* if we don't have a timestamp, we don't sync */
- if (!start_valid) {
+ if (!GST_CLOCK_TIME_IS_VALID (start)) {
GST_DEBUG_OBJECT (basesink, "start not valid");
goto done;
}
/* save last times seen. */
- basesink->current_start = start;
- if (end_valid)
- basesink->current_end = end;
+ if (GST_CLOCK_TIME_IS_VALID (end))
+ gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_TIME,
+ (gint64) end);
else
- basesink->current_end = start;
+ gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_TIME,
+ (gint64) start);
- if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
- /* check if not outside of the segment range, start is
- * always valid here. */
- if (start > basesink->segment_stop)
- goto out_of_segment;
- }
-
- /* bring timestamp to stream time using last segment offset. */
- if (GST_CLOCK_TIME_IS_VALID (basesink->segment_start)) {
- /* check if not outside of the segment range */
- if (end_valid && end < basesink->segment_start)
- goto out_of_segment;
-
- stream_start = (gint64) start - basesink->segment_start;
- stream_end = (gint64) end - basesink->segment_start;
-
- if (stream_start < 0) {
- GST_DEBUG_OBJECT (basesink, "stream_start negative, invalid");
- goto done;
- }
- } else {
- stream_start = (gint64) start;
- stream_end = (gint64) end;
- }
-
-
- /* correct for rate */
- if (basesink->segment_rate != 0.0) {
- stream_start /= ABS (basesink->segment_rate);
- if (end_valid)
- stream_end /= ABS (basesink->segment_rate);
- }
-
- stream_start += basesink->segment_accum;
- if (end_valid)
- stream_end += basesink->segment_accum;
+ /* clip */
+ if (!gst_segment_clip (&basesink->segment, GST_FORMAT_TIME,
+ (gint64) start, (gint64) end, &cstart, &cend))
+ goto out_of_segment;
if (!basesink->sync) {
GST_DEBUG_OBJECT (basesink, "no need to sync");
/* now do clocking */
if (basesink->clock) {
GstClockTime base_time;
+ GstClockTimeDiff stream_start, stream_end;
+
+ stream_start =
+ gst_segment_to_running_time (&basesink->segment, GST_FORMAT_TIME,
+ cstart);
+ stream_end =
+ gst_segment_to_running_time (&basesink->segment, GST_FORMAT_TIME, cend);
GST_OBJECT_LOCK (basesink);
/* also save end_time of this buffer so that we can wait
* to signal EOS */
- if (end_valid)
+ if (GST_CLOCK_TIME_IS_VALID (stream_end))
basesink->end_time = stream_end + base_time;
else
basesink->end_time = GST_CLOCK_TIME_NONE;
} else {
if (gst_pad_activate_pull (peer, TRUE)) {
basesink->have_newsegment = TRUE;
- basesink->segment_start = basesink->segment_stop = 0;
+ gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
/* set the pad mode before starting the task so that it's in the
correct state for the new thread... */
GST_OBJECT_LOCK (basesink);
if ((clock = GST_ELEMENT_CLOCK (basesink))) {
GstClockTime now;
- gint64 segment_time;
+ gint64 time;
gst_object_ref (clock);
GST_OBJECT_UNLOCK (basesink);
now = gst_clock_get_time (clock);
GST_OBJECT_LOCK (basesink);
- if (GST_CLOCK_TIME_IS_VALID (basesink->segment_time))
- segment_time = basesink->segment_time;
+ if (GST_CLOCK_TIME_IS_VALID (basesink->segment.time))
+ time = basesink->segment.time;
else
- segment_time = 0;
+ time = 0;
*cur = now - GST_ELEMENT_CAST (basesink)->base_time -
- basesink->segment_accum + segment_time;
+ basesink->segment.accum + time;
GST_DEBUG_OBJECT (basesink,
"now %" GST_TIME_FORMAT " + segment_time %" GST_TIME_FORMAT " = %"
GST_TIME_FORMAT, GST_TIME_ARGS (now),
- GST_TIME_ARGS (segment_time), GST_TIME_ARGS (*cur));
+ GST_TIME_ARGS (time), GST_TIME_ARGS (*cur));
gst_object_unref (clock);
case GST_QUERY_SEGMENT:
{
/* FIXME, bring start/stop to stream time */
- gst_query_set_segment (query, basesink->segment_rate,
- GST_FORMAT_TIME, basesink->segment_start, basesink->segment_stop);
+ gst_query_set_segment (query, basesink->segment.rate,
+ GST_FORMAT_TIME, basesink->segment.start, basesink->segment.stop);
break;
}
case GST_QUERY_SEEKING:
GST_DEBUG_OBJECT (basesink, "READY to PAUSED, need preroll to FALSE");
basesink->need_preroll = TRUE;
GST_PREROLL_UNLOCK (basesink->sinkpad);
+ gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
basesink->have_newsegment = FALSE;
- basesink->segment_rate = 1.0;
- basesink->segment_start = 0;
- basesink->segment_stop = -1;
- basesink->segment_time = 0;
- basesink->current_start = -1;
- basesink->current_duration = -1;
- basesink->current_end = -1;
- basesink->segment_accum = 0;
ret = GST_STATE_CHANGE_ASYNC;
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
/*< protected >*/ /* with STREAM_LOCK */
gboolean have_newsegment;
- gdouble segment_rate;
- gint64 segment_start;
- gint64 segment_stop;
- gint64 segment_time;
- gint64 segment_accum;
-
- gint64 current_start;
- gint64 current_duration;
- gint64 current_end;
+ GstSegment segment;
/*< private >*/ /* with LOCK */
GstClock *clock;
basesrc->blocksize = DEFAULT_BLOCKSIZE;
basesrc->clock_id = NULL;
- basesrc->segment_start = 0;
- basesrc->segment_end = -1;
+ gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
{
gint64 start, stop;
- start = src->segment_start;
+ start = src->segment.start;
/* no end segment configured, current size then */
- if ((stop = src->segment_end) == -1)
+ if ((stop = src->segment.stop) == -1)
stop = src->size;
/* FIXME, we can't report our rate as we did not store it, d'oh!.
GstEvent *event;
GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
+ " to %" G_GINT64_FORMAT, src->segment.start, src->segment.stop);
event = gst_event_new_newsegment (FALSE, 1.0,
- GST_FORMAT_BYTES, src->segment_start, src->segment_end,
- src->segment_start);
+ GST_FORMAT_BYTES, src->segment.start, src->segment.stop,
+ src->segment.start);
return gst_pad_push_event (src->srcpad, event);
}
return result;
}
-/* based on the event parameters configure the segment_start/stop
+/* based on the event parameters configure the segment.start/stop
* times. Called with STREAM_LOCK.
*/
static gboolean
GstSeekFlags flags;
GstSeekType cur_type, stop_type;
gint64 cur, stop;
- gboolean update_stop, update_start;
+ gboolean update;
gst_event_parse_seek (event, &rate, &format, &flags,
&cur_type, &cur, &stop_type, &stop);
- /* parse the loop flag */
- /* FIXME, need to store other flags and rate too */
- src->segment_loop = (flags & GST_SEEK_FLAG_SEGMENT) != 0;
-
- /* assume we'll update both start and stop values */
- update_start = TRUE;
- update_stop = TRUE;
-
- /* perform the seek, segment_start is never invalid */
- switch (cur_type) {
- case GST_SEEK_TYPE_NONE:
- /* no update to segment */
- cur = src->segment_start;
- update_start = FALSE;
- break;
- case GST_SEEK_TYPE_SET:
- /* cur holds desired position */
- break;
- case GST_SEEK_TYPE_CUR:
- /* add cur to currently configure segment */
- cur = src->segment_start + cur;
- break;
- case GST_SEEK_TYPE_END:
- /* add cur to total length */
- cur = src->size + cur;
- break;
- }
- /* bring in sane range */
- if (src->size != -1)
- cur = CLAMP (cur, 0, src->size);
- else
- cur = MAX (cur, 0);
-
- /* segment_end can be -1 if we have not configured a stop. */
- switch (stop_type) {
- case GST_SEEK_TYPE_NONE:
- stop = src->segment_end;
- update_stop = FALSE;
- break;
- case GST_SEEK_TYPE_SET:
- /* stop folds required value */
- break;
- case GST_SEEK_TYPE_CUR:
- if (src->segment_end != -1)
- stop = src->segment_end + stop;
- else
- stop = -1;
- break;
- case GST_SEEK_TYPE_END:
- if (src->size != -1)
- stop = src->size + stop;
- else
- stop = -1;
- break;
- }
-
- /* if we have a valid stop time, make sure it is clipped */
- if (stop != -1) {
- if (src->size != -1)
- stop = CLAMP (stop, 0, src->size);
- else
- stop = MAX (stop, 0);
- }
-
- src->segment_start = cur;
- src->segment_end = stop;
+ gst_segment_set_seek (&src->segment, rate, format, flags,
+ cur_type, cur, stop_type, stop, &update);
/* update our offset if it was updated */
- if (update_start)
+ if (update)
src->offset = cur;
GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
+ " to %" G_GINT64_FORMAT, src->segment.start, src->segment.stop);
return TRUE;
}
/* this code implements the seeking. It is a good example
* handling all cases (modulo the FIXMEs).
*
- * A seek updates the currently configured segment_start
- * and segment_stop values based on the SEEK_TYPE. If the
- * segment_start value is updated, a seek to this new position
+ * A seek updates the currently configured segment.start
+ * and segment.stop values based on the SEEK_TYPE. If the
+ * segment.start value is updated, a seek to this new position
* should be performed.
*
* The seek can only be executed when we are not currently
* can continue the seek. A non-flushing seek is normally done in a
* running pipeline to perform seamless playback.
*
- * After updating the segment_start/stop values, we prepare for
+ * After updating the segment.start/stop values, we prepare for
* streaming again. We push out a FLUSH_STOP to make the peer pad
* accept data again and we start our task again.
*
* A segment seek posts a message on the bus saying that the playback
* of the segment started. We store the segment flag internally because
- * when we reach the segment_stop we have to post a segment_done
+ * when we reach the segment.stop we have to post a segment.done
* instead of EOS when doing a segment seek.
*/
static gboolean
* thread. We could opt to send it here too. */
src->need_newsegment = TRUE;
- if (src->segment_loop) {
+ if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
/* FIXME subclasses should be able to provide other formats */
gst_element_post_message (GST_ELEMENT (src),
gst_message_new_segment_start (GST_OBJECT (src), GST_FORMAT_BYTES,
- src->segment_start));
+ src->segment.start));
}
/* and restart the task in case it got paused explicitely or by
goto no_function;
/* the max amount of bytes to read is the total size or
- * up to the segment_end if present. */
- if (src->segment_end != -1)
- maxsize = MIN (src->size, src->segment_end);
+ * up to the segment.stop if present. */
+ if (src->segment.stop != -1)
+ maxsize = MIN (src->size, src->segment.stop);
else
maxsize = src->size;
GST_DEBUG_OBJECT (src,
"reading offset %" G_GUINT64_FORMAT ", length %u, size %" G_GINT64_FORMAT
- ", segment_end %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
- length, src->size, src->segment_end, maxsize);
+ ", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
+ length, src->size, src->segment.stop, maxsize);
/* check size */
if (maxsize != -1) {
if (bclass->get_size)
bclass->get_size (src, &src->size);
- if (src->segment_end != -1)
- maxsize = MIN (src->size, src->segment_end);
+ if (src->segment.stop != -1)
+ maxsize = MIN (src->size, src->segment.stop);
else
maxsize = src->size;
{
GST_DEBUG_OBJECT (src, "going to EOS, getrange returned UNEXPECTED");
gst_pad_pause_task (pad);
- if (src->segment_loop) {
+ if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
/* FIXME, subclass might want to use another format */
gst_element_post_message (GST_ELEMENT (src),
gst_message_new_segment_done (GST_OBJECT (src),
- GST_FORMAT_BYTES, src->segment_end));
+ GST_FORMAT_BYTES, src->segment.stop));
} else {
gst_pad_push_event (pad, gst_event_new_eos ());
}
/* we always run from start to end when in READY, after putting
* the element to READY a seek can be done on the element to
* configure the segment when going to PAUSED. */
- basesrc->segment_loop = FALSE;
- basesrc->segment_start = 0;
- basesrc->segment_end = -1;
+ gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
basesrc->offset = 0;
break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
if (!gst_base_src_stop (basesrc))
goto error_stop;
/* we always run from start to end when in READY */
- basesrc->segment_loop = FALSE;
- basesrc->segment_start = 0;
- basesrc->segment_end = -1;
+ gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
basesrc->offset = 0;
break;
case GST_STATE_CHANGE_READY_TO_NULL:
GstClockTime end_time;
/* MT-protected (with STREAM_LOCK) */
- gint64 segment_start; /* start and end positions for seeking */
- gint64 segment_end;
- gboolean segment_loop;
+ GstSegment segment;
gboolean need_newsegment;
guint64 offset; /* current offset in the resource */
if (G_UNLIKELY (!gst_caps_is_equal (out_caps, GST_BUFFER_CAPS (*out_buf)))) {
/* FIXME, it is possible we can reconfigure the transform with new caps at this
* point but for now we just create a buffer ourselves */
+ gst_buffer_unref (*out_buf);
*out_buf = gst_buffer_new_and_alloc (out_size);
gst_buffer_set_caps (*out_buf, out_caps);
}
GST_STREAM_LOCK (pad);
unlock = TRUE;
/* we need new segment info after the flush. */
- trans->segment_rate = 1.0;
- trans->segment_start = -1;
- trans->segment_stop = -1;
- trans->segment_base = -1;
- GST_DEBUG_OBJECT (trans, "reset accum %" GST_TIME_FORMAT,
- GST_TIME_ARGS (trans->segment_accum));
- trans->segment_accum = 0;
+ gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
break;
case GST_EVENT_EOS:
GST_STREAM_LOCK (pad);
{
GstFormat format;
gdouble rate;
- gint64 start, stop, time, duration;
+ gint64 start, stop, time;
gboolean update;
GST_STREAM_LOCK (pad);
gst_event_parse_newsegment (event, &update, &rate, &format, &start, &stop,
&time);
- /* any other format with 0 also gives time 0, the other values are
- * invalid as time though. */
- if (format != GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (trans,
- "non-time newsegment with start 0, coaxing into FORMAT_TIME");
- format = GST_FORMAT_TIME;
- if (start != 0)
- start = -1;
- if (stop != 0)
- stop = -1;
- if (time != 0)
- time = -1;
- }
-
- /* check if we really have a new segment or the previous one is
- * closed */
- if (!update) {
- /* the new segment has to be aligned with the old segment.
- * We first update the accumulated time of the previous
- * segment. the accumulated time is used when syncing to the
- * clock. A flush event sets the accumulated time back to 0
- */
- if (GST_CLOCK_TIME_IS_VALID (trans->segment_stop)) {
- duration = trans->segment_stop - trans->segment_start;
- } else {
- duration = 0;
- }
- } else {
- if (GST_CLOCK_TIME_IS_VALID (start))
- duration = start - trans->segment_start;
- else
- duration = 0;
- }
+ gst_segment_set_newsegment (&trans->segment, update, rate, format, start,
+ stop, time);
trans->have_newsegment = TRUE;
- trans->segment_accum += gst_gdouble_to_guint64 (
- (gst_guint64_to_gdouble (duration) / ABS (trans->segment_rate)));;
- trans->segment_rate = rate;
- trans->segment_start = start;
- trans->segment_stop = stop;
- trans->segment_base = time;
-
if (format == GST_FORMAT_TIME) {
GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" GST_TIME_FORMAT
" -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
", accum %" GST_TIME_FORMAT,
- GST_TIME_ARGS (trans->segment_start),
- GST_TIME_ARGS (trans->segment_stop),
- GST_TIME_ARGS (trans->segment_base),
- GST_TIME_ARGS (trans->segment_accum));
+ GST_TIME_ARGS (trans->segment.start),
+ GST_TIME_ARGS (trans->segment.stop),
+ GST_TIME_ARGS (trans->segment.time),
+ GST_TIME_ARGS (trans->segment.accum));
} else {
GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" G_GINT64_FORMAT
" -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
", accum %" G_GINT64_FORMAT,
- trans->segment_start, trans->segment_stop,
- trans->segment_base, trans->segment_accum);
+ trans->segment.start, trans->segment.stop,
+ trans->segment.time, trans->segment.accum);
}
break;
}
GST_DEBUG_OBJECT (trans, "have_same_caps %d", trans->have_same_caps);
trans->negotiated = FALSE;
trans->have_newsegment = FALSE;
- trans->segment_rate = 1.0;
- trans->segment_start = 0;
- trans->segment_stop = -1;
- trans->segment_base = 0;
- trans->segment_accum = 0;
+ gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
GST_OBJECT_UNLOCK (trans);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
guint cache_caps1_size;
GstCaps *cache_caps2;
guint cache_caps2_size;
+ gboolean have_same_caps;
gboolean delay_configure;
gboolean pending_configure;
gboolean have_newsegment;
/* MT-protected (with STREAM_LOCK) */
- gdouble segment_rate;
- gint64 segment_start;
- gint64 segment_stop;
- gint64 segment_base;
-
- union {
- /* FIXME: When adjusting the padding, move this to a nice place in the structure */
- /* Set if caps on each pad are equal */
- struct {
- gboolean have_same_caps;
- GMutex *transform_lock;
- gint64 segment_accum;
- };
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING-1+1];
- };
+ GstSegment segment;
+
+ GMutex *transform_lock;
+
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING];
};
/**
gpointer _gst_reserved[GST_PADDING - 2];
};
-void gst_base_transform_set_passthrough (GstBaseTransform *trans,
- gboolean passthrough);
-gboolean gst_base_transform_is_passthrough (GstBaseTransform *trans);
+GType gst_base_transform_get_type (void);
+
+void gst_base_transform_set_passthrough (GstBaseTransform *trans,
+ gboolean passthrough);
+gboolean gst_base_transform_is_passthrough (GstBaseTransform *trans);
-void gst_base_transform_set_in_place (GstBaseTransform *trans,
- gboolean in_place);
-gboolean gst_base_transform_is_in_place (GstBaseTransform *trans);
+void gst_base_transform_set_in_place (GstBaseTransform *trans,
+ gboolean in_place);
+gboolean gst_base_transform_is_in_place (GstBaseTransform *trans);
-GType gst_base_transform_get_type (void);
G_END_DECLS
data->collect = pads;
data->pad = pad;
data->buffer = NULL;
+ gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
GST_OBJECT_LOCK (pads);
pads->data = g_slist_append (pads->data, data);
}
case GST_EVENT_NEWSEGMENT:
{
- gint64 segment_start, segment_stop, stream_time;
- gdouble segment_rate;
+ gint64 start, stop, time;
+ gdouble rate;
GstFormat format;
gboolean update;
- gst_event_parse_newsegment (event, &update, &segment_rate, &format,
- &segment_start, &segment_stop, &stream_time);
-
- if (format == GST_FORMAT_TIME) {
- data->segment_start = segment_start;
- data->segment_stop = segment_stop;
- data->stream_time = stream_time;
- }
+ gst_event_parse_newsegment (event, &update, &rate, &format,
+ &start, &stop, &time);
+ gst_segment_set_newsegment (&data->segment, update, rate, format,
+ start, stop, time);
goto beach;
}
default:
GstPad *pad;
GstBuffer *buffer;
guint pos;
- gint64 segment_start;
- gint64 segment_stop;
- gint64 stream_time;
+ GstSegment segment;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
gst_fake_src_init (GstFakeSrc * fakesrc, GstFakeSrcClass * g_class)
{
fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
- fakesrc->segment_start = -1;
- fakesrc->segment_end = -1;
fakesrc->buffer_count = 0;
fakesrc->silent = DEFAULT_SILENT;
fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
src = GST_FAKE_SRC (basesrc);
- if (src->buffer_count == src->segment_end) {
- GST_INFO ("buffer_count reaches segment_end %d %d", src->buffer_count,
- src->segment_end);
- return GST_FLOW_UNEXPECTED;
- }
-
buf = gst_fake_src_create_buffer (src);
GST_BUFFER_OFFSET (buf) = src->buffer_count++;
gint datarate;
gboolean sync;
GstClock *clock;
- gint64 segment_start;
- gint64 segment_end;
- gboolean segment_loop;
+
gint num_buffers;
gint rt_num_buffers; /* we are going to change this at runtime */
gint64 buffer_count;
GstClockReturn cret;
GstClockTime timestamp;
- timestamp = GST_BUFFER_TIMESTAMP (buf) - trans->segment_start;
- timestamp += trans->segment_accum;
+ timestamp = gst_segment_to_running_time (&trans->segment,
+ GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
timestamp += GST_ELEMENT (identity)->base_time;
/* save id if we need to unlock */
GstSegment segment;
gboolean res;
gint64 cstart, cstop;
+ gboolean update;
gst_segment_init (&segment, GST_FORMAT_BYTES);
/* configure segment to start 100 */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == -1);
* size is unknown. */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == -1);
/* add 100 to start, set stop to 300 */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
fail_unless (segment.start == 200);
fail_unless (segment.stop == 300);
* nothing should be updated in the segment. */
ASSERT_CRITICAL (gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200));
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update));
fail_unless (segment.start == 200);
fail_unless (segment.stop == 300);
* unknown. */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update);
fail_unless (segment.start == 200);
fail_unless (segment.stop == 300);
GstSegment segment;
gboolean res;
gint64 cstart, cstop;
+ gboolean update;
gst_segment_init (&segment, GST_FORMAT_BYTES);
gst_segment_set_duration (&segment, GST_FORMAT_BYTES, 200);
/* configure segment to start 100 */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == -1);
* since we did not set it before. */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == -1);
/* add 100 to start, set stop to 300, stop clips to 200 */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
fail_unless (segment.start == 200);
fail_unless (segment.stop == 200);
* to duration */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update);
fail_unless (segment.start == 200);
fail_unless (segment.stop == 200);
/* seek relative to end */
gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
- GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20);
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update);
fail_unless (segment.start == 100);
fail_unless (segment.stop == 180);