add new API for framestepping

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()
This commit is contained in:
Wim Taymans 2009-06-01 12:19:52 +02:00 committed by Wim Taymans
parent a565dbd1f3
commit 386c516e51
9 changed files with 214 additions and 15 deletions

View 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.

View 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

View 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)));
}

View 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__ */

View 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)));
}

View 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,

View 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];

View 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];

View 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