summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2005-01-04 12:08:22 +0000
committerWim Taymans <wim.taymans@gmail.com>2005-01-04 12:08:22 +0000
commitdc7434a40b3a39079cc4247e8c213cec8abe48c6 (patch)
tree666840ce004da4c0c8f54a290e85e9ee6b8a1262
parentc678ed9394644c87912e29ab77b8111489b9caff (diff)
downloadgstreamer-plugins-base-dc7434a40b3a39079cc4247e8c213cec8abe48c6.tar.gz
Implement flushing.
Original commit message from CVS: * examples/seeking/seek.c: (dynamic_link), (make_vorbis_pipeline), (make_theora_pipeline), (do_seek), (start_seek), (stop_seek): * ext/ogg/gstoggdemux.c: (gst_ogg_pad_get_type), (gst_ogg_pad_init), (gst_ogg_pad_src_query), (gst_ogg_pad_event), (gst_ogg_demux_factory_filter), (compare_ranks), (gst_ogg_pad_internal_chain), (gst_ogg_pad_typefind), (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_chain_new), (gst_ogg_chain_free), (gst_ogg_chain_new_stream), (gst_ogg_chain_get_stream), (gst_ogg_chain_has_stream), (gst_ogg_demux_base_init), (gst_ogg_demux_init), (gst_ogg_demux_submit_buffer), (gst_ogg_demux_seek), (gst_ogg_demux_get_data), (gst_ogg_demux_get_next_page), (gst_ogg_demux_get_prev_page), (gst_ogg_demux_perform_seek), (gst_ogg_demux_bisect_forward_serialno), (gst_ogg_demux_read_chain), (gst_ogg_demux_read_end_chain), (gst_ogg_demux_find_pad), (gst_ogg_demux_find_chains), (gst_ogg_demux_chain_unlocked), (gst_ogg_demux_chain), (gst_ogg_demux_loop), (gst_ogg_demux_sink_activate), (gst_ogg_print): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_sink_link), (gst_xvimagesink_event), (gst_xvimagesink_show_frame), (gst_xvimagesink_finish_preroll), (gst_xvimagesink_chain), (gst_xvimagesink_buffer_alloc): * sys/xvimage/xvimagesink.h: Implement flushing. Improved seeking in ogg.
-rw-r--r--ChangeLog30
-rw-r--r--examples/seeking/seek.c34
-rw-r--r--ext/ogg/gstoggdemux.c151
-rw-r--r--sys/xvimage/xvimagesink.c151
-rw-r--r--sys/xvimage/xvimagesink.h1
-rw-r--r--tests/examples/seek/seek.c34
6 files changed, 322 insertions, 79 deletions
diff --git a/ChangeLog b/ChangeLog
index 0bfb5e960..54a2c8a9f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2005-01-04 Wim Taymans <wim@fluendo.com>
+
+ * examples/seeking/seek.c: (dynamic_link), (make_vorbis_pipeline),
+ (make_theora_pipeline), (do_seek), (start_seek), (stop_seek):
+ * ext/ogg/gstoggdemux.c: (gst_ogg_pad_get_type),
+ (gst_ogg_pad_init), (gst_ogg_pad_src_query), (gst_ogg_pad_event),
+ (gst_ogg_demux_factory_filter), (compare_ranks),
+ (gst_ogg_pad_internal_chain), (gst_ogg_pad_typefind),
+ (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page),
+ (gst_ogg_chain_new), (gst_ogg_chain_free),
+ (gst_ogg_chain_new_stream), (gst_ogg_chain_get_stream),
+ (gst_ogg_chain_has_stream), (gst_ogg_demux_base_init),
+ (gst_ogg_demux_init), (gst_ogg_demux_submit_buffer),
+ (gst_ogg_demux_seek), (gst_ogg_demux_get_data),
+ (gst_ogg_demux_get_next_page), (gst_ogg_demux_get_prev_page),
+ (gst_ogg_demux_perform_seek),
+ (gst_ogg_demux_bisect_forward_serialno),
+ (gst_ogg_demux_read_chain), (gst_ogg_demux_read_end_chain),
+ (gst_ogg_demux_find_pad), (gst_ogg_demux_find_chains),
+ (gst_ogg_demux_chain_unlocked), (gst_ogg_demux_chain),
+ (gst_ogg_demux_loop), (gst_ogg_demux_sink_activate),
+ (gst_ogg_print):
+ * sys/xvimage/xvimagesink.c: (gst_xvimagesink_sink_link),
+ (gst_xvimagesink_event), (gst_xvimagesink_show_frame),
+ (gst_xvimagesink_finish_preroll), (gst_xvimagesink_chain),
+ (gst_xvimagesink_buffer_alloc):
+ * sys/xvimage/xvimagesink.h:
+ Implement flushing.
+ Improved seeking in ogg.
+
2004-12-31 Wim Taymans <wim@fluendo.com>
* examples/seeking/seek.c: (dynamic_link), (make_vorbis_pipeline),
diff --git a/examples/seeking/seek.c b/examples/seeking/seek.c
index 8a2b5083b..a1d29b107 100644
--- a/examples/seeking/seek.c
+++ b/examples/seeking/seek.c
@@ -17,6 +17,7 @@ static gboolean elem_seek = FALSE;
static gboolean verbose = FALSE;
static guint update_id;
+static gulong changed_id;
//#define SOURCE "gnomevfssrc"
#define SOURCE "filesrc"
@@ -847,16 +848,7 @@ update_scale (gpointer data)
}
static gboolean
-start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
-{
- gst_element_set_state (pipeline, GST_STATE_PAUSED);
- gtk_timeout_remove (update_id);
-
- return FALSE;
-}
-
-static gboolean
-stop_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
+do_seek (GtkWidget * widget, gpointer user_data)
{
gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100;
gboolean res;
@@ -896,6 +888,28 @@ stop_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
}
}
+ GST_PIPELINE (pipeline)->stream_time = real;
+
+ return FALSE;
+}
+
+static gboolean
+start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
+{
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ gtk_timeout_remove (update_id);
+
+ changed_id = gtk_signal_connect (GTK_OBJECT (hscale),
+ "value_changed", G_CALLBACK (do_seek), pipeline);
+
+ return FALSE;
+}
+
+static gboolean
+stop_seek (GtkWidget * widget, gpointer user_data)
+{
+ g_signal_handler_disconnect (GTK_OBJECT (hscale), changed_id);
+
gst_element_set_state (pipeline, GST_STATE_PLAYING);
update_id =
gtk_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline);
diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c
index 35ef43548..90fcc5bd3 100644
--- a/ext/ogg/gstoggdemux.c
+++ b/ext/ogg/gstoggdemux.c
@@ -108,6 +108,10 @@ struct _GstOggPad
gint64 packetno;
gint64 offset;
+ GstEvent *new_segment;
+ gint64 start;
+ gint64 stop;
+
gint64 current_granule;
GstClockTime start_time; /* the timestamp of the first sample */
@@ -146,6 +150,8 @@ struct _GstOggDemux
OggState state;
gboolean seekable;
+ gboolean need_chains;
+
/* state */
GArray *chains; /* list of chains we know */
@@ -564,11 +570,25 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
buf =
gst_pad_alloc_buffer (GST_PAD (pad), GST_BUFFER_OFFSET_NONE,
packet->bytes, GST_PAD_CAPS (pad));
+
+ if (pad->new_segment) {
+ ret = gst_pad_push_event (GST_PAD (pad), pad->new_segment);
+ pad->new_segment = NULL;
+ }
if (buf) {
+ //GstFormat target = GST_FORMAT_TIME;
+
memcpy (buf->data, packet->packet, packet->bytes);
+ /*
+ if (packet->granulepos != -1) {
+ gst_pad_convert (pad->elem_pad,
+ GST_FORMAT_DEFAULT, packet->granulepos,
+ &target, &GST_BUFFER_TIMESTAMP (buf));
+ }
+ */
+ pad->offset = packet->granulepos;
GST_BUFFER_OFFSET (buf) = -1;
GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
- pad->offset = packet->granulepos;
ret = gst_pad_push (GST_PAD (pad), buf);
}
@@ -909,6 +929,7 @@ gst_ogg_demux_get_data (GstOggDemux * ogg)
return -1;
size = gst_ogg_demux_submit_buffer (ogg, buffer);
+ gst_buffer_unref (buffer);
return size;
}
@@ -1031,6 +1052,26 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
if (pos < 0 || pos > total)
return FALSE;
+ /* first step is to unlock the streaming thread if it is
+ * blocked in a chain call, we do this by starting the flush */
+ {
+ gint i;
+
+ for (i = 0; i < ogg->chains->len; i++) {
+ GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
+ gint j;
+
+ for (j = 0; j < chain->streams->len; j++) {
+ GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
+
+ gst_pad_push_event (GST_PAD (pad), gst_event_new_flush (FALSE));
+ }
+ }
+ }
+
+ /* now grab the stream lock so that streaming cannot continue */
+ GST_STREAM_LOCK (ogg->sinkpad);
+
/* first find the chain to search in */
for (i = ogg->chains->len - 1; i >= 0; i--) {
chain = g_array_index (ogg->chains, GstOggChain *, i);
@@ -1083,8 +1124,9 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
", end %" G_GINT64_FORMAT, bisect, begin, end);
result = gst_ogg_demux_get_next_page (ogg, &og, end - ogg->offset);
- if (result == OV_EREAD)
+ if (result == OV_EREAD) {
goto seek_error;
+ }
if (result < 0) {
if (bisect <= begin + 1) {
@@ -1149,11 +1191,47 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
}
}
}
+
+ ogg->offset = best;
+
+ /* now we have a new position, prepare for streaming again */
+ {
+ gint i;
+ GstEvent *event;
+
+ /* create the discont event we are going to send out */
+ event = gst_event_new_discontinuous (1.0,
+ GST_FORMAT_TIME, (gint64) pos, (gint64) ogg->total_time, NULL);
+
+ for (i = 0; i < ogg->chains->len; i++) {
+ GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
+ gint j;
+
+ for (j = 0; j < chain->streams->len; j++) {
+ GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
+
+ gst_event_ref (event);
+ /* queue the event for the strea,ing thread */
+ pad->new_segment = event;
+ gst_pad_push_event (GST_PAD (pad), gst_event_new_flush (TRUE));
+ }
+ }
+ gst_event_unref (event);
+ /* restart our task since it might have been stopped when we did the
+ * flush. */
+ gst_task_start (GST_RPAD_TASK (ogg->sinkpad));
+ }
+ /* streaming can continue now */
+ GST_STREAM_UNLOCK (ogg->sinkpad);
+
/* FIXME, switch to different chain */
return TRUE;
seek_error:
+ GST_DEBUG_OBJECT (ogg, "got a seek error");
+ GST_STREAM_UNLOCK (ogg->sinkpad);
+
return FALSE;
}
@@ -1492,7 +1570,7 @@ no_length:
* the serialno, submit pages and packets to the oggpads
*/
static GstFlowReturn
-gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
+gst_ogg_demux_chain_unlocked (GstPad * pad, GstBuffer * buffer)
{
GstOggDemux *ogg;
gint ret = -1;
@@ -1558,6 +1636,18 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
return result;
}
+static GstFlowReturn
+gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
+{
+ GstFlowReturn ret;
+
+ GST_STREAM_LOCK (pad);
+ ret = gst_ogg_demux_chain_unlocked (pad, buffer);
+ GST_STREAM_UNLOCK (pad);
+
+ return ret;
+}
+
/* random access code
*
* - first find all the chains and streams by scanning the
@@ -1571,35 +1661,49 @@ static gboolean
gst_ogg_demux_loop (GstOggPad * pad)
{
GstOggDemux *ogg;
+ GstFlowReturn ret;
+ GstBuffer *buffer;
ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad));
- gst_ogg_demux_find_chains (ogg);
-
- ogg->offset = 0;
- while (TRUE) {
- GstFlowReturn ret;
- GstBuffer *buffer;
+ GST_STREAM_LOCK (pad);
+ if (ogg->need_chains) {
+ gst_ogg_demux_find_chains (ogg);
+ ogg->need_chains = FALSE;
+ ogg->offset = 0;
+ }
- GST_LOG_OBJECT (ogg, "pull data %lld", ogg->offset);
- if (ogg->offset == ogg->length)
- return FALSE;
+ GST_LOG_OBJECT (ogg, "pull data %lld", ogg->offset);
+ if (ogg->offset == ogg->length)
+ goto error;
- ret = gst_pad_pull_range (ogg->sinkpad, ogg->offset, CHUNKSIZE, &buffer);
- if (ret != GST_FLOW_OK) {
- GST_LOG_OBJECT (ogg, "got error %d", ret);
- return FALSE;
- }
+ ret = gst_pad_pull_range (ogg->sinkpad, ogg->offset, CHUNKSIZE, &buffer);
+ if (ret != GST_FLOW_OK) {
+ GST_LOG_OBJECT (ogg, "got error %d", ret);
+ goto error;
+ }
- ogg->offset += GST_BUFFER_SIZE (buffer);
+ ogg->offset += GST_BUFFER_SIZE (buffer);
- ret = gst_ogg_demux_chain (ogg->sinkpad, buffer);
- if (ret != GST_FLOW_OK) {
- GST_LOG_OBJECT (ogg, "got error %d", ret);
- return FALSE;
- }
+ ret = gst_ogg_demux_chain_unlocked (ogg->sinkpad, buffer);
+ if (ret == GST_FLOW_UNEXPECTED) {
+ gst_task_pause (GST_RPAD_TASK (ogg->sinkpad));
+ GST_LOG_OBJECT (ogg, "got unexpected %d", ret);
+ goto done;
}
+ if (ret != GST_FLOW_OK) {
+ GST_LOG_OBJECT (ogg, "got error %d", ret);
+ goto error;
+ }
+done:
+ GST_STREAM_UNLOCK (pad);
+
return TRUE;
+
+error:
+
+ GST_STREAM_UNLOCK (pad);
+ return FALSE;
}
static gboolean
@@ -1622,6 +1726,7 @@ gst_ogg_demux_sink_activate (GstPad * sinkpad, GstActivateMode mode)
gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (ogg),
(GstTaskFunction) gst_ogg_demux_loop, sinkpad);
+ ogg->need_chains = TRUE;
gst_task_start (GST_RPAD_TASK (sinkpad));
ogg->seekable = TRUE;
GST_STREAM_UNLOCK (sinkpad);
diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c
index 13bbf5e8d..53e1b8f2e 100644
--- a/sys/xvimage/xvimagesink.c
+++ b/sys/xvimage/xvimagesink.c
@@ -1390,6 +1390,10 @@ gst_xvimagesink_change_state (GstElement * element)
return result;
}
+static GstFlowReturn
+gst_xvimagesink_finish_preroll (GstXvImageSink * xvimagesink, GstPad * pad,
+ GstBuffer * buf);
+
static gboolean
gst_xvimagesink_event (GstPad * pad, GstEvent * event)
{
@@ -1398,11 +1402,10 @@ gst_xvimagesink_event (GstPad * pad, GstEvent * event)
xvimagesink = GST_XVIMAGESINK (GST_PAD_PARENT (pad));
- GST_STREAM_LOCK (pad);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
- gst_element_finish_preroll (GST_ELEMENT (xvimagesink),
- GST_STREAM_GET_LOCK (pad));
+ GST_STREAM_LOCK (pad);
+ gst_xvimagesink_finish_preroll (xvimagesink, pad, NULL);
gst_clock_id_wait (gst_clock_new_single_shot_id (GST_VIDEOSINK_CLOCK
(xvimagesink),
xvimagesink->end_time + GST_ELEMENT (xvimagesink)->base_time),
@@ -1411,11 +1414,105 @@ gst_xvimagesink_event (GstPad * pad, GstEvent * event)
gst_message_new_eos (GST_OBJECT (xvimagesink)));
result = TRUE;
break;
+ GST_STREAM_UNLOCK (pad);
+ case GST_EVENT_FLUSH:
+ if (xvimagesink->clock_id) {
+ gst_clock_id_unlock (xvimagesink->clock_id);
+ xvimagesink->clock_id = NULL;
+ }
+ GST_STATE_LOCK (xvimagesink);
+ g_cond_broadcast (GST_STATE_GET_COND (xvimagesink));
+ GST_STATE_UNLOCK (xvimagesink);
+ result = TRUE;
+ break;
default:
- result = gst_pad_event_default (pad, event);
+ result = TRUE;
break;
}
- GST_STREAM_UNLOCK (pad);
+ gst_event_unref (event);
+
+ return result;
+}
+
+static GstFlowReturn
+gst_xvimagesink_show_frame (GstXvImageSink * xvimagesink, GstBuffer * buf)
+{
+ /* If this buffer has been allocated using our buffer management we simply
+ put the ximage which is in the PRIVATE pointer */
+ if (GST_BUFFER_FREE_DATA_FUNC (buf) == gst_xvimagesink_buffer_free) {
+ gst_xvimagesink_xvimage_put (xvimagesink, GST_BUFFER_PRIVATE (buf));
+ } else {
+ /* Else we have to copy the data into our private image, */
+ /* if we have one... */
+ if (!xvimagesink->xvimage) {
+ GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
+ xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
+ xvimagesink->video_width, xvimagesink->video_height);
+ if (!xvimagesink->xvimage) {
+ /* No image available. That's very bad ! */
+ gst_buffer_unref (buf);
+ GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
+ ("Failed creating an XvImage in xvimagesink chain function."));
+ return GST_FLOW_ERROR;
+ }
+ }
+
+ memcpy (xvimagesink->xvimage->xvimage->data,
+ GST_BUFFER_DATA (buf),
+ MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
+ gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
+ }
+ return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_xvimagesink_finish_preroll (GstXvImageSink * xvimagesink, GstPad * pad,
+ GstBuffer * buf)
+{
+ GstFlowReturn result = GST_FLOW_OK;
+
+ /* grab state change lock */
+ GST_STATE_LOCK (xvimagesink);
+ /* if we are going to PAUSED, we can commit the state change */
+ if (GST_STATE_PENDING (xvimagesink) == GST_STATE_PAUSED) {
+ gst_element_commit_state (GST_ELEMENT (xvimagesink));
+ }
+ /* if we are paused we need to wait for playing to continue */
+ if (GST_STATE (xvimagesink) == GST_STATE_PAUSED) {
+ GST_DEBUG_OBJECT (xvimagesink,
+ "element %s wants to finish preroll", GST_ELEMENT_NAME (xvimagesink));
+
+ if (buf)
+ gst_xvimagesink_show_frame (xvimagesink, buf);
+
+ //GST_STREAM_UNLOCK (pad);
+
+ /* here we wait for the next state change */
+ while (GST_STATE (xvimagesink) == GST_STATE_PAUSED) {
+ if (GST_RPAD_IS_FLUSHING (pad)) {
+ GST_DEBUG_OBJECT (xvimagesink, "pad is flushing");
+ result = GST_FLOW_UNEXPECTED;
+ //GST_STREAM_LOCK (pad);
+ goto done;
+ }
+
+ GST_DEBUG_OBJECT (xvimagesink, "waiting for next state change");
+ GST_STATE_WAIT (xvimagesink);
+ GST_DEBUG_OBJECT (xvimagesink, "got unlocked, maybe a state change");
+ }
+
+ //GST_STREAM_LOCK (pad);
+
+ /* check if we got playing */
+ if (GST_STATE (xvimagesink) != GST_STATE_PLAYING) {
+ /* not playing, we can't accept the buffer */
+ result = GST_FLOW_WRONG_STATE;
+ }
+
+ GST_DEBUG_OBJECT (xvimagesink, "done preroll");
+ }
+done:
+ GST_STATE_UNLOCK (xvimagesink);
return result;
}
@@ -1440,17 +1537,17 @@ gst_xvimagesink_chain (GstPad * pad, GstBuffer * buffer)
GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
("received unkown format"));
gst_element_abort_preroll (GST_ELEMENT (xvimagesink));
+ gst_buffer_unref (buffer);
return GST_FLOW_NOT_NEGOTIATED;
}
}
if (!GST_PAD_CAPS (pad)) {
+ gst_buffer_unref (buffer);
return GST_FLOW_NOT_NEGOTIATED;
}
GST_STREAM_LOCK (pad);
- result =
- gst_element_finish_preroll (GST_ELEMENT (xvimagesink),
- GST_STREAM_GET_LOCK (pad));
+ result = gst_xvimagesink_finish_preroll (xvimagesink, pad, buf);
if (result != GST_FLOW_OK) {
goto done;
}
@@ -1466,38 +1563,20 @@ gst_xvimagesink_chain (GstPad * pad, GstBuffer * buffer)
GST_TIME_ARGS (xvimagesink->time));
if (GST_VIDEOSINK_CLOCK (xvimagesink)) {
- //gst_element_wait (GST_ELEMENT (xvimagesink), xvimagesink->time);
- gst_clock_id_wait (gst_clock_new_single_shot_id (GST_VIDEOSINK_CLOCK
- (xvimagesink),
- xvimagesink->time + GST_ELEMENT (xvimagesink)->base_time), NULL);
- }
+ GstClockReturn ret;
- /* If this buffer has been allocated using our buffer management we simply
- put the ximage which is in the PRIVATE pointer */
- if (GST_BUFFER_FREE_DATA_FUNC (buf) == gst_xvimagesink_buffer_free) {
- gst_xvimagesink_xvimage_put (xvimagesink, GST_BUFFER_PRIVATE (buf));
- } else {
- /* Else we have to copy the data into our private image, */
- /* if we have one... */
- if (!xvimagesink->xvimage) {
- GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
- xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
- xvimagesink->video_width, xvimagesink->video_height);
- if (!xvimagesink->xvimage) {
- /* No image available. That's very bad ! */
- gst_buffer_unref (buf);
- GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
- ("Failed creating an XvImage in xvimagesink chain function."));
- return GST_FLOW_ERROR;
- }
- }
+ //gst_element_wait (GST_ELEMENT (xvimagesink), xvimagesink->time);
+ xvimagesink->clock_id =
+ gst_clock_new_single_shot_id (GST_VIDEOSINK_CLOCK (xvimagesink),
+ xvimagesink->time + GST_ELEMENT (xvimagesink)->base_time);
- memcpy (xvimagesink->xvimage->xvimage->data,
- GST_BUFFER_DATA (buf),
- MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
- gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
+ ret = gst_clock_id_wait (xvimagesink->clock_id, NULL);
+ xvimagesink->clock_id = NULL;
+ GST_LOG_OBJECT (xvimagesink, "clock entry done: %d", ret);
}
+ gst_xvimagesink_show_frame (xvimagesink, buf);
+
/* set correct time for next buffer */
if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf) && xvimagesink->framerate > 0) {
xvimagesink->time += GST_SECOND / xvimagesink->framerate;
diff --git a/sys/xvimage/xvimagesink.h b/sys/xvimage/xvimagesink.h
index 35891b5c8..99e845b28 100644
--- a/sys/xvimage/xvimagesink.h
+++ b/sys/xvimage/xvimagesink.h
@@ -149,6 +149,7 @@ struct _GstXvImageSink {
GstClockTime time;
GstClockTime end_time;
+ GstClockEntry *clock_id;
GMutex *pool_lock;
GSList *image_pool;
diff --git a/tests/examples/seek/seek.c b/tests/examples/seek/seek.c
index 8a2b5083b..a1d29b107 100644
--- a/tests/examples/seek/seek.c
+++ b/tests/examples/seek/seek.c
@@ -17,6 +17,7 @@ static gboolean elem_seek = FALSE;
static gboolean verbose = FALSE;
static guint update_id;
+static gulong changed_id;
//#define SOURCE "gnomevfssrc"
#define SOURCE "filesrc"
@@ -847,16 +848,7 @@ update_scale (gpointer data)
}
static gboolean
-start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
-{
- gst_element_set_state (pipeline, GST_STATE_PAUSED);
- gtk_timeout_remove (update_id);
-
- return FALSE;
-}
-
-static gboolean
-stop_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
+do_seek (GtkWidget * widget, gpointer user_data)
{
gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100;
gboolean res;
@@ -896,6 +888,28 @@ stop_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
}
}
+ GST_PIPELINE (pipeline)->stream_time = real;
+
+ return FALSE;
+}
+
+static gboolean
+start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
+{
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ gtk_timeout_remove (update_id);
+
+ changed_id = gtk_signal_connect (GTK_OBJECT (hscale),
+ "value_changed", G_CALLBACK (do_seek), pipeline);
+
+ return FALSE;
+}
+
+static gboolean
+stop_seek (GtkWidget * widget, gpointer user_data)
+{
+ g_signal_handler_disconnect (GTK_OBJECT (hscale), changed_id);
+
gst_element_set_state (pipeline, GST_STATE_PLAYING);
update_id =
gtk_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline);