playback-test: Add support for sending instant-rate-change seeks
authorSebastian Dröge <sebastian@centricular.com>
Fri, 25 May 2018 08:01:58 +0000 (11:01 +0300)
committerSebastian Dröge <slomo@coaxion.net>
Wed, 1 Apr 2020 21:01:38 +0000 (21:01 +0000)
tests/examples/playback/playback-test.c

index 10cf886..b310e4b 100644 (file)
@@ -149,6 +149,7 @@ typedef struct
   gboolean flush_seek;
   gboolean scrub;
   gboolean play_scrub;
+  gboolean instant_rate_change;
   gboolean skip_seek;
   gboolean skip_seek_key_only;
   gboolean skip_seek_no_audio;
@@ -544,6 +545,9 @@ do_seek (PlaybackApp * app, GstFormat format, gint64 position)
 {
   gboolean res = FALSE;
   GstEvent *s_event;
+  GstClockTime start, stop;
+  GstSeekType start_type = GST_SEEK_TYPE_SET;
+  GstSeekType stop_type = GST_SEEK_TYPE_SET;
   GstSeekFlags flags;
 
   flags = 0;
@@ -566,18 +570,32 @@ do_seek (PlaybackApp * app, GstFormat format, gint64 position)
   if (app->snap_after)
     flags |= GST_SEEK_FLAG_SNAP_AFTER;
 
+  if (app->instant_rate_change) {
+    flags |= GST_SEEK_FLAG_INSTANT_RATE_CHANGE;
+    start_type = stop_type = GST_SEEK_TYPE_NONE;
+    start = stop = GST_CLOCK_TIME_NONE;
+    if (app->flush_seek) {
+      g_warning ("Instant rate change seek not supported with flushing");
+      return;
+    }
+  } else if (app->rate < 0) {
+    stop = position;
+    start = 0;
+  } else {
+    start = position;
+    stop = GST_CLOCK_TIME_NONE;
+  }
+
   if (app->rate >= 0) {
     s_event = gst_event_new_seek (app->rate,
-        format, flags, GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_SET,
-        GST_CLOCK_TIME_NONE);
+        format, flags, start_type, start, stop_type, stop);
     GST_DEBUG ("seek with rate %lf to %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT,
-        app->rate, GST_TIME_ARGS (position), GST_TIME_ARGS (app->duration));
+        app->rate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
   } else {
     s_event = gst_event_new_seek (app->rate,
-        format, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0),
-        GST_SEEK_TYPE_SET, position);
+        format, flags, start_type, start, stop_type, stop);
     GST_DEBUG ("seek with rate %lf to %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT,
-        app->rate, GST_TIME_ARGS (0), GST_TIME_ARGS (position));
+        app->rate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
   }
 
   res = send_event (app, s_event);
@@ -940,6 +958,12 @@ play_scrub_toggle_cb (GtkToggleButton * button, PlaybackApp * app)
 }
 
 static void
+instant_rate_change_toggle_cb (GtkToggleButton * button, PlaybackApp * app)
+{
+  app->instant_rate_change = gtk_toggle_button_get_active (button);
+}
+
+static void
 skip_toggle_common (gboolean * v, GtkToggleButton * button, PlaybackApp * app)
 {
   *v = gtk_toggle_button_get_active (button);
@@ -977,6 +1001,9 @@ rate_spinbutton_changed_cb (GtkSpinButton * button, PlaybackApp * app)
   gboolean res = FALSE;
   GstEvent *s_event;
   GstSeekFlags flags;
+  GstClockTime start, stop;
+  GstSeekType start_type = GST_SEEK_TYPE_SET;
+  GstSeekType stop_type = GST_SEEK_TYPE_SET;
 
   app->rate = gtk_spin_button_get_value (button);
 
@@ -998,14 +1025,28 @@ rate_spinbutton_changed_cb (GtkSpinButton * button, PlaybackApp * app)
   if (app->skip_seek_no_audio)
     flags |= GST_SEEK_FLAG_TRICKMODE_NO_AUDIO;
 
+  if (app->instant_rate_change) {
+    flags |= GST_SEEK_FLAG_INSTANT_RATE_CHANGE;
+    start_type = stop_type = GST_SEEK_TYPE_NONE;
+    start = stop = GST_CLOCK_TIME_NONE;
+    if (app->flush_seek) {
+      g_warning ("Instant rate change seek not supported with flushing");
+      return;
+    }
+  } else if (app->rate < 0) {
+    stop = app->position;
+    start = 0;
+  } else {
+    start = app->position;
+    stop = GST_CLOCK_TIME_NONE;
+  }
+
   if (app->rate >= 0.0) {
     s_event = gst_event_new_seek (app->rate,
-        GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, app->position,
-        GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE);
+        GST_FORMAT_TIME, flags, start_type, start, stop_type, stop);
   } else {
     s_event = gst_event_new_seek (app->rate,
-        GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0),
-        GST_SEEK_TYPE_SET, app->position);
+        GST_FORMAT_TIME, flags, start_type, start, stop_type, stop);
   }
 
   res = send_event (app, s_event);
