diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2005-01-04 12:08:22 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2005-01-04 12:08:22 +0000 |
commit | dc7434a40b3a39079cc4247e8c213cec8abe48c6 (patch) | |
tree | 666840ce004da4c0c8f54a290e85e9ee6b8a1262 | |
parent | c678ed9394644c87912e29ab77b8111489b9caff (diff) | |
download | gstreamer-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-- | ChangeLog | 30 | ||||
-rw-r--r-- | examples/seeking/seek.c | 34 | ||||
-rw-r--r-- | ext/ogg/gstoggdemux.c | 151 | ||||
-rw-r--r-- | sys/xvimage/xvimagesink.c | 151 | ||||
-rw-r--r-- | sys/xvimage/xvimagesink.h | 1 | ||||
-rw-r--r-- | tests/examples/seek/seek.c | 34 |
6 files changed, 322 insertions, 79 deletions
@@ -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); |