diff --git a/ChangeLog b/ChangeLog index 5b37d48711..849034cbfa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,35 @@ -2007-02-02 Wim Taymans,,, +2007-02-02 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + Add docs for new methods. + + * gst/gstevent.c: (gst_event_new_latency), + (gst_event_parse_latency): + * gst/gstevent.h: + Add new LATENCY event to configure latency in a pipeline. + API: gst_event_new_latency + API: gst_event_parse_latency + + * gst/gstmessage.c: (gst_message_new_buffering), + (gst_message_new_lost_preroll), (gst_message_new_prerolled), + (gst_message_new_latency), (gst_message_parse_buffering), + (gst_message_parse_lost_preroll): + * gst/gstmessage.h: + Added messages used in draft-latency. + API: gst_message_new_lost_preroll + API: gst_message_parse_lost_preroll + API: gst_message_new_prerolled + API: gst_message_new_latency + + * gst/gstquery.c: (gst_query_new_latency), (gst_query_set_latency), + (gst_query_parse_latency): + * gst/gstquery.h: + Implemented new latency query as in design doc. + API: gst_query_new_latency + API: gst_query_set_latency + API: gst_query_parse_latency + +2007-02-02 Wim Taymans * docs/design/draft-latency.txt: Slight redesign to allow for dynamic latency adjustments. diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 5e349e0e02..176d057184 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -639,6 +639,7 @@ gst_event_new_custom gst_event_new_eos gst_event_new_flush_start gst_event_new_flush_stop +gst_event_new_latency gst_event_new_navigation gst_event_new_new_segment gst_event_new_new_segment_full @@ -646,6 +647,7 @@ gst_event_new_qos gst_event_new_seek gst_event_new_tag gst_event_parse_buffer_size +gst_event_parse_latency gst_event_parse_new_segment gst_event_parse_new_segment_full gst_event_parse_qos @@ -1003,6 +1005,9 @@ gst_message_new_buffering gst_message_new_warning gst_message_new_duration gst_message_new_state_dirty +gst_message_new_lost_preroll +gst_message_new_prerolled +gst_message_new_latency gst_message_parse_clock_lost gst_message_parse_clock_provide gst_message_parse_error @@ -1014,6 +1019,8 @@ gst_message_parse_tag gst_message_parse_buffering gst_message_parse_warning gst_message_parse_duration +gst_message_parse_lost_preroll +gst_message_parse_prerolled gst_message_ref gst_message_unref @@ -1602,6 +1609,10 @@ gst_query_new_duration gst_query_set_duration gst_query_parse_duration +gst_query_new_latency +gst_query_parse_latency +gst_query_set_latency + gst_query_new_seeking gst_query_set_seeking gst_query_parse_seeking @@ -1616,7 +1627,7 @@ gst_query_new_segment gst_query_set_segment gst_query_parse_segment -SUBSECTION Standard> + GstQueryClass GST_QUERY GST_IS_QUERY diff --git a/gst/gstevent.c b/gst/gstevent.c index 3c1c00e84b..de94c812b7 100644 --- a/gst/gstevent.c +++ b/gst/gstevent.c @@ -115,7 +115,7 @@ static GstEventQuarks event_quarks[] = { {GST_EVENT_QOS, "qos", 0}, {GST_EVENT_SEEK, "seek", 0}, {GST_EVENT_NAVIGATION, "navigation", 0}, - {GST_EVENT_SET_LATENCY, "set-latency", 0}, + {GST_EVENT_LATENCY, "latency", 0}, {GST_EVENT_CUSTOM_UPSTREAM, "custom-upstream", 0}, {GST_EVENT_CUSTOM_DOWNSTREAM, "custom-downstream", 0}, {GST_EVENT_CUSTOM_DOWNSTREAM_OOB, "custom-downstream-oob", 0}, @@ -913,3 +913,52 @@ gst_event_new_navigation (GstStructure * structure) return gst_event_new_custom (GST_EVENT_NAVIGATION, structure); } + +/** + * gst_event_new_latency: + * @latency: the new latency value + * + * Create a new latency event. The event is sent upstream from the sinks and + * notifies elements that they should add an additional @latency to the + * timestamps before synchronising against the clock. + * + * The latency is mostly used in live sinks and is always expressed in + * the time format. + * + * Returns: a new #GstEvent + * + * Since: 0.10.12 + */ +GstEvent * +gst_event_new_latency (GstClockTime latency) +{ + GST_CAT_INFO (GST_CAT_EVENT, + "creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); + + return gst_event_new_custom (GST_EVENT_LATENCY, + gst_structure_new ("GstEventLatency", + "latency", G_TYPE_UINT64, latency, NULL)); +} + +/** + * gst_event_parse_latency: + * @event: The event to query + * @latency: A pointer to store the latency in. + * + * Get the latency in the latency event. + * + * Since: 0.10.12 + */ +void +gst_event_parse_latency (GstEvent * event, GstClockTime * latency) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_LATENCY); + + structure = gst_event_get_structure (event); + if (latency) + *latency = + g_value_get_uint64 (gst_structure_get_value (structure, "latency")); +} diff --git a/gst/gstevent.h b/gst/gstevent.h index d772e5dff5..3232f044fc 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -91,7 +91,7 @@ typedef enum { * @GST_EVENT_NAVIGATION: Navigation events are usually used for communicating * user requests, such as mouse or keyboard movements, * to upstream elements. - * @GST_EVENT_SET_LATENCY: A request for a new latency adjustment. Since: 0.10.12 + * @GST_EVENT_LATENCY: Notification of new latency adjustment. Since: 0.10.12 * @GST_EVENT_CUSTOM_UPSTREAM: Upstream custom event * @GST_EVENT_CUSTOM_DOWNSTREAM: Downstream custom event that travels in the * data flow. @@ -123,7 +123,7 @@ typedef enum { GST_EVENT_QOS = GST_EVENT_MAKE_TYPE (15, FLAG(UPSTREAM)), GST_EVENT_SEEK = GST_EVENT_MAKE_TYPE (16, FLAG(UPSTREAM)), GST_EVENT_NAVIGATION = GST_EVENT_MAKE_TYPE (17, FLAG(UPSTREAM)), - GST_EVENT_SET_LATENCY = GST_EVENT_MAKE_TYPE (18, FLAG(UPSTREAM)), + GST_EVENT_LATENCY = GST_EVENT_MAKE_TYPE (18, FLAG(UPSTREAM)), /* custom events start here */ GST_EVENT_CUSTOM_UPSTREAM = GST_EVENT_MAKE_TYPE (32, FLAG(UPSTREAM)), @@ -423,6 +423,10 @@ void gst_event_parse_seek (GstEvent *event, gdouble *rate, GstFormat *format, /* navigation event */ GstEvent* gst_event_new_navigation (GstStructure *structure); +/* latency event */ +GstEvent* gst_event_new_latency (GstClockTime latency); +void gst_event_parse_latency (GstEvent *event, GstClockTime *latency); + G_END_DECLS #endif /* __GST_EVENT_H__ */ diff --git a/gst/gstmessage.c b/gst/gstmessage.c index ba3f86cba6..534a81dd16 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -108,6 +108,9 @@ static GstMessageQuarks message_quarks[] = { {GST_MESSAGE_SEGMENT_START, "segment-start", 0}, {GST_MESSAGE_SEGMENT_DONE, "segment-done", 0}, {GST_MESSAGE_DURATION, "duration", 0}, + {GST_MESSAGE_LOST_PREROLL, "lost-preroll", 0}, + {GST_MESSAGE_PREROLLED, "prerolled", 0}, + {GST_MESSAGE_LATENCY, "latency", 0}, {0, NULL, 0} }; @@ -696,6 +699,74 @@ gst_message_new_duration (GstObject * src, GstFormat format, gint64 duration) return message; } +/** + * gst_message_new_lost_preroll: + * @src: The object originating the message. + * @pending: The state of @src when it lost preroll + * + * Returns: The new lost_preroll message. + * + * MT safe. + * + * Since: 0.10.12 + */ +GstMessage * +gst_message_new_lost_preroll (GstObject * src, GstState pending) +{ + GstMessage *message; + + message = gst_message_new_custom (GST_MESSAGE_LOST_PREROLL, src, + gst_structure_new ("GstMessageLostPreroll", + "pending", GST_TYPE_STATE, pending, NULL)); + + return message; +} + +/** + * gst_message_new_prerolled: + * @src: The object originating the message. + * + * This message is posted by sinks when they preroll. + * + * Returns: The new prerolled message. + * + * MT safe. + * + * Since: 0.10.12 + */ +GstMessage * +gst_message_new_prerolled (GstObject * src) +{ + GstMessage *message; + + message = gst_message_new_custom (GST_MESSAGE_PREROLLED, src, NULL); + + return message; +} + +/** + * gst_message_new_latency: + * @src: The object originating the message. + * + * This message can be posted by elements when their latency requirements have + * changed. + * + * Returns: The new latency message. + * + * MT safe. + * + * Since: 0.10.12 + */ +GstMessage * +gst_message_new_latency (GstObject * src) +{ + GstMessage *message; + + message = gst_message_new_custom (GST_MESSAGE_LATENCY, src, NULL); + + return message; +} + /** * gst_message_get_structure: * @message: The #GstMessage. @@ -1021,3 +1092,29 @@ gst_message_parse_duration (GstMessage * message, GstFormat * format, *duration = g_value_get_int64 (gst_structure_get_value (structure, "duration")); } + +/** + * gst_message_parse_lost_preroll: + * @message: A valid #GstMessage of type GST_MESSAGE_LOST_PREROLL. + * @pending: Result location for the pending state, or NULL + * + * Extract the pending state from the lost_preroll message. The pending state is + * the state the element was in when it lost the preroll buffer. + * + * MT safe. + * + * Since: 0.10.12 + */ +void +gst_message_parse_lost_preroll (GstMessage * message, GstState * pending) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_LOST_PREROLL); + + structure = gst_message_get_structure (message); + if (pending) + *pending = + g_value_get_enum (gst_structure_get_value (structure, "pending")); +} diff --git a/gst/gstmessage.h b/gst/gstmessage.h index 23e3f2d8a7..9fc745dfc8 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -55,6 +55,11 @@ typedef struct _GstMessageClass GstMessageClass; * @GST_MESSAGE_SEGMENT_START: pipeline started playback of a segment. * @GST_MESSAGE_SEGMENT_DONE: pipeline completed playback of a segment. * @GST_MESSAGE_DURATION: The duration of a pipeline changed. + * @GST_MESSAGE_LOST_PREROLL: Posted by ASYNC elements when they are flushed. + * Since: 0.10.12 + * @GST_MESSAGE_PREROLLED: Posted by elements when they preroll. Since: 0.10.12 + * @GST_MESSAGE_LATENCY: Posted by elements when their latency changes. The + * pipeline will calculate and distribute a new latency. Since: 0.10.12 * @GST_MESSAGE_ANY: mask for all of the above messages. * * The different message types that are available. @@ -84,6 +89,9 @@ typedef enum GST_MESSAGE_SEGMENT_START = (1 << 16), GST_MESSAGE_SEGMENT_DONE = (1 << 17), GST_MESSAGE_DURATION = (1 << 18), + GST_MESSAGE_LOST_PREROLL = (1 << 19), + GST_MESSAGE_PREROLLED = (1 << 20), + GST_MESSAGE_LATENCY = (1 << 21), GST_MESSAGE_ANY = ~0 } GstMessageType; @@ -259,6 +267,9 @@ GstMessage * gst_message_new_element (GstObject * src, GstStructure * structure GstMessage * gst_message_new_segment_start (GstObject * src, GstFormat format, gint64 position); GstMessage * gst_message_new_segment_done (GstObject * src, GstFormat format, gint64 position); GstMessage * gst_message_new_duration (GstObject * src, GstFormat format, gint64 duration); +GstMessage * gst_message_new_lost_preroll (GstObject * src, GstState pending); +GstMessage * gst_message_new_prerolled (GstObject * src); +GstMessage * gst_message_new_latency (GstObject * src); GstMessage * gst_message_new_custom (GstMessageType type, GstObject * src, GstStructure * structure); @@ -275,6 +286,7 @@ void gst_message_parse_new_clock (GstMessage *message, GstClock **clock); void gst_message_parse_segment_start (GstMessage *message, GstFormat *format, gint64 *position); void gst_message_parse_segment_done (GstMessage *message, GstFormat *format, gint64 *position); void gst_message_parse_duration (GstMessage *message, GstFormat *format, gint64 *duration); +void gst_message_parse_lost_preroll (GstMessage *message, GstState *pending); const GstStructure * gst_message_get_structure (GstMessage *message); diff --git a/gst/gstquery.c b/gst/gstquery.c index 2d9750e037..29ba21d859 100644 --- a/gst/gstquery.c +++ b/gst/gstquery.c @@ -536,6 +536,92 @@ gst_query_parse_duration (GstQuery * query, GstFormat * format, GST_QUARK (DURATION))); } +/** + * gst_query_new_latency: + * + * Constructs a new latency query object. + * Use gst_query_unref() when done with it. A latency query is usually performed + * by sinks to compensate for additional latency introduced by elements in the + * pipeline. + * + * Returns: A #GstQuery + * + * Since: 0.10.12 + */ +GstQuery * +gst_query_new_latency (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_empty_new ("GstQueryLatency"); + gst_structure_set (structure, + "live", G_TYPE_BOOLEAN, FALSE, + "upstream-live", G_TYPE_BOOLEAN, FALSE, + "min-latency", G_TYPE_UINT64, (gint64) 0, + "max-latency", G_TYPE_UINT64, (gint64) - 1, NULL); + + query = gst_query_new (GST_QUERY_LATENCY, structure); + + return query; +} + +/** + * gst_query_set_latency: + * @query: a #GstQuery + * @live: if there is a live element upstream + * @min_latency: the minimal latency of the live element + * @max_latency: the maximal latency of the live element + * + * Answer a latency query by setting the requested values in the given format. + * + * Since: 0.10.12 + */ +void +gst_query_set_latency (GstQuery * query, gboolean live, + GstClockTime min_latency, GstClockTime max_latency) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY); + + structure = gst_query_get_structure (query); + gst_structure_set (structure, + "live", G_TYPE_BOOLEAN, live, + "min-latency", G_TYPE_UINT64, min_latency, + "max-latency", G_TYPE_UINT64, max_latency, NULL); +} + +/** + * gst_query_parse_latency: + * @query: a #GstQuery + * @live: storage for live or NULL + * @min_latency: the storage for the min latency or NULL + * @max_latency: the storage for the max latency or NULL + * + * Parse a latency query answer. + * + * Since: 0.10.12 + */ +void +gst_query_parse_latency (GstQuery * query, gboolean * live, + GstClockTime * min_latency, GstClockTime * max_latency) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY); + + structure = gst_query_get_structure (query); + if (live) + *live = g_value_get_boolean (gst_structure_get_value (structure, "live")); + if (min_latency) + *min_latency = g_value_get_uint64 (gst_structure_get_value (structure, + "min-latency")); + if (max_latency) + *max_latency = g_value_get_uint64 (gst_structure_get_value (structure, + "max-latency")); +} + /** * gst_query_new_convert: * @src_format: the source #GstFormat for the new query diff --git a/gst/gstquery.h b/gst/gstquery.h index 1acc2f9d8f..88d552abb8 100644 --- a/gst/gstquery.h +++ b/gst/gstquery.h @@ -80,8 +80,8 @@ typedef struct _GstQueryClass GstQueryClass; struct _GstQueryTypeDefinition { GstQueryType value; - gchar *nick; - gchar *description; + gchar *nick; + gchar *description; GQuark quark; }; @@ -205,6 +205,13 @@ GstQuery* gst_query_new_duration (GstFormat format); void gst_query_set_duration (GstQuery *query, GstFormat format, gint64 duration); void gst_query_parse_duration (GstQuery *query, GstFormat *format, gint64 *duration); +/* latency query */ +GstQuery* gst_query_new_latency (void); +void gst_query_set_latency (GstQuery *query, gboolean live, GstClockTime min_latency, + GstClockTime max_latency); +void gst_query_parse_latency (GstQuery *query, gboolean *live, GstClockTime *min_latency, + GstClockTime *max_latency); + /* convert query */ GstQuery* gst_query_new_convert (GstFormat src_format, gint64 value, GstFormat dest_format); void gst_query_set_convert (GstQuery *query, GstFormat src_format, gint64 src_value, @@ -218,15 +225,12 @@ void gst_query_set_segment (GstQuery *query, gdouble rate, void gst_query_parse_segment (GstQuery *query, gdouble *rate, GstFormat *format, gint64 *start_value, gint64 *stop_value); - /* application specific query */ GstQuery * gst_query_new_application (GstQueryType type, GstStructure *structure); - - GstStructure * gst_query_get_structure (GstQuery *query); -/* moved from old gstqueryutils.h */ +/* seeking query */ GstQuery* gst_query_new_seeking (GstFormat format); void gst_query_set_seeking (GstQuery *query, GstFormat format, gboolean seekable, @@ -236,7 +240,7 @@ void gst_query_parse_seeking (GstQuery *query, GstFormat *for gboolean *seekable, gint64 *segment_start, gint64 *segment_end); - +/* formats query */ GstQuery* gst_query_new_formats (void); void gst_query_set_formats (GstQuery *query, gint n_formats, ...); void gst_query_set_formatsv (GstQuery *query, gint n_formats, GstFormat *formats);