gst/base/gstbasesink.*: Correctly parse newsegment info.

Original commit message from CVS:
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_do_sync), (gst_base_sink_query),
(gst_base_sink_change_state):
* gst/base/gstbasesink.h:
Correctly parse newsegment info.
This commit is contained in:
Wim Taymans 2005-10-11 17:32:00 +00:00
parent 593c714746
commit 9decf461f5
3 changed files with 78 additions and 36 deletions

View file

@ -1,3 +1,11 @@
2005-10-11 Wim Taymans <wim@fluendo.com>
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_do_sync), (gst_base_sink_query),
(gst_base_sink_change_state):
* gst/base/gstbasesink.h:
Correctly parse newsegment info.
2005-10-11 Thomas Vander Stichele <thomas at apestaart dot org> 2005-10-11 Thomas Vander Stichele <thomas at apestaart dot org>
* gst/gst.c: (init_post): * gst/gst.c: (init_post):

View file

@ -466,15 +466,19 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
break; break;
case GST_EVENT_NEWSEGMENT: case GST_EVENT_NEWSEGMENT:
{ {
gboolean update;
gdouble rate;
GstFormat format; GstFormat format;
gint64 segment_start; gint64 segment_start;
gint64 segment_stop; gint64 segment_stop;
gboolean update; gint64 segment_time;
GstClockTime duration;
/* the newsegment event is needed to bring the buffer timestamps to the /* the newsegment event is needed to bring the buffer timestamps to the
* stream time and to drop samples outside of the playback segment. */ * stream time and to drop samples outside of the playback segment. */
gst_event_parse_newsegment (event, &update, &basesink->segment_rate, gst_event_parse_newsegment (event, &update, &rate, &format,
&format, &segment_start, &segment_stop, &basesink->segment_base); &segment_start, &segment_stop, &segment_time);
basesink->have_newsegment = TRUE; basesink->have_newsegment = TRUE;
@ -483,53 +487,57 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
if (format != GST_FORMAT_TIME && segment_start == 0) { if (format != GST_FORMAT_TIME && segment_start == 0) {
format = GST_FORMAT_TIME; format = GST_FORMAT_TIME;
segment_stop = -1; segment_stop = -1;
basesink->segment_base = -1; segment_time = -1;
} }
if (format != GST_FORMAT_TIME) { if (format != GST_FORMAT_TIME) {
GST_DEBUG_OBJECT (basesink, GST_DEBUG_OBJECT (basesink,
"received non time %d NEW_SEGMENT %" G_GINT64_FORMAT "received non time %d NEW_SEGMENT %" G_GINT64_FORMAT
" -- %" G_GINT64_FORMAT ", base %" G_GINT64_FORMAT, " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT,
format, basesink->segment_start, basesink->segment_stop, format, segment_start, segment_stop, segment_time);
basesink->segment_base);
/* this means this sink will not be able to clip or drop samples /* this means this sink will not be able to clip or drop samples
* and timestamps have to start from 0. */ * and timestamps have to start from 0. */
basesink->segment_start = -1; basesink->segment_start = -1;
basesink->segment_stop = -1; basesink->segment_stop = -1;
basesink->segment_base = -1; basesink->segment_time = -1;
goto done_newsegment; goto done_newsegment;
} }
/* check if we really have a new segment or the previous one is /* check if we really have a new segment or the previous one is
* closed */ * closed */
if (basesink->segment_start != segment_start) { if (!update) {
/* the new segment has to be aligned with the old segment. /* the new segment has to be aligned with the old segment.
* We first update the accumulated time of the previous * We first update the accumulated time of the previous
* segment. the accumulated time is used when syncing to the * segment. the accumulated time is used when syncing to the
* clock. A flush event sets the accumulated time back to 0 * clock. A flush event sets the accumulated time back to 0
*/ */
if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) { if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
basesink->segment_accum += duration = basesink->segment_stop - basesink->segment_start;
basesink->segment_stop - basesink->segment_start;
} else if (GST_CLOCK_TIME_IS_VALID (basesink->current_end)) { } else if (GST_CLOCK_TIME_IS_VALID (basesink->current_end)) {
/* else use last seen timestamp as segment stop */ /* else use last seen timestamp as segment stop */
basesink->segment_accum += duration = basesink->current_end - basesink->segment_start;
basesink->current_end - basesink->segment_start;
} else { } else {
basesink->segment_accum = 0; duration = 0;
} }
} else {
duration = segment_start - basesink->segment_start;
} }
/* use previous rate to calculate duration */
basesink->segment_accum += (duration / ABS (basesink->segment_rate));
/* then update the current segment */
basesink->segment_rate = rate;
basesink->segment_start = segment_start; basesink->segment_start = segment_start;
basesink->segment_stop = segment_stop; basesink->segment_stop = segment_stop;
basesink->segment_time = segment_time;
GST_DEBUG_OBJECT (basesink, GST_DEBUG_OBJECT (basesink,
"received DISCONT %" GST_TIME_FORMAT " -- %" "received NEWSEGMENT %" GST_TIME_FORMAT " -- %"
GST_TIME_FORMAT ", base %" GST_TIME_FORMAT ", accum %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT ", accum %"
GST_TIME_FORMAT, GST_TIME_FORMAT,
GST_TIME_ARGS (basesink->segment_start), GST_TIME_ARGS (basesink->segment_start),
GST_TIME_ARGS (basesink->segment_stop), GST_TIME_ARGS (basesink->segment_stop),
GST_TIME_ARGS (basesink->segment_base), GST_TIME_ARGS (basesink->segment_time),
GST_TIME_ARGS (basesink->segment_accum)); GST_TIME_ARGS (basesink->segment_accum));
done_newsegment: done_newsegment:
break; break;
@ -1013,6 +1021,13 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
stream_end = (gint64) end; 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; stream_start += basesink->segment_accum;
if (end_valid) if (end_valid)
stream_end += basesink->segment_accum; stream_end += basesink->segment_accum;
@ -1416,7 +1431,7 @@ gst_base_sink_query (GstElement * element, GstQuery * query)
{ {
gst_query_set_segment (query, basesink->segment_rate, gst_query_set_segment (query, basesink->segment_rate,
GST_FORMAT_TIME, basesink->segment_start, basesink->segment_stop, GST_FORMAT_TIME, basesink->segment_start, basesink->segment_stop,
basesink->segment_base); basesink->segment_time);
break; break;
} }
case GST_QUERY_CONVERT: case GST_QUERY_CONVERT:
@ -1459,6 +1474,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
basesink->segment_rate = 1.0; basesink->segment_rate = 1.0;
basesink->segment_start = 0; basesink->segment_start = 0;
basesink->segment_stop = 0; basesink->segment_stop = 0;
basesink->segment_time = 0;
basesink->segment_accum = 0;
ret = GST_STATE_CHANGE_ASYNC; ret = GST_STATE_CHANGE_ASYNC;
break; break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PAUSED_TO_PLAYING:

