mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 13:06:23 +00:00
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:
parent
9409e07440
commit
a35882df1f
28 changed files with 361 additions and 788 deletions
34
ChangeLog
34
ChangeLog
|
@ -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):
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
--------------
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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++;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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++;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue