diff --git a/docs/design/draft-framestep.txt b/docs/design/draft-framestep.txt index 8f74ae3563..56bceb0b7f 100644 --- a/docs/design/draft-framestep.txt +++ b/docs/design/draft-framestep.txt @@ -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. diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 6c9fb4e87e..bd2abd076c 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -743,6 +743,9 @@ gst_event_new_navigation gst_event_new_latency gst_event_parse_latency + +gst_event_new_step +gst_event_parse_step 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 diff --git a/gst/gstevent.c b/gst/gstevent.c index bb90a3072f..ba208c1eac 100644 --- a/gst/gstevent.c +++ b/gst/gstevent.c @@ -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))); +} diff --git a/gst/gstevent.h b/gst/gstevent.h index 121736644f..89e703128e 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -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__ */ diff --git a/gst/gstmessage.c b/gst/gstmessage.c index 3bc168a6cb..fec9a1992f 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -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))); +} diff --git a/gst/gstmessage.h b/gst/gstmessage.h index 5790315d55..fe55aa5edd 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -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, diff --git a/gst/gstquark.c b/gst/gstquark.c index 64385fa375..6f8fa93e69 100644 --- a/gst/gstquark.c +++ b/gst/gstquark.c @@ -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]; diff --git a/gst/gstquark.h b/gst/gstquark.h index e9d3f48d5e..568885804b 100644 --- a/gst/gstquark.h +++ b/gst/gstquark.h @@ -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]; diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 4374f20b70..f7cc829f13 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -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