event: add new seek parameter, "trickmode-interval"
authorMathieu Duponchelle <mathieu@centricular.com>
Mon, 1 Apr 2019 16:34:07 +0000 (18:34 +0200)
committerMathieu Duponchelle <mduponchelle1@gmail.com>
Mon, 1 Apr 2019 17:13:32 +0000 (17:13 +0000)
When performing a key unit trickmode seek, it may be useful to
specify a minimum interval between the output frames, either
in very high rate cases, or as a protection against streams
that may contain an overly large amount of key frames.

One use case is ONVIF Section 6.5.3:

<https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec.pdf>

docs/gst/gstreamer-sections.txt
gst/gstevent.c
gst/gstevent.h
gst/gstquark.c
gst/gstquark.h
tests/check/gst/gstevent.c

index 9d172ae..1af775a 100644 (file)
@@ -1216,6 +1216,8 @@ GstSeekType
 GstSeekFlags
 gst_event_new_seek
 gst_event_parse_seek
+gst_event_set_seek_trickmode_interval
+gst_event_parse_seek_trickmode_interval
 
 gst_event_new_navigation
 
index 0189f43..2bd06d7 100644 (file)
@@ -1306,7 +1306,8 @@ gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
       GST_QUARK (CUR_TYPE), GST_TYPE_SEEK_TYPE, start_type,
       GST_QUARK (CUR), G_TYPE_INT64, start,
       GST_QUARK (STOP_TYPE), GST_TYPE_SEEK_TYPE, stop_type,
-      GST_QUARK (STOP), G_TYPE_INT64, stop, NULL);
+      GST_QUARK (STOP), G_TYPE_INT64, stop,
+      GST_QUARK (TRICKMODE_INTERVAL), GST_TYPE_CLOCK_TIME, 0, NULL);
   event = gst_event_new_custom (GST_EVENT_SEEK, structure);
 
   return event;
@@ -1367,6 +1368,48 @@ gst_event_parse_seek (GstEvent * event, gdouble * rate,
 }
 
 /**
+ * gst_event_set_seek_trickmode_interval:
+ *
+ * Sets a trickmode interval on a (writable) seek event. Elements
+ * that support TRICKMODE_KEY_UNITS seeks SHOULD use this as the minimal
+ * interval between each frame they may output.
+ *
+ * Since: 1.16
+ */
+void
+gst_event_set_seek_trickmode_interval (GstEvent * event, GstClockTime interval)
+{
+  g_return_if_fail (event != NULL);
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
+  g_return_if_fail (gst_event_is_writable (event));
+  g_return_if_fail (GST_CLOCK_TIME_IS_VALID (interval));
+
+  gst_structure_id_set (GST_EVENT_STRUCTURE (event),
+      GST_QUARK (TRICKMODE_INTERVAL), GST_TYPE_CLOCK_TIME, interval, NULL);
+}
+
+/**
+ * gst_event_parse_seek_trickmode_interval:
+ * @interval: (out)
+ *
+ * Retrieve the trickmode interval that may have been set on a
+ * seek event with gst_event_set_seek_trickmode_interval().
+ *
+ * Since: 1.16
+ */
+void
+gst_event_parse_seek_trickmode_interval (GstEvent * event,
+    GstClockTime * interval)
+{
+  g_return_if_fail (event != NULL);
+  g_return_if_fail (interval != NULL);
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
+
+  gst_structure_id_get (GST_EVENT_STRUCTURE (event),
+      GST_QUARK (TRICKMODE_INTERVAL), GST_TYPE_CLOCK_TIME, interval, NULL);
+}
+
+/**
  * gst_event_new_navigation:
  * @structure: (transfer full): description of the event. The event will take
  *     ownership of the structure.
index 4033cac..282acf2 100644 (file)
@@ -676,6 +676,12 @@ void            gst_event_parse_seek            (GstEvent *event, gdouble *rate,
                                                  GstSeekType *start_type, gint64 *start,
                                                  GstSeekType *stop_type, gint64 *stop);
 
+GST_API
+void            gst_event_set_seek_trickmode_interval (GstEvent *event, GstClockTime interval);
+
+GST_API
+void            gst_event_parse_seek_trickmode_interval (GstEvent *event, GstClockTime *interval);
+
 /* navigation event */
 
 GST_API
index 4614578..e42e5d0 100644 (file)
@@ -76,7 +76,7 @@ static const gchar *_quark_strings[] = {
   "GstMessageStreamsSelected", "GstMessageRedirect", "redirect-entry-locations",
   "redirect-entry-taglists", "redirect-entry-structures",
   "GstEventStreamGroupDone", "GstQueryBitrate", "nominal-bitrate",
-  "GstMessageDeviceChanged", "device-changed"
+  "GstMessageDeviceChanged", "device-changed", "trickmode-interval",
 };
 
 GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index e93a61f..84c40d7 100644 (file)
@@ -221,7 +221,8 @@ typedef enum _GstQuarkId
   GST_QUARK_NOMINAL_BITRATE = 190,
   GST_QUARK_MESSAGE_DEVICE_CHANGED = 191,
   GST_QUARK_DEVICE_CHANGED = 192,
-  GST_QUARK_MAX = 193
+  GST_QUARK_TRICKMODE_INTERVAL = 193,
+  GST_QUARK_MAX = 194
 } GstQuarkId;
 
 extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index d124c91..39b5f30 100644 (file)
@@ -218,6 +218,7 @@ GST_START_TEST (create_events)
     GstSeekFlags flags;
     GstSeekType start_type, stop_type;
     gint64 start, stop;
+    GstClockTime trickmode_interval;
 
     event = gst_event_new_seek (0.5, GST_FORMAT_BYTES,
         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
@@ -239,6 +240,22 @@ GST_START_TEST (create_events)
     fail_unless (stop_type == GST_SEEK_TYPE_NONE);
     fail_unless (stop == 0xdeadbeef);
 
+    gst_event_parse_seek_trickmode_interval (event, &trickmode_interval);
+    fail_unless_equals_uint64 (trickmode_interval, 0);
+
+    gst_event_set_seek_trickmode_interval (event, GST_SECOND);
+    gst_event_parse_seek_trickmode_interval (event, &trickmode_interval);
+    fail_unless_equals_uint64 (trickmode_interval, GST_SECOND);
+
+    gst_event_ref (event);
+    ASSERT_CRITICAL (gst_event_set_seek_trickmode_interval (event,
+            2 * GST_SECOND));
+    gst_event_unref (event);
+
+    gst_event_unref (event);
+
+    event = gst_event_new_flush_start ();
+    ASSERT_CRITICAL (gst_event_set_seek_trickmode_interval (event, GST_SECOND));
     gst_event_unref (event);
   }