diff -r 000000000000 -r 0e761a78d257 gstreamer_core/gst/gstevent.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gstreamer_core/gst/gstevent.c Thu Dec 17 08:53:32 2009 +0200 @@ -0,0 +1,1072 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstevent.c: GstEvent subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:gstevent + * @short_description: Structure describing events that are passed up and down + * a pipeline + * @see_also: #GstPad, #GstElement + * + * The event class provides factory methods to construct and functions query + * (parse) events. + * + * Events are usually created with gst_event_new_*() which takes event-type + * specific parameters as arguments. + * To send an event application will usually use gst_element_send_event() and + * elements will use gst_pad_send_event() or gst_pad_push_event(). + * The event should be unreffed with gst_event_unref() if it has not been sent. + * + * Events that have been received can be parsed with their respective + * gst_event_parse_*() functions. It is valid to pass %NULL for unwanted details. + * + * Events are passed between elements in parallel to the data stream. Some events + * are serialized with buffers, others are not. Some events only travel downstream, + * others only upstream. Some events can travel both upstream and downstream. + * + * The events are used to signal special conditions in the datastream such as + * EOS (end of stream) or the start of a new stream-segment. + * Events are also used to flush the pipeline of any pending data. + * + * Most of the event API is used inside plugins. Applications usually only + * construct and use seek events. + * To do that gst_event_new_seek() is used to create a seek event. It takes + * the needed parameters to specity seeking time and mode. + * + * performing a seek on a pipeline + * + * GstEvent *event; + * gboolean result; + * ... + * // construct a seek event to play the media from second 2 to 5, flush + * // the pipeline to decrease latency. + * event = gst_event_new_seek (1.0, + * GST_FORMAT_TIME, + * GST_SEEK_FLAG_FLUSH, + * GST_SEEK_TYPE_SET, 2 * GST_SECOND, + * GST_SEEK_TYPE_SET, 5 * GST_SECOND); + * ... + * result = gst_element_send_event (pipeline, event); + * if (!result) + * g_warning ("seek failed"); + * ... + * + * + * + * Last reviewed on 2006-09-6 (0.10.10) + */ + + +#include "gst_private.h" +#include /* memcpy */ + +#include "gstinfo.h" +#include "gstevent.h" +#include "gstenumtypes.h" +#include "gstutils.h" + +static void gst_event_init (GTypeInstance * instance, gpointer g_class); +static void gst_event_class_init (gpointer g_class, gpointer class_data); +static void gst_event_finalize (GstEvent * event); +static GstEvent *_gst_event_copy (GstEvent * event); + +static GstMiniObjectClass *parent_class = NULL; +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + + +void +_gst_event_initialize (void) +{ + g_type_class_ref (gst_event_get_type ()); + g_type_class_ref (gst_seek_flags_get_type ()); + g_type_class_ref (gst_seek_type_get_type ()); +} + +typedef struct +{ + const gint type; + const gchar *name; + GQuark quark; +} GstEventQuarks; + +static GstEventQuarks event_quarks[] = { + {GST_EVENT_UNKNOWN, "unknown", 0}, + {GST_EVENT_FLUSH_START, "flush-start", 0}, + {GST_EVENT_FLUSH_STOP, "flush-stop", 0}, + {GST_EVENT_EOS, "eos", 0}, + {GST_EVENT_NEWSEGMENT, "newsegment", 0}, + {GST_EVENT_TAG, "tag", 0}, + {GST_EVENT_BUFFERSIZE, "buffersize", 0}, + {GST_EVENT_QOS, "qos", 0}, + {GST_EVENT_SEEK, "seek", 0}, + {GST_EVENT_NAVIGATION, "navigation", 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}, + {GST_EVENT_CUSTOM_BOTH, "custom-both", 0}, + {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0}, + + {0, NULL, 0} +}; + +/** + * gst_event_type_get_name: + * @type: the event type + * + * Get a printable name for the given event type. Do not modify or free. + * + * Returns: a reference to the static name of the event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +const gchar * +gst_event_type_get_name (GstEventType type) +{ + gint i; + + for (i = 0; event_quarks[i].name; i++) { + if (type == event_quarks[i].type) + return event_quarks[i].name; + } + return "unknown"; +} + +/** + * gst_event_type_to_quark: + * @type: the event type + * + * Get the unique quark for the given event type. + * + * Returns: the quark associated with the event type + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GQuark +gst_event_type_to_quark (GstEventType type) +{ + gint i; + + for (i = 0; event_quarks[i].name; i++) { + if (type == event_quarks[i].type) + return event_quarks[i].quark; + } + return 0; +} + +/** + * gst_event_type_get_flags: + * @type: a #GstEventType + * + * Gets the #GstEventTypeFlags associated with @type. + * + * Returns: a #GstEventTypeFlags. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEventTypeFlags +gst_event_type_get_flags (GstEventType type) +{ + GstEventTypeFlags ret; + + ret = type & ((1 << GST_EVENT_TYPE_SHIFT) - 1); + + return ret; +} +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + + +GType +gst_event_get_type (void) +{ + static GType _gst_event_type = 0; + int i; + + if (G_UNLIKELY (_gst_event_type == 0)) { + static const GTypeInfo event_info = { + sizeof (GstEventClass), + NULL, + NULL, + gst_event_class_init, + NULL, + NULL, + sizeof (GstEvent), + 0, + gst_event_init, + NULL + }; + + _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT, + "GstEvent", &event_info, 0); + + for (i = 0; event_quarks[i].name; i++) { + event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name); + } + } + + return _gst_event_type; +} + +static void +gst_event_class_init (gpointer g_class, gpointer class_data) +{ + GstEventClass *event_class = GST_EVENT_CLASS (g_class); + + parent_class = g_type_class_peek_parent (g_class); + + event_class->mini_object_class.copy = + (GstMiniObjectCopyFunction) _gst_event_copy; + event_class->mini_object_class.finalize = + (GstMiniObjectFinalizeFunction) gst_event_finalize; +} + +static void +gst_event_init (GTypeInstance * instance, gpointer g_class) +{ + GstEvent *event; + + event = GST_EVENT (instance); + + GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE; +} + +static void +gst_event_finalize (GstEvent * event) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (GST_IS_EVENT (event)); + + GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event, + GST_EVENT_TYPE_NAME (event)); + + if (GST_EVENT_SRC (event)) { + gst_object_unref (GST_EVENT_SRC (event)); + GST_EVENT_SRC (event) = NULL; + } + if (event->structure) { + gst_structure_set_parent_refcount (event->structure, NULL); + gst_structure_free (event->structure); + } + + GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (event)); +} + +static GstEvent * +_gst_event_copy (GstEvent * event) +{ + GstEvent *copy; + + copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT); + + GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event); + GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event); + + if (GST_EVENT_SRC (event)) { + GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event)); + } + if (event->structure) { + copy->structure = gst_structure_copy (event->structure); + gst_structure_set_parent_refcount (copy->structure, + ©->mini_object.refcount); + } + return copy; +} + +static GstEvent * +gst_event_new (GstEventType type) +{ + GstEvent *event; + + event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT); + + GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s %d", event, + gst_event_type_get_name (type), type); + + event->type = type; + event->src = NULL; + event->structure = NULL; + + return event; +} + +/** + * gst_event_new_custom: + * @type: The type of the new event + * @structure: The structure for the event. The event will take ownership of + * the structure. + * + * Create a new custom-typed event. This can be used for anything not + * handled by other event-specific functions to pass an event to another + * element. + * + * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro, + * assigning a free number and filling in the correct direction and + * serialization flags. + * + * New custom events can also be created by subclassing the event type if + * needed. + * + * Returns: The new custom event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEvent * +gst_event_new_custom (GstEventType type, GstStructure * structure) +{ + GstEvent *event; + + /* structure must not have a parent */ + if (structure) + g_return_val_if_fail (structure->parent_refcount == NULL, NULL); + + event = gst_event_new (type); + if (structure) { + gst_structure_set_parent_refcount (structure, &event->mini_object.refcount); + event->structure = structure; + } + return event; +} + +/** + * gst_event_get_structure: + * @event: The #GstEvent. + * + * Access the structure of the event. + * + * Returns: The structure of the event. The structure is still + * owned by the event, which means that you should not free it and + * that the pointer becomes invalid when you free the event. + * + * MT safe. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +const GstStructure * +gst_event_get_structure (GstEvent * event) +{ + g_return_val_if_fail (GST_IS_EVENT (event), NULL); + + return event->structure; +} + +/** + * gst_event_new_flush_start: + * + * Allocate a new flush start event. The flush start event can be sent + * upstream and downstream and travels out-of-bounds with the dataflow. + * + * It marks pads as being flushing and will make them return + * #GST_FLOW_WRONG_STATE when used for data flow with gst_pad_push(), + * gst_pad_chain(), gst_pad_alloc_buffer(), gst_pad_get_range() and + * gst_pad_pull_range(). Any event (except a #GST_EVENT_FLUSH_STOP) received + * on a flushing pad will return %FALSE immediately. + * + * Elements should unlock any blocking functions and exit their streaming + * functions as fast as possible when this event is received. + * + * This event is typically generated after a seek to flush out all queued data + * in the pipeline so that the new media is played as soon as possible. + * + * Returns: A new flush start event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEvent * +gst_event_new_flush_start (void) +{ + return gst_event_new (GST_EVENT_FLUSH_START); +} + +/** + * gst_event_new_flush_stop: + * + * Allocate a new flush stop event. The flush stop event can be sent + * upstream and downstream and travels out-of-bounds with the dataflow. + * It is typically sent after sending a FLUSH_START event to make the + * pads accept data again. + * + * Elements can process this event synchronized with the dataflow since + * the preceeding FLUSH_START event stopped the dataflow. + * + * This event is typically generated to complete a seek and to resume + * dataflow. + * + * Returns: A new flush stop event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEvent * +gst_event_new_flush_stop (void) +{ + return gst_event_new (GST_EVENT_FLUSH_STOP); +} + +/** + * gst_event_new_eos: + * + * Create a new EOS event. The eos event can only travel downstream + * synchronized with the buffer flow. Elements that receive the EOS + * event on a pad can return #GST_FLOW_UNEXPECTED as a #GstFlowReturn + * when data after the EOS event arrives. + * + * The EOS event will travel down to the sink elements in the pipeline + * which will then post the #GST_MESSAGE_EOS on the bus after they have + * finished playing any buffered data. + * + * When all sinks have posted an EOS message, an EOS message is + * forwarded to the application. + * + * Returns: The new EOS event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEvent * +gst_event_new_eos (void) +{ + return gst_event_new (GST_EVENT_EOS); +} + +/** + * gst_event_new_new_segment: + * @update: is this segment an update to a previous one + * @rate: a new rate for playback + * @format: The format of the segment values + * @start: the start value of the segment + * @stop: the stop value of the segment + * @position: stream position + * + * Allocate a new newsegment event with the given format/ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif +values tripplets + * + * This method calls gst_event_new_new_segment_full() passing a default + * value of 1.0 for applied_rate + * + * Returns: A new newsegment event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEvent * +gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format, + gint64 start, gint64 stop, gint64 position) +{ + return gst_event_new_new_segment_full (update, rate, 1.0, format, start, + stop, position); +} + +/** + * gst_event_parse_new_segment: + * @event: The event to query + * @update: A pointer to the update flag of the segment + * @rate: A pointer to the rate of the segment + * @format: A pointer to the format of the newsegment values + * @start: A pointer to store the start value in + * @stop: A pointer to store the stop value in + * @position: A pointer to store the stream time in + * + * Get the update flag, rate, format, start, stop and position in the + * newsegment event. In general, gst_event_parse_new_segment_full() should + * be used instead of this, to also retrieve the applied_rate value of the + * segment. See gst_event_new_new_segment_full() for a full description + * of the newsegment event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_event_parse_new_segment (GstEvent * event, gboolean * update, + gdouble * rate, GstFormat * format, gint64 * start, + gint64 * stop, gint64 * position) +{ + gst_event_parse_new_segment_full (event, update, rate, NULL, format, start, + stop, position); +} + +/** + * gst_event_new_new_segment_full: + * @update: Whether this segment is an update to a previous one + * @rate: A new rate for playback + * @applied_rate: The rate factor which has already been applied + * @format: The format of the segment values + * @start: The start value of the segment + * @stop: The stop value of the segment + * @position: stream position + * + * Allocate a new newsegment event with the given format/values triplets. + * + * The newsegment event marks the range of buffers to be processed. All + * data not within the segment range is not to be processed. This can be + * used intelligently by plugins to apply more efficient methods of skipping + * unneeded data. + * + * The position value of the segment is used in conjunction with the start + * value to convert the buffer timestamps into the stream time. This is + * usually done in sinks to report the current stream_time. + * @position represents the stream_time of a buffer carrying a timestamp of + * @start. @position cannot be -1. + * + * @start cannot be -1, @stop can be -1. If there + * is a valid @stop given, it must be greater or equal the @start, including + * when the indicated playback @rate is < 0. + * + * The @applied_rate value provides information about any rate adjustment that + * has already been made to the timestamps and content on the buffers of the + * stream. (@rate * @applied_rate) should always equal the rate that has been + * requested for playback. For example, if an element has an input segment + * with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust + * incoming timestamps and buffer content by half and output a newsegment event + * with @rate of 1.0 and @applied_rate of 2.0 + * + * After a newsegment event, the buffer stream time is calculated with: + * + * position + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate) + * + * Returns: A new newsegment event. + * + * Since: 0.10.6 + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif +GstEvent * +gst_event_new_new_segment_full (gboolean update, gdouble rate, + gdouble applied_rate, GstFormat format, gint64 start, gint64 stop, + gint64 position) +{ + g_return_val_if_fail (rate != 0.0, NULL); + g_return_val_if_fail (applied_rate != 0.0, NULL); + + if (format == GST_FORMAT_TIME) { + GST_CAT_INFO (GST_CAT_EVENT, + "creating newsegment update %d, rate %lf, format GST_FORMAT_TIME, " + "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT + ", position %" GST_TIME_FORMAT, + update, rate, GST_TIME_ARGS (start), + GST_TIME_ARGS (stop), GST_TIME_ARGS (position)); + } else { + GST_CAT_INFO (GST_CAT_EVENT, + "creating newsegment update %d, rate %lf, format %d, " + "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %" + G_GINT64_FORMAT, update, rate, format, start, stop, position); + } + + g_return_val_if_fail (position != -1, NULL); + g_return_val_if_fail (start != -1, NULL); + if (stop != -1) + g_return_val_if_fail (start <= stop, NULL); + + return gst_event_new_custom (GST_EVENT_NEWSEGMENT, + gst_structure_new ("GstEventNewsegment", + "update", G_TYPE_BOOLEAN, update, + "rate", G_TYPE_DOUBLE, rate, + "applied_rate", G_TYPE_DOUBLE, applied_rate, + "format", GST_TYPE_FORMAT, format, + "start", G_TYPE_INT64, start, + "stop", G_TYPE_INT64, stop, + "position", G_TYPE_INT64, position, NULL)); +} + +/** + * gst_event_parse_new_segment_full: + * @event: The event to query + * @update: A pointer to the update flag of the segment + * @rate: A pointer to the rate of the segment + * @applied_rate: A pointer to the applied_rate of the segment + * @format: A pointer to the format of the newsegment values + * @start: A pointer to store the start value in + * @stop: A pointer to store the stop value in + * @position: A pointer to store the stream time in + * + * Get the update, rate, applied_rate, format, start, stop and + * position in the newsegment event. See gst_event_new_new_segment_full() + * for a full description of the newsegment event. + * + * Since: 0.10.6 + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_event_parse_new_segment_full (GstEvent * event, gboolean * update, + gdouble * rate, gdouble * applied_rate, GstFormat * format, + gint64 * start, gint64 * stop, gint64 * position) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT); + + structure = gst_event_get_structure (event); + if (G_LIKELY (update)) + *update = + g_value_get_boolean (gst_structure_get_value (structure, "update")); + if (G_LIKELY (rate)) + *rate = g_value_get_double (gst_structure_get_value (structure, "rate")); + if (G_LIKELY (applied_rate)) + *applied_rate = + g_value_get_double (gst_structure_get_value (structure, + "applied_rate")); + if (G_LIKELY (format)) + *format = g_value_get_enum (gst_structure_get_value (structure, "format")); + if (G_LIKELY (start)) + *start = g_value_get_int64 (gst_structure_get_value (structure, "start")); + if (G_LIKELY (stop)) + *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop")); + if (G_LIKELY (position)) + *position = + g_value_get_int64 (gst_structure_get_value (structure, "position")); +} + +/** + * gst_event_new_tag: + * @taglist: metadata list + * + * Generates a metadata tag event from the given @taglist. + * + * Returns: a new #GstEvent + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEvent * +gst_event_new_tag (GstTagList * taglist) +{ + g_return_val_if_fail (taglist != NULL, NULL); + + return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist); +} + +/** + * gst_event_parse_tag: + * @event: a tag event + * @taglist: pointer to metadata list + * + * Parses a tag @event and stores the results in the given @taglist location. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_event_parse_tag (GstEvent * event, GstTagList ** taglist) +{ + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG); + + if (taglist) + *taglist = (GstTagList *) event->structure; +} + +/* buffersize event */ +/** + * gst_event_new_buffer_size: + * @format: buffer format + * @minsize: minimum buffer size + * @maxsize: maximum buffer size + * @async: thread behavior + * + * Create a new buffersize event. The event is sent downstream and notifies + * elements that they should provide a buffer of the specified dimensions. + * + * When the @async flag is set, a thread boundary is prefered. + * + * Returns: a new #GstEvent + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEvent * +gst_event_new_buffer_size (GstFormat format, gint64 minsize, + gint64 maxsize, gboolean async) +{ + GST_CAT_INFO (GST_CAT_EVENT, + "creating buffersize format %d, minsize %" G_GINT64_FORMAT + ", maxsize %" G_GINT64_FORMAT ", async %d", format, + minsize, maxsize, async); + + return gst_event_new_custom (GST_EVENT_BUFFERSIZE, + gst_structure_new ("GstEventBufferSize", + "format", GST_TYPE_FORMAT, format, + "minsize", G_TYPE_INT64, minsize, + "maxsize", G_TYPE_INT64, maxsize, + "async", G_TYPE_BOOLEAN, async, NULL)); +} + +/** + * gst_event_parse_buffer_size: + * @event: The event to query + * @format: A pointer to store the format in + * @minsize: A pointer to store the minsize in + * @maxsize: A pointer to store the maxsize in + * @async: A pointer to store the async-flag in + * + * Get the format, minsize, maxsize and async-flag in the buffersize event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_event_parse_buffer_size (GstEvent * event, GstFormat * format, + gint64 * minsize, gint64 * maxsize, gboolean * async) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE); + + structure = gst_event_get_structure (event); + if (format) + *format = g_value_get_enum (gst_structure_get_value (structure, "format")); + if (minsize) + *minsize = + g_value_get_int64 (gst_structure_get_value (structure, "minsize")); + if (maxsize) + *maxsize = + g_value_get_int64 (gst_structure_get_value (structure, "maxsize")); + if (async) + *async = g_value_get_boolean (gst_structure_get_value (structure, "async")); +} + +/** + * gst_event_new_qos: + * @proportion: the proportion of the qos message + * @diff: The time difference of the last Clock sync + * @timestamp: The timestamp of the buffer + * + * Allocate a new qos event with the given values. + * The QOS event is generated in an element that wants an upstream + * element to either reduce or increase its rate because of + * high/low CPU load or other resource usage such as network performance. + * Typically sinks generate these events for each buffer they receive. + * + * @proportion indicates the real-time performance of the streaming in the + * element that generated the QoS event (usually the sink). The value is + * generally computed based on more long term statistics about the streams + * timestamps compared to the clock. + * A value < 1.0 indicates that the upstream element is producing data faster + * than real-time. A value > 1.0 indicates that the upstream element is not + * producing data fast enough. 1.0 is the ideal @proportion value. The + * proportion value can safely be used to lower or increase the quality of + * the element. + * + * @diff is the difference against the clock in running time of the last + * buffer that caused the element to generate the QOS event. A negative value + * means that the buffer with @timestamp arrived in time. A positive value + * indicates how late the buffer with @timestamp was. + * + * @timestamp is the timestamp of the last buffer that cause the element + * to generate the QOS event. It is expressed in running time and thus an ever + * increasing value. + * + * The upstream element can use the @diff and @timestamp values to decide + * whether to process more buffers. For possitive @diff, all buffers with + * timestamp <= @timestamp + @diff will certainly arrive late in the sink + * as well. + * + * The application can use general event probes to intercept the QoS + * event and implement custom application specific QoS handling. + * + * Returns: A new QOS event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEvent * +gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff, + GstClockTime timestamp) +{ + GST_CAT_INFO (GST_CAT_EVENT, + "creating qos proportion %lf, diff %" G_GINT64_FORMAT + ", timestamp %" GST_TIME_FORMAT, proportion, + diff, GST_TIME_ARGS (timestamp)); + + return gst_event_new_custom (GST_EVENT_QOS, + gst_structure_new ("GstEventQOS", + "proportion", G_TYPE_DOUBLE, proportion, + "diff", G_TYPE_INT64, diff, + "timestamp", G_TYPE_UINT64, timestamp, NULL)); +} + +/** + * gst_event_parse_qos: + * @event: The event to query + * @proportion: A pointer to store the proportion in + * @diff: A pointer to store the diff in + * @timestamp: A pointer to store the timestamp in + * + * Get the proportion, diff and timestamp in the qos event. See + * gst_event_new_qos() for more information about the different QoS values. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_event_parse_qos (GstEvent * event, gdouble * proportion, + GstClockTimeDiff * diff, GstClockTime * timestamp) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS); + + structure = gst_event_get_structure (event); + if (proportion) + *proportion = + g_value_get_double (gst_structure_get_value (structure, "proportion")); + if (diff) + *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff")); + if (timestamp) + *timestamp = + g_value_get_uint64 (gst_structure_get_value (structure, "timestamp")); +} + +/** + * gst_event_new_seek: + * @rate: The new playback rate + * @format: The format of the seek values + * @flags: The optional seek flags + * @start_type: The type and flags for the new start position + * @start: The value of the new start position + * @stop_type: The type and flags for the new stop position + * @stop: The value of the new stop position + * + * Allocate a new seek event with the given parameters. + * + * The seek event configures playback of the pipeline between @start to @stop + * at the speed given in @rate, also called a playback segment. + * The @start and @stop values are expressed in @format. + * + * A @rate of 1.0 means normal playback rate, 2.0 means double speed. + * Negatives values means backwards playback. A value of 0.0 for the + * rate is not allowed and should be accomplished instead by PAUSING the + * pipeline. + * + * A pipeline has a default playback segment configured with a start + * position of 0, a stop position of -1 and a rate of 1.0. The currently + * configured playback segment can be queried with #GST_QUERY_SEGMENT. + * + * @start_type and @stop_type specify how to adjust the currently configured + * start and stop fields in @segment. Adjustments can be made relative or + * absolute to the last configured values. A type of #GST_SEEK_TYPE_NONE means + * that the position should not be updated. + * + * When the rate is positive and @start has been updated, playback will start + * from the newly configured start position. + * + * For negative rates, playback will start from the newly configured stop + * position (if any). If the stop position if updated, it must be different from + * -1 for negative rates. + * + * It is not possible to seek relative to the current playback position, to do + * this, PAUSE the pipeline, query the current playback position with + * #GST_QUERY_POSITION and update the playback segment current position with a + * #GST_SEEK_TYPE_SET to the desired position. + * + * Returns: A new seek event. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif +GstEvent * +gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags, + GstSeekType start_type, gint64 start, GstSeekType stop_type, gint64 stop) +{ + g_return_val_if_fail (rate != 0.0, NULL); + + if (format == GST_FORMAT_TIME) { + GST_CAT_INFO (GST_CAT_EVENT, + "creating seek rate %lf, format TIME, flags %d, " + "start_type %d, start %" GST_TIME_FORMAT ", " + "stop_type %d, stop %" GST_TIME_FORMAT, + rate, flags, start_type, GST_TIME_ARGS (start), + stop_type, GST_TIME_ARGS (stop)); + } else { + GST_CAT_INFO (GST_CAT_EVENT, + "creating seek rate %lf, format %d, flags %d, " + "start_type %d, start %" G_GINT64_FORMAT ", " + "stop_type %d, stop %" G_GINT64_FORMAT, + rate, format, flags, start_type, start, stop_type, stop); + } + + return gst_event_new_custom (GST_EVENT_SEEK, + gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate, + "format", GST_TYPE_FORMAT, format, + "flags", GST_TYPE_SEEK_FLAGS, flags, + "cur_type", GST_TYPE_SEEK_TYPE, start_type, + "cur", G_TYPE_INT64, start, + "stop_type", GST_TYPE_SEEK_TYPE, stop_type, + "stop", G_TYPE_INT64, stop, NULL)); +} + +/** + * gst_event_parse_seek: + * @event: a seek event + * @rate: result location for the rate + * @format: result location for the stream format + * @flags: result location for the #GstSeekFlags + * @start_type: result location for the #GstSeekType of the start position + * @start: result location for the start postion expressed in @format + * @stop_type: result location for the #GstSeekType of the stop position + * @stop: result location for the stop postion expressed in @format + * + * Parses a seek @event and stores the results in the given result locations. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_event_parse_seek (GstEvent * event, gdouble * rate, + GstFormat * format, GstSeekFlags * flags, GstSeekType * start_type, + gint64 * start, GstSeekType * stop_type, gint64 * stop) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK); + + structure = gst_event_get_structure (event); + if (rate) + *rate = g_value_get_double (gst_structure_get_value (structure, "rate")); + if (format) + *format = g_value_get_enum (gst_structure_get_value (structure, "format")); + if (flags) + *flags = g_value_get_flags (gst_structure_get_value (structure, "flags")); + if (start_type) + *start_type = + g_value_get_enum (gst_structure_get_value (structure, "cur_type")); + if (start) + *start = g_value_get_int64 (gst_structure_get_value (structure, "cur")); + if (stop_type) + *stop_type = + g_value_get_enum (gst_structure_get_value (structure, "stop_type")); + if (stop) + *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop")); +} + +/** + * gst_event_new_navigation: + * @structure: description of the event + * + * Create a new navigation event from the given description. + * + * Returns: a new #GstEvent + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstEvent * +gst_event_new_navigation (GstStructure * structure) +{ + g_return_val_if_fail (structure != NULL, NULL); + + 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 + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +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 + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +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")); +}