summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Schmidt <thaytan@mad.scientist.com>2005-02-20 14:16:38 +0000
committerJan Schmidt <thaytan@mad.scientist.com>2005-02-20 14:16:38 +0000
commit593fb4a9fb808cd00274256a531cbe2d73ae3e1e (patch)
tree7fecbe35edf3e9de41a358e35e33e7344c7113d2
parent002836cd1566890a9d5ba988a0fb684edd1cb9dc (diff)
downloadgstreamer-plugins-base-593fb4a9fb808cd00274256a531cbe2d73ae3e1e.tar.gz
examples/seeking/seek.c: Add realtime scrubbing to the seek example.
Original commit message from CVS: * examples/seeking/seek.c: (end_scrub), (do_seek), (seek_cb), (start_seek), (stop_seek): Add realtime scrubbing to the seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_demux_perform_seek): Avoid overflowing 64-bits on large files when estimating the new position during a seek.
-rw-r--r--examples/seeking/seek.c51
-rw-r--r--ext/ogg/gstoggdemux.c10
-rw-r--r--tests/examples/seek/seek.c51
3 files changed, 99 insertions, 13 deletions
diff --git a/examples/seeking/seek.c b/examples/seeking/seek.c
index 4ba2f34c6..81ba7d8f4 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 guint seek_timeout_id = 0;
static gulong changed_id;
//#define SOURCE "gnomevfssrc"
@@ -24,6 +25,10 @@ static gulong changed_id;
#define UPDATE_INTERVAL 500
+/* number of milliseconds to play for after a seek */
+#define SCRUB_TIME 250
+#undef SCRUB
+
#define THREAD
#define PAD_SEEK
@@ -982,8 +987,21 @@ update_scale (gpointer data)
return TRUE;
}
+static void do_seek (GtkWidget * widget);
+
+#ifdef SCRUB
static gboolean
-do_seek (GtkWidget * widget, gpointer user_data)
+end_scrub (GtkWidget * widget)
+{
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ seek_timeout_id = 0;
+
+ return FALSE;
+}
+#endif
+
+static void
+do_seek (GtkWidget * widget)
{
gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100;
gboolean res;
@@ -1024,8 +1042,28 @@ do_seek (GtkWidget * widget, gpointer user_data)
}
GST_PIPELINE (pipeline)->stream_time = real;
+}
- return FALSE;
+static void
+seek_cb (GtkWidget * widget)
+{
+#ifdef SCRUB
+ /* If the timer hasn't expired yet, then the pipeline is running */
+ if (seek_timeout_id != 0) {
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ }
+#endif
+
+ do_seek (widget);
+
+#ifdef SCRUB
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+ if (seek_timeout_id == 0) {
+ seek_timeout_id =
+ gtk_timeout_add (SCRUB_TIME, (GSourceFunc) end_scrub, widget);
+ }
+#endif
}
static gboolean
@@ -1036,7 +1074,7 @@ start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
if (changed_id == 0) {
changed_id = gtk_signal_connect (GTK_OBJECT (hscale),
- "value_changed", G_CALLBACK (do_seek), pipeline);
+ "value_changed", G_CALLBACK (seek_cb), pipeline);
}
return FALSE;
@@ -1047,8 +1085,13 @@ stop_seek (GtkWidget * widget, gpointer user_data)
{
g_signal_handler_disconnect (GTK_OBJECT (hscale), changed_id);
changed_id = 0;
+ if (seek_timeout_id != 0) {
+ gtk_timeout_remove (seek_timeout_id);
+ seek_timeout_id = 0;
+ /* Still scrubbing, so the pipeline is already playing */
+ } else
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
- 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 9625d9281..02519b343 100644
--- a/ext/ogg/gstoggdemux.c
+++ b/ext/ogg/gstoggdemux.c
@@ -1275,13 +1275,13 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
while (begin < end) {
gint64 bisect;
- if (end - begin < CHUNKSIZE) {
+ if ((end - begin < CHUNKSIZE) || (endtime == begintime)) {
bisect = begin;
} else {
- /* take a (pretty decent) guess. */
- bisect = begin +
- (target - begintime) * (end - begin) / (endtime - begintime) -
- CHUNKSIZE;
+ /* take a (pretty decent) guess, avoiding overflow */
+ gint64 rate = (end - begin) * GST_MSECOND / (endtime - begintime);
+
+ bisect = (target - begintime) / GST_MSECOND * rate + begin - CHUNKSIZE;
if (bisect <= begin)
bisect = begin + 1;
diff --git a/tests/examples/seek/seek.c b/tests/examples/seek/seek.c
index 4ba2f34c6..81ba7d8f4 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 guint seek_timeout_id = 0;
static gulong changed_id;
//#define SOURCE "gnomevfssrc"
@@ -24,6 +25,10 @@ static gulong changed_id;
#define UPDATE_INTERVAL 500
+/* number of milliseconds to play for after a seek */
+#define SCRUB_TIME 250
+#undef SCRUB
+
#define THREAD
#define PAD_SEEK
@@ -982,8 +987,21 @@ update_scale (gpointer data)
return TRUE;
}
+static void do_seek (GtkWidget * widget);
+
+#ifdef SCRUB
static gboolean
-do_seek (GtkWidget * widget, gpointer user_data)
+end_scrub (GtkWidget * widget)
+{
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ seek_timeout_id = 0;
+
+ return FALSE;
+}
+#endif
+
+static void
+do_seek (GtkWidget * widget)
{
gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100;
gboolean res;
@@ -1024,8 +1042,28 @@ do_seek (GtkWidget * widget, gpointer user_data)
}
GST_PIPELINE (pipeline)->stream_time = real;
+}
- return FALSE;
+static void
+seek_cb (GtkWidget * widget)
+{
+#ifdef SCRUB
+ /* If the timer hasn't expired yet, then the pipeline is running */
+ if (seek_timeout_id != 0) {
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ }
+#endif
+
+ do_seek (widget);
+
+#ifdef SCRUB
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+ if (seek_timeout_id == 0) {
+ seek_timeout_id =
+ gtk_timeout_add (SCRUB_TIME, (GSourceFunc) end_scrub, widget);
+ }
+#endif
}
static gboolean
@@ -1036,7 +1074,7 @@ start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
if (changed_id == 0) {
changed_id = gtk_signal_connect (GTK_OBJECT (hscale),
- "value_changed", G_CALLBACK (do_seek), pipeline);
+ "value_changed", G_CALLBACK (seek_cb), pipeline);
}
return FALSE;
@@ -1047,8 +1085,13 @@ stop_seek (GtkWidget * widget, gpointer user_data)
{
g_signal_handler_disconnect (GTK_OBJECT (hscale), changed_id);
changed_id = 0;
+ if (seek_timeout_id != 0) {
+ gtk_timeout_remove (seek_timeout_id);
+ seek_timeout_id = 0;
+ /* Still scrubbing, so the pipeline is already playing */
+ } else
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
update_id =
gtk_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline);