add new API for framestepping
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 1 Jun 2009 10:19:52 +0000 (12:19 +0200)
committerWim Taymans <wim@metal.(none)>
Mon, 1 Jun 2009 11:36:49 +0000 (13:36 +0200)
Add new STEP event and methods for creating/parsing the event
Update design docs.
Add new STEP_DONE message and method to create/parse.

API: GstEvent::gst_event_new_step()
API: GstEvent::gst_event_parse_step()
API: GstMessage::gst_message_new_step_done()
API: GstMessage::gst_message_parse_step_done()

docs/design/draft-framestep.txt
docs/gst/gstreamer-sections.txt
gst/gstevent.c
gst/gstevent.h
gst/gstmessage.c
gst/gstmessage.h
gst/gstquark.c
gst/gstquark.h
win32/common/libgstreamer.def

index 8f74ae3..56bceb0 100644 (file)
@@ -114,15 +114,6 @@ events
      rates here, use a seek with a negative rate first to reverse the playback
      direction.
 
-  "intermediate", G_TYPE_BOOLEAN
-     Signal that this step operation is an intermediate step, part of a series
-     of step operations. It is mostly interesting for stepping in the PAUSED state
-     because the sink will only perform a preroll after a non-intermediate step
-     operation completes. Intermediate steps are usefull to flush out data from
-     other sinks in order to not cause excessive queueing. In the PLAYING state
-     the intermediate flag has no visual effect. In all states, the intermediate
-     flag is passed to the corresponding GST_MESSAGE_STEP_DONE.
-
   "flush", G_TYPE_BOOLEAN
      when flushing is TRUE, the step is performed immediatly: 
 
@@ -143,7 +134,16 @@ events
       - In the PLAYING state the step operation will be performed after the
        current step operation completes. If there was no previous step
        operation, the step operation will be performed from the position of the
-       last PAUSED state.
+       last PAUSED state. 
+
+  "intermediate", G_TYPE_BOOLEAN
+     Signal that this step operation is an intermediate step, part of a series
+     of step operations. It is mostly interesting for stepping in the PAUSED state
+     because the sink will only perform a preroll after a non-intermediate step
+     operation completes. Intermediate steps are usefull to flush out data from
+     other sinks in order to not cause excessive queueing. In the PLAYING state
+     the intermediate flag has no visual effect. In all states, the intermediate
+     flag is passed to the corresponding GST_MESSAGE_STEP_DONE.
 
 
  The application will create a STEP event to start or stop the stepping
@@ -180,12 +180,12 @@ messages
   "rate", G_TYPE_DOUBLE
      The rate and direction at which the frames were stepped.
 
-  "intermediate", G_TYPE_BOOLEAN
-     If this is an intermediate step operation that completed.
-
   "duration", G_TYPE_UINT64
      The total duration of the stepped units in GST_FORMAT_TIME.
 
+  "intermediate", G_TYPE_BOOLEAN
+     If this is an intermediate step operation that completed.
+
  The message is emited by the element that performs the step operation.
 
 
index 6c9fb4e..bd2abd0 100644 (file)
@@ -743,6 +743,9 @@ gst_event_new_navigation
 
 gst_event_new_latency
 gst_event_parse_latency
+
+gst_event_new_step
+gst_event_parse_step
 <SUBSECTION Standard>
 GstEventClass
 GST_EVENT
@@ -1121,6 +1124,8 @@ gst_message_parse_buffering_stats
 gst_message_new_state_changed
 gst_message_parse_state_changed
 gst_message_new_state_dirty
+gst_message_new_step_done
+gst_message_parse_step_done
 gst_message_new_clock_provide
 gst_message_parse_clock_provide
 gst_message_new_clock_lost
index bb90a30..ba208c1 100644 (file)
@@ -1088,3 +1088,90 @@ gst_event_parse_latency (GstEvent * event, GstClockTime * latency)
         g_value_get_uint64 (gst_structure_id_get_value (structure,
             GST_QUARK (LATENCY)));
 }
+
+/**
+ * gst_event_new_step:
+ * @format: the format of @amount
+ * @amount: the amount of data to step
+ * @rate: the step rate
+ * @flush: flushing steps
+ * @intermediate: intermediate steps
+ *
+ * Create a new step event. The purpose of the step event is to instruct a sink
+ * to skip @amount (expressed in @format) of media. It can be used to implement
+ * stepping through the video frame by frame or for doing fast trick modes.
+ *
+ * A rate of <= 0.0 is not allowed, pause the pipeline or reverse the playback
+ * direction of the pipeline to get the same effect.
+ *
+ * The @flush flag will clear any pending data in the pipeline before starting
+ * the step operation.
+ *
+ * The @intermediate flag instructs the pipeline that this step operation is
+ * part of a larger step operation.
+ *
+ * Returns: a new #GstEvent
+ *
+ * Since: 0.10.24
+ */
+GstEvent *
+gst_event_new_step (GstFormat format, guint64 amount, gdouble rate,
+    gboolean flush, gboolean intermediate)
+{
+  GstEvent *event;
+  GstStructure *structure;
+
+  g_return_val_if_fail (rate > 0.0, NULL);
+
+  GST_CAT_INFO (GST_CAT_EVENT, "creating step event");
+
+  structure = gst_structure_id_new (GST_QUARK (EVENT_STEP),
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
+  event = gst_event_new_custom (GST_EVENT_STEP, structure);
+
+  return event;
+}
+
+/**
+ * gst_event_parse_step:
+ * @event: The event to query
+ * @format: A pointer to store the format in.
+ * @amount: A pointer to store the amount in.
+ * @rate: A pointer to store the rate in.
+ * @flush: A pointer to store the flush boolean in.
+ * @intermediate: A pointer to store the intermediate boolean in.
+ *
+ * Parse the step event.
+ *
+ * Since: 0.10.24
+ */
+void
+gst_event_parse_step (GstEvent * event, GstFormat * format, guint64 * amount,
+    gdouble * rate, gboolean * flush, gboolean * intermediate)
+{
+  const GstStructure *structure;
+
+  g_return_if_fail (GST_IS_EVENT (event));
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STEP);
+
+  structure = gst_event_get_structure (event);
+  if (format)
+    *format = g_value_get_enum (gst_structure_id_get_value (structure,
+            GST_QUARK (FORMAT)));
+  if (amount)
+    *amount = g_value_get_uint64 (gst_structure_id_get_value (structure,
+            GST_QUARK (AMOUNT)));
+  if (rate)
+    *rate = g_value_get_double (gst_structure_id_get_value (structure,
+            GST_QUARK (RATE)));
+  if (flush)
+    *flush = g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (FLUSH)));
+  if (intermediate)
+    *intermediate = g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (INTERMEDIATE)));
+}
index 1217366..89e7031 100644 (file)
@@ -92,6 +92,7 @@ typedef enum {
  *                        user requests, such as mouse or keyboard movements,
  *                        to upstream elements.
  * @GST_EVENT_LATENCY: Notification of new latency adjustment. Since: 0.10.12
+ * @GST_EVENT_STEP: A request for stepping through the media. Since: 0.10.24
  * @GST_EVENT_CUSTOM_UPSTREAM: Upstream custom event
  * @GST_EVENT_CUSTOM_DOWNSTREAM: Downstream custom event that travels in the
  *                        data flow.
@@ -124,6 +125,7 @@ typedef enum {
   GST_EVENT_SEEK                 = GST_EVENT_MAKE_TYPE (16, FLAG(UPSTREAM)),
   GST_EVENT_NAVIGATION           = GST_EVENT_MAKE_TYPE (17, FLAG(UPSTREAM)),
   GST_EVENT_LATENCY              = GST_EVENT_MAKE_TYPE (18, FLAG(UPSTREAM)),
+  GST_EVENT_STEP                 = GST_EVENT_MAKE_TYPE (19, FLAG(UPSTREAM)),
 
   /* custom events start here */
   GST_EVENT_CUSTOM_UPSTREAM      = GST_EVENT_MAKE_TYPE (32, FLAG(UPSTREAM)),
@@ -460,6 +462,12 @@ GstEvent*  gst_event_new_navigation        (GstStructure *structure);
 GstEvent*      gst_event_new_latency           (GstClockTime latency);
 void           gst_event_parse_latency         (GstEvent *event, GstClockTime *latency);
 
+/* step event */
+GstEvent*      gst_event_new_step              (GstFormat format, guint64 amount, gdouble rate,
+                                                 gboolean flush, gboolean intermediate);
+void           gst_event_parse_step            (GstEvent *event, GstFormat *format, guint64 *amount,
+                                                 gdouble *rate, gboolean *flush, gboolean *intermediate);
+
 G_END_DECLS
 
 #endif /* __GST_EVENT_H__ */
index 3bc168a..fec9a19 100644 (file)
@@ -1634,3 +1634,85 @@ gst_message_get_stream_status_object (GstMessage * message)
 
   return result;
 }
+
+/**
+ * gst_message_new_step_done:
+ * @src: The object originating the message.
+ * @format: the format of @amount
+ * @amount: the amount of stepped data
+ * @rate: the rate of the stepped amount
+ * @duration: the duration of the data
+ * @intermediate: is this an intermediate step
+ *
+ * This message is posted by elements when they complete a part, when @intermediate set
+ * to TRUE, or a complete step operation.
+ *
+ * @duration will contain the amount of time (in GST_FORMAT_TIME) of the stepped
+ * @amount of media in format @format.
+ *
+ * Returns: The new step_done message. 
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+GstMessage *
+gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
+    gdouble rate, guint64 duration, gboolean intermediate)
+{
+  GstMessage *message;
+  GstStructure *structure;
+
+  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STEP_DONE),
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+      GST_QUARK (DURATION), G_TYPE_UINT64, duration,
+      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_STEP_DONE, src, structure);
+
+  return message;
+}
+
+/**
+ * gst_message_parse_step_done:
+ * @message: A valid #GstMessage of type GST_MESSAGE_STEP_DONE.
+ * @format: result location for the format
+ * @amount: result location for the amount
+ * @rate: result location for the rate
+ * @duration: result location for the duration
+ * @intermediate: result location for the intermediate flag
+ *
+ * Extract the requested state from the request_state message.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.24
+ */
+void
+gst_message_parse_step_done (GstMessage * message, GstFormat * format,
+    guint64 * amount, gdouble * rate, guint64 * duration,
+    gboolean * intermediate)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_DONE);
+
+  if (format)
+    *format = g_value_get_enum (gst_structure_id_get_value (message->structure,
+            GST_QUARK (FORMAT)));
+  if (amount)
+    *amount =
+        g_value_get_uint64 (gst_structure_id_get_value (message->structure,
+            GST_QUARK (AMOUNT)));
+  if (rate)
+    *rate = g_value_get_double (gst_structure_id_get_value (message->structure,
+            GST_QUARK (RATE)));
+  if (duration)
+    *duration =
+        g_value_get_uint64 (gst_structure_id_get_value (message->structure,
+            GST_QUARK (DURATION)));
+  if (intermediate)
+    *intermediate =
+        g_value_get_boolean (gst_structure_id_get_value (message->structure,
+            GST_QUARK (INTERMEDIATE)));
+}
index 5790315..fe55aa5 100644 (file)
@@ -383,6 +383,12 @@ void               gst_message_parse_state_changed (GstMessage *message, GstState *oldstate,
 /* STATE_DIRTY */
 GstMessage *   gst_message_new_state_dirty     (GstObject * src);
 
+/* STEP_DONE */
+GstMessage *    gst_message_new_step_done       (GstObject * src, GstFormat format, guint64 amount,
+                                                 gdouble rate, guint64 duration, gboolean intermediate);
+void            gst_message_parse_step_done     (GstMessage * message, GstFormat *format, guint64 *amount,
+                                                 gdouble *rate, guint64 *duration, gboolean *intermediate);
+
 /* CLOCK_PROVIDE */
 GstMessage *   gst_message_new_clock_provide   (GstObject * src, GstClock *clock, gboolean ready);
 void           gst_message_parse_clock_provide (GstMessage *message, GstClock **clock,
index 64385fa..6f8fa93 100644 (file)
@@ -46,7 +46,8 @@ static const gchar *_quark_strings[] = {
   "GstMessageAsyncStart", "GstMessageRequestState", "GstMessageStreamStatus",
   "GstQueryPosition", "GstQueryDuration", "GstQueryLatency", "GstQueryConvert",
   "GstQuerySegment", "GstQuerySeeking", "GstQueryFormats", "GstQueryBuffering",
-  "GstQueryURI"
+  "GstQueryURI", "GstEventStep", "GstMessageStepDone", "amount", "flush",
+  "intermediate"
 };
 
 GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index e9d3f48..5688858 100644 (file)
@@ -109,7 +109,13 @@ typedef enum _GstQuarkId
   GST_QUARK_QUERY_FORMATS = 80,
   GST_QUARK_QUERY_BUFFERING = 81,
   GST_QUARK_QUERY_URI = 82,
-  GST_QUARK_MAX = 83
+  GST_QUARK_EVENT_STEP = 83,
+  GST_QUARK_MESSAGE_STEP_DONE = 84,
+  GST_QUARK_AMOUNT = 85,
+  GST_QUARK_FLUSH = 86,
+  GST_QUARK_INTERMEDIATE = 87,
+
+  GST_QUARK_MAX = 88
 } GstQuarkId;
 
 extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index 4374f20..f7cc829 100644 (file)
@@ -355,6 +355,7 @@ EXPORTS
        gst_event_new_new_segment_full
        gst_event_new_qos
        gst_event_new_seek
+       gst_event_new_step
        gst_event_new_tag
        gst_event_parse_buffer_size
        gst_event_parse_latency
@@ -362,6 +363,7 @@ EXPORTS
        gst_event_parse_new_segment_full
        gst_event_parse_qos
        gst_event_parse_seek
+       gst_event_parse_step
        gst_event_parse_tag
        gst_event_set_seqnum
        gst_event_type_flags_get_type
@@ -489,6 +491,7 @@ EXPORTS
        gst_message_new_segment_start
        gst_message_new_state_changed
        gst_message_new_state_dirty
+       gst_message_new_step_done
        gst_message_new_stream_status
        gst_message_new_structure_change
        gst_message_new_tag
@@ -507,6 +510,7 @@ EXPORTS
        gst_message_parse_segment_done
        gst_message_parse_segment_start
        gst_message_parse_state_changed
+       gst_message_parse_step_done
        gst_message_parse_stream_status
        gst_message_parse_structure_change
        gst_message_parse_tag