View file

@ -466,15 +466,19 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
break; break;
case GST_EVENT_NEWSEGMENT: case GST_EVENT_NEWSEGMENT:
{ {
gboolean update;
gdouble rate;
GstFormat format; GstFormat format;
gint64 segment_start; gint64 segment_start;
gint64 segment_stop; gint64 segment_stop;
gboolean update; gint64 segment_time;
GstClockTime duration;
/* the newsegment event is needed to bring the buffer timestamps to the /* the newsegment event is needed to bring the buffer timestamps to the
* stream time and to drop samples outside of the playback segment. */ * stream time and to drop samples outside of the playback segment. */
gst_event_parse_newsegment (event, &update, &basesink->segment_rate, gst_event_parse_newsegment (event, &update, &rate, &format,
&format, &segment_start, &segment_stop, &basesink->segment_base); &segment_start, &segment_stop, &segment_time);
basesink->have_newsegment = TRUE; basesink->have_newsegment = TRUE;
@ -483,53 +487,57 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
if (format != GST_FORMAT_TIME && segment_start == 0) { if (format != GST_FORMAT_TIME && segment_start == 0) {
format = GST_FORMAT_TIME; format = GST_FORMAT_TIME;
segment_stop = -1; segment_stop = -1;
basesink->segment_base = -1; segment_time = -1;
} }
if (format != GST_FORMAT_TIME) { if (format != GST_FORMAT_TIME) {
GST_DEBUG_OBJECT (basesink, GST_DEBUG_OBJECT (basesink,
"received non time %d NEW_SEGMENT %" G_GINT64_FORMAT "received non time %d NEW_SEGMENT %" G_GINT64_FORMAT
" -- %" G_GINT64_FORMAT ", base %" G_GINT64_FORMAT, " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT,
format, basesink->segment_start, basesink->segment_stop, format, segment_start, segment_stop, segment_time);
basesink->segment_base);
/* this means this sink will not be able to clip or drop samples /* this means this sink will not be able to clip or drop samples
* and timestamps have to start from 0. */ * and timestamps have to start from 0. */
basesink->segment_start = -1; basesink->segment_start = -1;
basesink->segment_stop = -1; basesink->segment_stop = -1;
basesink->segment_base = -1; basesink->segment_time = -1;
goto done_newsegment; goto done_newsegment;
} }
/* check if we really have a new segment or the previous one is /* check if we really have a new segment or the previous one is
* closed */ * closed */
if (basesink->segment_start != segment_start) { if (!update) {
/* the new segment has to be aligned with the old segment. /* the new segment has to be aligned with the old segment.
* We first update the accumulated time of the previous * We first update the accumulated time of the previous
* segment. the accumulated time is used when syncing to the * segment. the accumulated time is used when syncing to the
* clock. A flush event sets the accumulated time back to 0 * clock. A flush event sets the accumulated time back to 0
*/ */
if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) { if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
basesink->segment_accum += duration = basesink->segment_stop - basesink->segment_start;
basesink->segment_stop - basesink->segment_start;
} else if (GST_CLOCK_TIME_IS_VALID (basesink->current_end)) { } else if (GST_CLOCK_TIME_IS_VALID (basesink->current_end)) {
/* else use last seen timestamp as segment stop */ /* else use last seen timestamp as segment stop */
basesink->segment_accum += duration = basesink->current_end - basesink->segment_start;
basesink->current_end - basesink->segment_start;
} else { } else {
basesink->segment_accum = 0; duration = 0;
} }
} else {
duration = segment_start - basesink->segment_start;
} }
/* use previous rate to calculate duration */
basesink->segment_accum += (duration / ABS (basesink->segment_rate));
/* then update the current segment */
basesink->segment_rate = rate;
basesink->segment_start = segment_start; basesink->segment_start = segment_start;
basesink->segment_stop = segment_stop; basesink->segment_stop = segment_stop;
basesink->segment_time = segment_time;
GST_DEBUG_OBJECT (basesink, GST_DEBUG_OBJECT (basesink,
"received DISCONT %" GST_TIME_FORMAT " -- %" "received NEWSEGMENT %" GST_TIME_FORMAT " -- %"
GST_TIME_FORMAT ", base %" GST_TIME_FORMAT ", accum %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT ", accum %"
GST_TIME_FORMAT, GST_TIME_FORMAT,
GST_TIME_ARGS (basesink->segment_start), GST_TIME_ARGS (basesink->segment_start),
GST_TIME_ARGS (basesink->segment_stop), GST_TIME_ARGS (basesink->segment_stop),
GST_TIME_ARGS (basesink->segment_base), GST_TIME_ARGS (basesink->segment_time),
GST_TIME_ARGS (basesink->segment_accum)); GST_TIME_ARGS (basesink->segment_accum));
done_newsegment: done_newsegment:
break; break;
@ -1013,6 +1021,13 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
stream_end = (gint64) end; 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; stream_start += basesink->segment_accum;
if (end_valid) if (end_valid)
stream_end += basesink->segment_accum; stream_end += basesink->segment_accum;
@ -1416,7 +1431,7 @@ gst_base_sink_query (GstElement * element, GstQuery * query)
{ {
gst_query_set_segment (query, basesink->segment_rate, gst_query_set_segment (query, basesink->segment_rate,
GST_FORMAT_TIME, basesink->segment_start, basesink->segment_stop, GST_FORMAT_TIME, basesink->segment_start, basesink->segment_stop,
basesink->segment_base); basesink->segment_time);
break; break;
} }
case GST_QUERY_CONVERT: case GST_QUERY_CONVERT:
@ -1459,6 +1474,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
basesink->segment_rate = 1.0; basesink->segment_rate = 1.0;
basesink->segment_start = 0; basesink->segment_start = 0;
basesink->segment_stop = 0; basesink->segment_stop = 0;
basesink->segment_time = 0;
basesink->segment_accum = 0;
ret = GST_STATE_CHANGE_ASYNC; ret = GST_STATE_CHANGE_ASYNC;
break; break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PAUSED_TO_PLAYING: