More segment updates, replace code in plugins with segment helper functions.

Original commit message from CVS:
* 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.
This commit is contained in:
Wim Taymans 2005-11-21 17:09:45 +00:00
parent 9409e07440
commit a35882df1f
28 changed files with 361 additions and 788 deletions

View file

@ -1,3 +1,37 @@
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):

View file

@ -27,13 +27,15 @@ GST_START_TEST (segment_seek_nosize)
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);
@ -41,7 +43,8 @@ GST_START_TEST (segment_seek_nosize)
* 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);
@ -99,7 +102,8 @@ GST_START_TEST (segment_seek_nosize)
/* 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);
@ -107,7 +111,8 @@ GST_START_TEST (segment_seek_nosize)
* 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);
@ -115,7 +120,8 @@ GST_START_TEST (segment_seek_nosize)
* 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);
@ -193,6 +199,7 @@ GST_START_TEST (segment_seek_size)
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);
@ -200,7 +207,8 @@ GST_START_TEST (segment_seek_size)
/* 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);
@ -208,7 +216,8 @@ GST_START_TEST (segment_seek_size)
* 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);
@ -273,7 +282,8 @@ GST_START_TEST (segment_seek_size)
/* 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);
@ -281,14 +291,16 @@ GST_START_TEST (segment_seek_size)
* 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);

View file

@ -15,8 +15,6 @@ API/ABI
- 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
@ -26,10 +24,6 @@ API/ABI
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
--------------

View file

@ -579,81 +579,28 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
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:
@ -669,8 +616,8 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
("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 */
@ -685,28 +632,10 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
", 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++;
@ -917,13 +846,7 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
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);
@ -1004,9 +927,8 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
{
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);
@ -1014,61 +936,27 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
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");
@ -1078,6 +966,13 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
/* 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);
@ -1090,7 +985,7 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
/* 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;
@ -1386,7 +1281,7 @@ gst_base_sink_activate_pull (GstPad * pad, gboolean active)
} 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... */
@ -1467,7 +1362,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
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);
@ -1475,18 +1370,18 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
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);
@ -1547,8 +1442,8 @@ gst_base_sink_query (GstElement * element, GstQuery * query)
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:
@ -1585,15 +1480,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
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:

View file

@ -80,15 +80,7 @@ struct _GstBaseSink {
/*< 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;

View file

@ -229,8 +229,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
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);
@ -411,9 +410,9 @@ gst_base_src_query (GstPad * pad, GstQuery * query)
{
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!.
@ -448,11 +447,11 @@ gst_base_src_default_newsegment (GstBaseSrc * src)
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);
}
@ -471,7 +470,7 @@ gst_base_src_newsegment (GstBaseSrc * src)
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
@ -482,84 +481,20 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
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;
}
@ -567,9 +502,9 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
/* 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
@ -592,13 +527,13 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
* 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
@ -648,11 +583,11 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
* 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
@ -906,16 +841,16 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
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) {
@ -927,8 +862,8 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
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;
@ -1072,11 +1007,11 @@ eos:
{
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 ());
}
@ -1493,9 +1428,7 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
/* 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:
@ -1510,9 +1443,7 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
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:

View file

@ -84,9 +84,7 @@ struct _GstBaseSrc {
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 */

View file

@ -854,6 +854,7 @@ gst_base_transform_prepare_output_buf (GstBaseTransform * trans,
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);
}
@ -1056,13 +1057,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
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);
@ -1076,7 +1071,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
{
GstFormat format;
gdouble rate;
gint64 start, stop, time, duration;
gint64 start, stop, time;
gboolean update;
GST_STREAM_LOCK (pad);
@ -1084,63 +1079,25 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
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;
}
@ -1432,11 +1389,7 @@ gst_base_transform_change_state (GstElement * element,
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:

View file

@ -65,6 +65,7 @@ struct _GstBaseTransform {
guint cache_caps1_size;
GstCaps *cache_caps2;
guint cache_caps2_size;
gboolean have_same_caps;
gboolean delay_configure;
gboolean pending_configure;
@ -73,22 +74,12 @@ struct _GstBaseTransform {
gboolean have_newsegment;
/* MT-protected (with STREAM_LOCK) */
gdouble segment_rate;
gint64 segment_start;
gint64 segment_stop;
gint64 segment_base;
GstSegment segment;
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];
};
GMutex *transform_lock;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
/**
@ -165,15 +156,16 @@ struct _GstBaseTransformClass {
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_in_place (GstBaseTransform *trans,
gboolean in_place);
gboolean gst_base_transform_is_in_place (GstBaseTransform *trans);
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);
GType gst_base_transform_get_type (void);
G_END_DECLS

View file

@ -196,6 +196,7 @@ gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
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);
@ -599,20 +600,16 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event)
}
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:

View file

@ -55,9 +55,7 @@ struct _GstCollectData
GstPad *pad;
GstBuffer *buffer;
guint pos;
gint64 segment_start;
gint64 segment_stop;
gint64 stream_time;
GstSegment segment;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];

View file

@ -324,8 +324,6 @@ static void
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;
@ -687,12 +685,6 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
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++;

View file

@ -96,9 +96,7 @@ struct _GstFakeSrc {
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;

View file

@ -376,8 +376,8 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
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 */

View file

@ -77,7 +77,11 @@ gst_segment_set_duration (GstSegment * segment, GstFormat format,
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;
}
@ -95,7 +99,11 @@ gst_segment_set_last_stop (GstSegment * segment, GstFormat format,
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;
}
@ -110,19 +118,26 @@ gst_segment_set_last_stop (GstSegment * segment, GstFormat format,
* @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;
@ -199,6 +214,9 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
segment->flags = flags;
segment->start = cur;
segment->stop = stop;
if (update)
*update = update_start || update_stop;
}
/**
@ -222,6 +240,9 @@ gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
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) {
@ -283,12 +304,22 @@ gint64
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;
}
@ -313,10 +344,17 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
{
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;
}
@ -341,7 +379,11 @@ gst_segment_clip (GstSegment * segment, GstFormat format, gint64 start,
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)

View file

@ -72,7 +72,8 @@ void gst_segment_set_last_stop (GstSegment *segment, GstFormat format, gint64 p
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);

View file

@ -579,81 +579,28 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
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:
@ -669,8 +616,8 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
("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 */
@ -685,28 +632,10 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
", 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++;
@ -917,13 +846,7 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
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);
@ -1004,9 +927,8 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
{
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);
@ -1014,61 +936,27 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
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");
@ -1078,6 +966,13 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
/* 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);
@ -1090,7 +985,7 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
/* 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;
@ -1386,7 +1281,7 @@ gst_base_sink_activate_pull (GstPad * pad, gboolean active)
} 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... */
@ -1467,7 +1362,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
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);
@ -1475,18 +1370,18 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
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);
@ -1547,8 +1442,8 @@ gst_base_sink_query (GstElement * element, GstQuery * query)
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:
@ -1585,15 +1480,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
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:

View file

@ -80,15 +80,7 @@ struct _GstBaseSink {
/*< 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;

View file

@ -229,8 +229,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
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);
@ -411,9 +410,9 @@ gst_base_src_query (GstPad * pad, GstQuery * query)
{
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!.
@ -448,11 +447,11 @@ gst_base_src_default_newsegment (GstBaseSrc * src)
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);
}
@ -471,7 +470,7 @@ gst_base_src_newsegment (GstBaseSrc * src)
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
@ -482,84 +481,20 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
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;
}
@ -567,9 +502,9 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
/* 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
@ -592,13 +527,13 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
* 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
@ -648,11 +583,11 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
* 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
@ -906,16 +841,16 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
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) {
@ -927,8 +862,8 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
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;
@ -1072,11 +1007,11 @@ eos:
{
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 ());
}
@ -1493,9 +1428,7 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
/* 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:
@ -1510,9 +1443,7 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
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:

View file

@ -84,9 +84,7 @@ struct _GstBaseSrc {
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 */

View file

@ -854,6 +854,7 @@ gst_base_transform_prepare_output_buf (GstBaseTransform * trans,
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);
}
@ -1056,13 +1057,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
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);
@ -1076,7 +1071,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
{
GstFormat format;
gdouble rate;
gint64 start, stop, time, duration;
gint64 start, stop, time;
gboolean update;
GST_STREAM_LOCK (pad);
@ -1084,63 +1079,25 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
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;
}
@ -1432,11 +1389,7 @@ gst_base_transform_change_state (GstElement * element,
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:

View file

@ -65,6 +65,7 @@ struct _GstBaseTransform {
guint cache_caps1_size;
GstCaps *cache_caps2;
guint cache_caps2_size;
gboolean have_same_caps;
gboolean delay_configure;
gboolean pending_configure;
@ -73,22 +74,12 @@ struct _GstBaseTransform {
gboolean have_newsegment;
/* MT-protected (with STREAM_LOCK) */
gdouble segment_rate;
gint64 segment_start;
gint64 segment_stop;
gint64 segment_base;
GstSegment segment;
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];
};
GMutex *transform_lock;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
/**
@ -165,15 +156,16 @@ struct _GstBaseTransformClass {
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_in_place (GstBaseTransform *trans,
gboolean in_place);
gboolean gst_base_transform_is_in_place (GstBaseTransform *trans);
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);
GType gst_base_transform_get_type (void);
G_END_DECLS

View file

@ -196,6 +196,7 @@ gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
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);
@ -599,20 +600,16 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event)
}
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:

View file

@ -55,9 +55,7 @@ struct _GstCollectData
GstPad *pad;
GstBuffer *buffer;
guint pos;
gint64 segment_start;
gint64 segment_stop;
gint64 stream_time;
GstSegment segment;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];

View file

@ -324,8 +324,6 @@ static void
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;
@ -687,12 +685,6 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
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++;

View file

@ -96,9 +96,7 @@ struct _GstFakeSrc {
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;

View file

@ -376,8 +376,8 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
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 */

View file

@ -27,13 +27,15 @@ GST_START_TEST (segment_seek_nosize)
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);
@ -41,7 +43,8 @@ GST_START_TEST (segment_seek_nosize)
* 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);
@ -99,7 +102,8 @@ GST_START_TEST (segment_seek_nosize)
/* 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);
@ -107,7 +111,8 @@ GST_START_TEST (segment_seek_nosize)
* 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);
@ -115,7 +120,8 @@ GST_START_TEST (segment_seek_nosize)
* 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);
@ -193,6 +199,7 @@ GST_START_TEST (segment_seek_size)
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);
@ -200,7 +207,8 @@ GST_START_TEST (segment_seek_size)
/* 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);
@ -208,7 +216,8 @@ GST_START_TEST (segment_seek_size)
* 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);
@ -273,7 +282,8 @@ GST_START_TEST (segment_seek_size)
/* 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);
@ -281,14 +291,16 @@ GST_START_TEST (segment_seek_size)
* 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);