summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d3ffeea)
raw | patch | inline | side by side (parent: d3ffeea)
author | Wim Taymans <wim.taymans@gmail.com> | |
Sat, 16 Jul 2005 14:41:25 +0000 (14:41 +0000) | ||
committer | Wim Taymans <wim.taymans@gmail.com> | |
Sat, 16 Jul 2005 14:41:25 +0000 (14:41 +0000) |
Original commit message from CVS:
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_event), (gst_base_sink_get_times),
(gst_base_sink_do_sync), (gst_base_sink_change_state):
* gst/base/gstbasesink.h:
Store and use discont values when syncing buffers as described
in design docs.
* gst/base/gstbasesrc.c: (gst_base_src_send_discont),
(gst_base_src_do_seek), (gst_base_src_loop), (gst_base_src_start),
(gst_base_src_activate_push):
Push discont event when starting.
* gst/elements/gstidentity.c: (gst_identity_transform):
Small cleanups.
* gst/gstbin.c: (gst_bin_change_state):
Small cleanups in base_time distribution.
* gst/gstelement.c: (gst_element_set_base_time),
(gst_element_get_base_time), (gst_element_change_state):
* gst/gstelement.h:
Added methods for the base_time of the element.
Some MT fixes.
* gst/gstpipeline.c: (gst_pipeline_send_event),
(gst_pipeline_change_state), (gst_pipeline_set_new_stream_time),
(gst_pipeline_get_last_stream_time):
* gst/gstpipeline.h:
MT fixes.
Handle seeking as described in design doc, remove stream_time
hack.
Cleanups clock and stream_time selection code. Added accessors
for the stream_time.
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_event), (gst_base_sink_get_times),
(gst_base_sink_do_sync), (gst_base_sink_change_state):
* gst/base/gstbasesink.h:
Store and use discont values when syncing buffers as described
in design docs.
* gst/base/gstbasesrc.c: (gst_base_src_send_discont),
(gst_base_src_do_seek), (gst_base_src_loop), (gst_base_src_start),
(gst_base_src_activate_push):
Push discont event when starting.
* gst/elements/gstidentity.c: (gst_identity_transform):
Small cleanups.
* gst/gstbin.c: (gst_bin_change_state):
Small cleanups in base_time distribution.
* gst/gstelement.c: (gst_element_set_base_time),
(gst_element_get_base_time), (gst_element_change_state):
* gst/gstelement.h:
Added methods for the base_time of the element.
Some MT fixes.
* gst/gstpipeline.c: (gst_pipeline_send_event),
(gst_pipeline_change_state), (gst_pipeline_set_new_stream_time),
(gst_pipeline_get_last_stream_time):
* gst/gstpipeline.h:
MT fixes.
Handle seeking as described in design doc, remove stream_time
hack.
Cleanups clock and stream_time selection code. Added accessors
for the stream_time.
14 files changed:
diff --git a/ChangeLog b/ChangeLog
index 054ef8c6d3aa27e4e01b53400557dc0d35b40ea6..4a40454b8fe2ca8a3ed47e870626d8a2045ee8d1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+2005-07-16 Wim Taymans <wim@fluendo.com>
+
+ * gst/base/gstbasesink.c: (gst_base_sink_handle_object),
+ (gst_base_sink_event), (gst_base_sink_get_times),
+ (gst_base_sink_do_sync), (gst_base_sink_change_state):
+ * gst/base/gstbasesink.h:
+ Store and use discont values when syncing buffers as described
+ in design docs.
+
+ * gst/base/gstbasesrc.c: (gst_base_src_send_discont),
+ (gst_base_src_do_seek), (gst_base_src_loop), (gst_base_src_start),
+ (gst_base_src_activate_push):
+ Push discont event when starting.
+
+ * gst/elements/gstidentity.c: (gst_identity_transform):
+ Small cleanups.
+
+ * gst/gstbin.c: (gst_bin_change_state):
+ Small cleanups in base_time distribution.
+
+ * gst/gstelement.c: (gst_element_set_base_time),
+ (gst_element_get_base_time), (gst_element_change_state):
+ * gst/gstelement.h:
+ Added methods for the base_time of the element.
+ Some MT fixes.
+
+ * gst/gstpipeline.c: (gst_pipeline_send_event),
+ (gst_pipeline_change_state), (gst_pipeline_set_new_stream_time),
+ (gst_pipeline_get_last_stream_time):
+ * gst/gstpipeline.h:
+ MT fixes.
+ Handle seeking as described in design doc, remove stream_time
+ hack.
+ Cleanups clock and stream_time selection code. Added accessors
+ for the stream_time.
+
+
2005-07-16 Andy Wingo <wingo@pobox.com>
* gst/gsterror.c (_gst_core_errors_init): Use the magic word..
diff --git a/gst/base/gstbasesink.c b/gst/base/gstbasesink.c
index ae7d15731c87b8188007532cb051edc932814d3f..47945ca324a298782d3b2c57d2991e2cc219effe 100644 (file)
--- a/gst/base/gstbasesink.c
+++ b/gst/base/gstbasesink.c
have_event = GST_IS_EVENT (obj);
if (have_event) {
+ GstEvent *event = GST_EVENT (obj);
+
switch (GST_EVENT_TYPE (obj)) {
case GST_EVENT_EOS:
basesink->preroll_queued++;
basesink->eos = TRUE;
break;
+ case GST_EVENT_DISCONTINUOUS:
+ /* the discont event is needed to bring the buffer timestamps to the
+ * stream time */
+ if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
+ &basesink->discont_start, &basesink->discont_stop)) {
+ basesink->discont_start = 0;
+ basesink->discont_stop = 0;
+ }
+ basesink->have_discont = TRUE;
+
+ GST_DEBUG ("received DISCONT %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
+ GST_TIME_ARGS (basesink->discont_start),
+ GST_TIME_ARGS (basesink->discont_stop));
+ break;
default:
break;
}
basesink->events_queued++;
} else {
+ if (!basesink->have_discont) {
+ GST_ELEMENT_ERROR (basesink, STREAM, STOPPED,
+ ("received buffer without a discont"),
+ ("received buffer without a discont"));
+ }
basesink->preroll_queued++;
basesink->buffers_queued++;
}
GstFlowReturn ret;
GST_STREAM_LOCK (pad);
- if (basesink->clock) {
- //gint64 value = GST_EVENT_DISCONT_OFFSET (event, 0).value;
- }
ret =
gst_base_sink_handle_object (basesink, pad, GST_MINI_OBJECT (event));
GST_STREAM_UNLOCK (pad);
}
/* default implementation to calculate the start and end
- * timestamps on a buffer, subclasses cna override
+ * timestamps on a buffer, subclasses can override
*/
static void
gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
timestamp = GST_BUFFER_TIMESTAMP (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+ /* bring timestamp to stream time using last
+ * discont offset. */
+ timestamp -= basesink->discont_start;
+ /* get duration to calculate end time */
duration = GST_BUFFER_DURATION (buffer);
if (GST_CLOCK_TIME_IS_VALID (duration)) {
*end = timestamp + duration;
if (GST_CLOCK_TIME_IS_VALID (start)) {
GstClockReturn ret;
+ GstClockTime base_time;
- /* save clock id so that we can unlock it if needed */
GST_LOCK (basesink);
+ base_time = GST_ELEMENT (basesink)->base_time;
+
+ GST_LOG_OBJECT (basesink,
+ "waiting for clock, base time %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (base_time));
+ /* save clock id so that we can unlock it if needed */
basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
- start + GST_ELEMENT (basesink)->base_time);
+ start + base_time);
basesink->end_time = end;
GST_UNLOCK (basesink);
basesink->have_preroll = FALSE;
basesink->need_preroll = TRUE;
GST_PREROLL_UNLOCK (basesink->sinkpad);
+ basesink->have_discont = FALSE;
+ basesink->discont_start = 0;
+ basesink->discont_stop = 0;
ret = GST_STATE_ASYNC;
break;
case GST_STATE_PAUSED_TO_PLAYING:
diff --git a/gst/base/gstbasesink.h b/gst/base/gstbasesink.h
index 312d7c4b883fd8ca575fc4f3b1d586a7c8ae1b60..c7fc83e4d6a791ffbaf9885dbae8d0d8c0fc7662 100644 (file)
--- a/gst/base/gstbasesink.h
+++ b/gst/base/gstbasesink.h
GstClockID clock_id;
GstClockTime end_time;
+ gboolean have_discont;
+ GstClockTime discont_start;
+ GstClockTime discont_stop;
+
gboolean eos;
gboolean need_preroll;
gboolean have_preroll;
diff --git a/gst/base/gstbasesrc.c b/gst/base/gstbasesrc.c
index 88720a0a5ee1b43bd6cf3e97181443c2f6e00697..f866bf0a32e37ebfc69d43596bd9b621f33d4536 100644 (file)
--- a/gst/base/gstbasesrc.c
+++ b/gst/base/gstbasesrc.c
}
#endif
+static gboolean
+gst_base_src_send_discont (GstBaseSrc * src)
+{
+ GstEvent *event;
+
+ event = gst_event_new_discontinuous (1.0,
+ GST_FORMAT_BYTES,
+ (gint64) src->segment_start, (gint64) src->segment_end, NULL);
+
+ return gst_pad_push_event (src->srcpad, event);
+}
+
static gboolean
gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
{
gst_pad_push_event (src->srcpad, gst_event_new_flush (TRUE));
/* now send discont */
- {
- GstEvent *event;
-
- event = gst_event_new_discontinuous (1.0,
- GST_FORMAT_BYTES,
- (gint64) src->segment_start, (gint64) src->segment_end, NULL);
-
- gst_pad_push_event (src->srcpad, event);
- }
+ gst_base_src_send_discont (src);
/* and restart the task */
gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
GST_DEBUG ("size %d %lld", result, basesrc->size);
/* we always run to the end */
- basesrc->segment_end = -1;
+ basesrc->segment_end = basesrc->size;
/* check if we can seek, updates ->seekable */
gst_base_src_is_seekable (basesrc);
if (!gst_base_src_start (basesrc))
goto error_start;
+ /* now send discont */
+ gst_base_src_send_discont (basesrc);
+
return gst_pad_start_task (pad, (GstTaskFunction) gst_base_src_loop, pad);
} else {
return gst_base_src_deactivate (basesrc, pad);
index f73015dbe840e1a192380d151dd83ca05963d53b..090f6514e28bff5c437e7a2f59f641afea9280da 100644 (file)
if (identity->sync) {
GstClock *clock;
- GstClockReturn cret;
- clock = GST_ELEMENT (identity)->clock;
+ GST_LOCK (identity);
+ if ((clock = GST_ELEMENT (identity)->clock)) {
+ GstClockReturn cret;
- if (clock) {
/* save id if we need to unlock */
- /* FIXME: actually unlock this somewhere if the state changes */
- GST_LOCK (identity);
+ /* FIXME: actually unlock this somewhere in the state changes */
identity->clock_id = gst_clock_new_single_shot_id (clock,
GST_BUFFER_TIMESTAMP (outbuf) + GST_ELEMENT (identity)->base_time);
GST_UNLOCK (identity);
+
cret = gst_clock_id_wait (identity->clock_id, NULL);
+
GST_LOCK (identity);
if (identity->clock_id) {
gst_clock_id_unref (identity->clock_id);
identity->clock_id = NULL;
}
- GST_UNLOCK (identity);
if (cret == GST_CLOCK_UNSCHEDULED)
ret = GST_FLOW_UNEXPECTED;
}
+ GST_UNLOCK (identity);
}
identity->offset += GST_BUFFER_SIZE (outbuf);
diff --git a/gst/gstbin.c b/gst/gstbin.c
index e2b6bd3c4542467f52d98664bec72596d7eba863..5a38c6402ff90da1e3804ca8de75d526f21e1dbf 100644 (file)
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
GQueue *elem_queue; /* list of elements waiting for a state change */
GQueue *semi_queue; /* list of elements with no connected srcpads */
GQueue *temp; /* queue of leftovers */
+ GstClockTime base_time;
bin = GST_BIN (element);
GST_LOCK (bin);
restart:
+ /* take base time */
+ base_time = element->base_time;
+
/* make sure queues are empty, they could be filled when
* restarting. */
clear_queue (elem_queue, TRUE);
goto next_element;
/* set base time on element */
- qelement->base_time = element->base_time;
+ gst_element_set_base_time (qelement, base_time);
+
+ /* then change state */
ret = gst_element_set_state (qelement, pending);
/* the set state could have cause elements to be added/removed,
diff --git a/gst/gstelement.c b/gst/gstelement.c
index 544da34d458076916d8e558949e532ec7b7714e3..3d5698d3c76eaa34af6c3f284480d58937998fc3 100644 (file)
--- a/gst/gstelement.c
+++ b/gst/gstelement.c
return NULL;
}
+/**
+ * gst_element_set_base_time:
+ * @element: a #GstElement.
+ * @time: the base time to set.
+ *
+ * Set the base time of an element. See @gst_element_get_base_time().
+ *
+ * MT safe.
+ */
+void
+gst_element_set_base_time (GstElement * element, GstClockTime time)
+{
+ g_return_if_fail (GST_IS_ELEMENT (element));
+
+ GST_LOCK (element);
+ element->base_time = time;
+ GST_UNLOCK (element);
+}
+
+/**
+ * gst_element_get_base_time:
+ * @element: a #GstElement.
+ *
+ * Returns the base time of the element. The base time is the
+ * absolute time of the clock when this element was last put to
+ * PLAYING. Substracting the base time from the clock time gives
+ * the stream time of the element.
+ *
+ * Returns: the base time of the element.
+ *
+ * MT safe.
+ */
+GstClockTime
+gst_element_get_base_time (GstElement * element)
+{
+ GstClockTime result;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
+
+ GST_LOCK (element);
+ result = element->base_time;
+ GST_UNLOCK (element);
+
+ return result;
+}
+
#ifndef GST_DISABLE_INDEX
/**
* gst_element_is_indexable:
}
break;
case GST_STATE_PAUSED_TO_PLAYING:
+ /* FIXME really needed? */
GST_LOCK (element);
if (GST_ELEMENT_MANAGER (element)) {
element->base_time =
if (!gst_element_pads_activate (element, FALSE)) {
result = GST_STATE_FAILURE;
} else {
+ GST_LOCK (element);
element->base_time = 0;
+ GST_UNLOCK (element);
}
break;
default:
diff --git a/gst/gstelement.h b/gst/gstelement.h
index d9b3d9fd2552a6df6f5692f5eab90112461c17fa..98c6385bb45018226c7f838cda2bc167f58148ff 100644 (file)
--- a/gst/gstelement.h
+++ b/gst/gstelement.h
gboolean gst_element_provides_clock (GstElement *element);
GstClock* gst_element_get_clock (GstElement *element);
void gst_element_set_clock (GstElement *element, GstClock *clock);
+void gst_element_set_base_time (GstElement *element, GstClockTime time);
+GstClockTime gst_element_get_base_time (GstElement *element);
/* indexes */
gboolean gst_element_is_indexable (GstElement *element);
diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c
index 6c0ad24ef3c5c7e7344dfa579f58c08cb3f2dfb5..421aa9def089ffafa3b76fe33ed5679197871cae 100644 (file)
--- a/gst/gstpipeline.c
+++ b/gst/gstpipeline.c
GstElementState state;
GstEventType event_type = GST_EVENT_TYPE (event);
GTimeVal timeout;
- gint64 offset = -1;
/* need to call _get_state() since a bin state is only updated
* with this call. */
was_playing = state == GST_STATE_PLAYING;
if (event_type == GST_EVENT_SEEK) {
- if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_TIME) {
- GST_WARNING ("Pipelines only accept seek events with TIME format");
- g_warning ("Pipelines only accept seek events with TIME format");
- return FALSE;
- }
- offset = GST_EVENT_SEEK_OFFSET (event);
if (was_playing)
gst_element_set_state (element, GST_STATE_PAUSED);
}
if (res && event_type == GST_EVENT_SEEK) {
/* need to set the stream time to the seek time */
- GST_PIPELINE (element)->stream_time = offset;
+ gst_pipeline_set_new_stream_time (GST_PIPELINE (element), 0);
if (was_playing)
gst_element_set_state (element, GST_STATE_PLAYING);
}
GstElementStateReturn result = GST_STATE_SUCCESS;
GstPipeline *pipeline = GST_PIPELINE (element);
gint transition = GST_STATE_TRANSITION (element);
+ GstClock *clock;
switch (transition) {
case GST_STATE_NULL_TO_READY:
+ GST_LOCK (element);
if (element->bus)
gst_bus_set_flushing (element->bus, FALSE);
+ GST_UNLOCK (element);
gst_scheduler_setup (GST_ELEMENT_SCHEDULER (pipeline));
break;
case GST_STATE_READY_TO_PAUSED:
- {
- GstClock *clock;
-
- clock = gst_element_get_clock (element);
- gst_element_set_clock (element, clock);
- gst_object_unref (clock);
break;
- }
case GST_STATE_PAUSED_TO_PLAYING:
- if (element->clock) {
- GstClockTime start_time = gst_clock_get_time (element->clock);
+ /* when going to playing, select a clock */
+ if ((clock = gst_element_get_clock (element))) {
+ GstClockTime start_time;
+
+ /* distribute the clock */
+ gst_element_set_clock (element, clock);
+
+ /* get start time */
+ start_time = gst_clock_get_time (clock);
+ gst_object_unref (clock);
+ GST_LOCK (element);
element->base_time = start_time -
pipeline->stream_time + pipeline->delay;
GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", start_time=%"
GST_TIME_FORMAT ", base time %" GST_TIME_FORMAT,
GST_TIME_ARGS (pipeline->stream_time),
GST_TIME_ARGS (start_time), GST_TIME_ARGS (element->base_time));
+ GST_UNLOCK (element);
} else {
- element->base_time = 0;
+ GST_UNLOCK (element);
GST_DEBUG ("no clock, using base time of 0");
+ gst_element_set_base_time (element, 0);
}
break;
case GST_STATE_PLAYING_TO_PAUSED:
switch (transition) {
case GST_STATE_READY_TO_PAUSED:
- pipeline->stream_time = 0;
+ gst_pipeline_set_new_stream_time (pipeline, 0);
break;
case GST_STATE_PAUSED_TO_PLAYING:
break;
case GST_STATE_PLAYING_TO_PAUSED:
- if (element->clock) {
+ GST_LOCK (element);
+ if ((clock = element->clock)) {
GstClockTime now;
- now = gst_clock_get_time (element->clock);
+ gst_object_ref (clock);
+ GST_UNLOCK (element);
+
+ /* calculate the time when we stopped */
+ now = gst_clock_get_time (clock);
+ gst_object_unref (clock);
+
+ GST_LOCK (element);
+ /* store the current stream time */
pipeline->stream_time = now - element->base_time;
GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
", base time %" GST_TIME_FORMAT,
GST_TIME_ARGS (pipeline->stream_time),
GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time));
}
+ GST_UNLOCK (element);
break;
case GST_STATE_PAUSED_TO_READY:
break;
case GST_STATE_READY_TO_NULL:
+ GST_LOCK (element);
if (element->bus) {
gst_bus_set_flushing (element->bus, TRUE);
}
+ GST_UNLOCK (element);
break;
}
return gst_element_get_bus (GST_ELEMENT (pipeline));
}
+/**
+ * gst_pipeline_set_new_stream_time:
+ * @pipeline: the pipeline
+ *
+ * Set the new stream time of the pipeline. The stream time is used to
+ * set the base time on the elements (see @gst_element_set_base_time())
+ * in the PAUSED->PLAYING state transition.
+ *
+ * MT safe.
+ */
+void
+gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time)
+{
+ g_return_if_fail (GST_IS_PIPELINE (pipeline));
+
+ GST_LOCK (pipeline);
+ pipeline->stream_time = time;
+ GST_DEBUG ("%s: set new stream_time to %" GST_TIME_FORMAT,
+ GST_ELEMENT_NAME (pipeline), time);
+ GST_UNLOCK (pipeline);
+}
+
+/**
+ * gst_pipeline_get_last_stream_time:
+ * @pipeline: the pipeline
+ *
+ * Gets the last stream time of the pipeline. If the pipeline is PLAYING,
+ * the returned time is the stream time used to configure the elements
+ * in the PAUSED->PLAYING state. If the pipeline is PAUSED, the returned
+ * time is the stream time when the pipeline was paused.
+ *
+ * Returns: a GstClockTime
+ *
+ * MT safe.
+ */
+GstClockTime
+gst_pipeline_get_last_stream_time (GstPipeline * pipeline)
+{
+ GstClockTime result;
+
+ g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);
+
+ GST_LOCK (pipeline);
+ result = pipeline->stream_time;
+ GST_UNLOCK (pipeline);
+
+ return result;
+}
+
static GstClock *
gst_pipeline_get_clock_func (GstElement * element)
{
diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h
index 2f3cdae4276d1b7de1e3e3ed5488d7bcda28af6a..014106161386b840c300cf106ab26edae3e88d76 100644 (file)
--- a/gst/gstpipeline.h
+++ b/gst/gstpipeline.h
GstScheduler* gst_pipeline_get_scheduler (GstPipeline *pipeline);
GstBus* gst_pipeline_get_bus (GstPipeline *pipeline);
+void gst_pipeline_set_new_stream_time (GstPipeline *pipeline, GstClockTime time);
+GstClockTime gst_pipeline_get_last_stream_time (GstPipeline *pipeline);
+
void gst_pipeline_use_clock (GstPipeline *pipeline, GstClock *clock);
void gst_pipeline_set_clock (GstPipeline *pipeline, GstClock *clock);
GstClock* gst_pipeline_get_clock (GstPipeline *pipeline);
index ae7d15731c87b8188007532cb051edc932814d3f..47945ca324a298782d3b2c57d2991e2cc219effe 100644 (file)
have_event = GST_IS_EVENT (obj);
if (have_event) {
+ GstEvent *event = GST_EVENT (obj);
+
switch (GST_EVENT_TYPE (obj)) {
case GST_EVENT_EOS:
basesink->preroll_queued++;
basesink->eos = TRUE;
break;
+ case GST_EVENT_DISCONTINUOUS:
+ /* the discont event is needed to bring the buffer timestamps to the
+ * stream time */
+ if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
+ &basesink->discont_start, &basesink->discont_stop)) {
+ basesink->discont_start = 0;
+ basesink->discont_stop = 0;
+ }
+ basesink->have_discont = TRUE;
+
+ GST_DEBUG ("received DISCONT %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
+ GST_TIME_ARGS (basesink->discont_start),
+ GST_TIME_ARGS (basesink->discont_stop));
+ break;
default:
break;
}
basesink->events_queued++;
} else {
+ if (!basesink->have_discont) {
+ GST_ELEMENT_ERROR (basesink, STREAM, STOPPED,
+ ("received buffer without a discont"),
+ ("received buffer without a discont"));
+ }
basesink->preroll_queued++;
basesink->buffers_queued++;
}
GstFlowReturn ret;
GST_STREAM_LOCK (pad);
- if (basesink->clock) {
- //gint64 value = GST_EVENT_DISCONT_OFFSET (event, 0).value;
- }
ret =
gst_base_sink_handle_object (basesink, pad, GST_MINI_OBJECT (event));
GST_STREAM_UNLOCK (pad);
}
/* default implementation to calculate the start and end
- * timestamps on a buffer, subclasses cna override
+ * timestamps on a buffer, subclasses can override
*/
static void
gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
timestamp = GST_BUFFER_TIMESTAMP (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+ /* bring timestamp to stream time using last
+ * discont offset. */
+ timestamp -= basesink->discont_start;
+ /* get duration to calculate end time */
duration = GST_BUFFER_DURATION (buffer);
if (GST_CLOCK_TIME_IS_VALID (duration)) {
*end = timestamp + duration;
if (GST_CLOCK_TIME_IS_VALID (start)) {
GstClockReturn ret;
+ GstClockTime base_time;
- /* save clock id so that we can unlock it if needed */
GST_LOCK (basesink);
+ base_time = GST_ELEMENT (basesink)->base_time;
+
+ GST_LOG_OBJECT (basesink,
+ "waiting for clock, base time %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (base_time));
+ /* save clock id so that we can unlock it if needed */
basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
- start + GST_ELEMENT (basesink)->base_time);
+ start + base_time);
basesink->end_time = end;
GST_UNLOCK (basesink);
basesink->have_preroll = FALSE;
basesink->need_preroll = TRUE;
GST_PREROLL_UNLOCK (basesink->sinkpad);
+ basesink->have_discont = FALSE;
+ basesink->discont_start = 0;
+ basesink->discont_stop = 0;
ret = GST_STATE_ASYNC;
break;
case GST_STATE_PAUSED_TO_PLAYING:
index 312d7c4b883fd8ca575fc4f3b1d586a7c8ae1b60..c7fc83e4d6a791ffbaf9885dbae8d0d8c0fc7662 100644 (file)
GstClockID clock_id;
GstClockTime end_time;
+ gboolean have_discont;
+ GstClockTime discont_start;
+ GstClockTime discont_stop;
+
gboolean eos;
gboolean need_preroll;
gboolean have_preroll;
index 88720a0a5ee1b43bd6cf3e97181443c2f6e00697..f866bf0a32e37ebfc69d43596bd9b621f33d4536 100644 (file)
}
#endif
+static gboolean
+gst_base_src_send_discont (GstBaseSrc * src)
+{
+ GstEvent *event;
+
+ event = gst_event_new_discontinuous (1.0,
+ GST_FORMAT_BYTES,
+ (gint64) src->segment_start, (gint64) src->segment_end, NULL);
+
+ return gst_pad_push_event (src->srcpad, event);
+}
+
static gboolean
gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
{
gst_pad_push_event (src->srcpad, gst_event_new_flush (TRUE));
/* now send discont */
- {
- GstEvent *event;
-
- event = gst_event_new_discontinuous (1.0,
- GST_FORMAT_BYTES,
- (gint64) src->segment_start, (gint64) src->segment_end, NULL);
-
- gst_pad_push_event (src->srcpad, event);
- }
+ gst_base_src_send_discont (src);
/* and restart the task */
gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
GST_DEBUG ("size %d %lld", result, basesrc->size);
/* we always run to the end */
- basesrc->segment_end = -1;
+ basesrc->segment_end = basesrc->size;
/* check if we can seek, updates ->seekable */
gst_base_src_is_seekable (basesrc);
if (!gst_base_src_start (basesrc))
goto error_start;
+ /* now send discont */
+ gst_base_src_send_discont (basesrc);
+
return gst_pad_start_task (pad, (GstTaskFunction) gst_base_src_loop, pad);
} else {
return gst_base_src_deactivate (basesrc, pad);
index f73015dbe840e1a192380d151dd83ca05963d53b..090f6514e28bff5c437e7a2f59f641afea9280da 100644 (file)
if (identity->sync) {
GstClock *clock;
- GstClockReturn cret;
- clock = GST_ELEMENT (identity)->clock;
+ GST_LOCK (identity);
+ if ((clock = GST_ELEMENT (identity)->clock)) {
+ GstClockReturn cret;
- if (clock) {
/* save id if we need to unlock */
- /* FIXME: actually unlock this somewhere if the state changes */
- GST_LOCK (identity);
+ /* FIXME: actually unlock this somewhere in the state changes */
identity->clock_id = gst_clock_new_single_shot_id (clock,
GST_BUFFER_TIMESTAMP (outbuf) + GST_ELEMENT (identity)->base_time);
GST_UNLOCK (identity);
+
cret = gst_clock_id_wait (identity->clock_id, NULL);
+
GST_LOCK (identity);
if (identity->clock_id) {
gst_clock_id_unref (identity->clock_id);
identity->clock_id = NULL;
}
- GST_UNLOCK (identity);
if (cret == GST_CLOCK_UNSCHEDULED)
ret = GST_FLOW_UNEXPECTED;
}
+ GST_UNLOCK (identity);
}
identity->offset += GST_BUFFER_SIZE (outbuf);