@@ -1533,34 +1574,6 @@ step_cb (GtkButton * button, PlaybackApp * app)
 static void
 message_received (GstBus * bus, GstMessage * message, PlaybackApp * app)
 {
-  const GstStructure *s;
-
-  switch (GST_MESSAGE_TYPE (message)) {
-    case GST_MESSAGE_ERROR:
-      GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (app->pipeline),
-          GST_DEBUG_GRAPH_SHOW_ALL, "seek.error");
-      break;
-    case GST_MESSAGE_WARNING:
-      GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (app->pipeline),
-          GST_DEBUG_GRAPH_SHOW_ALL, "seek.warning");
-      break;
-    default:
-      break;
-  }
-
-  s = gst_message_get_structure (message);
-  g_print ("message from \"%s\" (%s): ",
-      GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))),
-      gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
-  if (s) {
-    gchar *sstr;
-
-    sstr = gst_structure_to_string (s);
-    g_print ("%s\n", sstr);
-    g_free (sstr);
-  } else {
-    g_print ("no message details\n");
-  }
 }
 
 static void
@@ -2686,11 +2699,11 @@ create_ui (PlaybackApp * app)
 
   /* seek expander */
   {
-    GtkWidget *accurate_checkbox, *key_checkbox, *loop_checkbox,
-        *flush_checkbox, *snap_before_checkbox, *snap_after_checkbox;
+    GtkWidget *accurate_checkbox, *key_checkbox, *loop_checkbox;
+    GtkWidget *flush_checkbox, *snap_before_checkbox, *snap_after_checkbox;
     GtkWidget *scrub_checkbox, *play_scrub_checkbox, *rate_label;
-    GtkWidget *skip_checkbox, *skip_key_checkbox, *skip_audio_checkbox,
-        *rate_spinbutton;
+    GtkWidget *skip_checkbox, *skip_key_checkbox, *skip_audio_checkbox;
+    GtkWidget *instant_checkbox, *rate_spinbutton;
     GtkWidget *flagtable, *advanced_seek, *advanced_seek_grid;
     GtkWidget *duration_label, *position_label, *seek_button;
     GtkWidget *start_label, *stop_label;
@@ -2708,6 +2721,7 @@ create_ui (PlaybackApp * app)
     flush_checkbox = gtk_check_button_new_with_label ("Flush");
     scrub_checkbox = gtk_check_button_new_with_label ("Scrub");
     play_scrub_checkbox = gtk_check_button_new_with_label ("Play Scrub");
+    instant_checkbox = gtk_check_button_new_with_label ("Instant Rate Change");
     skip_checkbox = gtk_check_button_new_with_label ("Trickmode Play");
     skip_key_checkbox =
         gtk_check_button_new_with_label ("Trickmode - Keyframes Only");
@@ -2731,6 +2745,7 @@ create_ui (PlaybackApp * app)
     gtk_widget_set_tooltip_text (scrub_checkbox, "show images while seeking");
     gtk_widget_set_tooltip_text (play_scrub_checkbox,
         "play video while seeking");
+    gtk_widget_set_tooltip_text (instant_checkbox, "do instant rate changes");
     gtk_widget_set_tooltip_text (skip_checkbox,
         "Skip frames while playing at high frame rates");
     gtk_widget_set_tooltip_text (skip_key_checkbox,
@@ -2759,6 +2774,8 @@ create_ui (PlaybackApp * app)
         G_CALLBACK (scrub_toggle_cb), app);
     g_signal_connect (G_OBJECT (play_scrub_checkbox), "toggled",
         G_CALLBACK (play_scrub_toggle_cb), app);
+    g_signal_connect (G_OBJECT (instant_checkbox), "toggled",
+        G_CALLBACK (instant_rate_change_toggle_cb), app);
     g_signal_connect (G_OBJECT (skip_checkbox), "toggled",
         G_CALLBACK (skip_toggle_cb), app);
     g_signal_connect (G_OBJECT (skip_key_checkbox), "toggled",
@@ -2778,6 +2795,7 @@ create_ui (PlaybackApp * app)
     gtk_grid_attach (GTK_GRID (flagtable), key_checkbox, 0, 1, 1, 1);
     gtk_grid_attach (GTK_GRID (flagtable), scrub_checkbox, 1, 1, 1, 1);
     gtk_grid_attach (GTK_GRID (flagtable), play_scrub_checkbox, 2, 1, 1, 1);
+    gtk_grid_attach (GTK_GRID (flagtable), instant_checkbox, 2, 2, 1, 1);
     gtk_grid_attach (GTK_GRID (flagtable), skip_checkbox, 3, 0, 1, 1);
     gtk_grid_attach (GTK_GRID (flagtable), skip_key_checkbox, 3, 1, 1, 1);
     gtk_grid_attach (GTK_GRID (flagtable), skip_audio_checkbox, 3, 2, 1, 1);