2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wim.taymans@chello.be>
5 * gstevent.c: GstEvent subsystem
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
25 * @short_description: Structure describing events that are passed up and down
27 * @see_also: #GstPad, #GstElement
29 * The event classes are used to construct and query events.
31 * Events are usually created with gst_event_new_*() which takes the extra
32 * event parameters as arguments.
33 * Events can be parsed with their respective gst_event_parse_*() functions.
34 * The event should be unreffed with gst_event_unref().
36 * Events are passed between elements in parallel to the data stream. Some events
37 * are serialized with buffers, others are not. Some events only travel downstream,
38 * others only upstream. Some events can travel both upstream and downstream.
40 * The events are used to signal special conditions in the datastream such as EOS
41 * or the start of a new segment. Events are also used to flush the pipeline of
44 * Most of the event API is used inside plugins. The application usually only
45 * constructs and uses the seek event API when it wants to perform a seek in the
48 * gst_event_new_seek() is usually used to create a seek event and it takes
49 * the needed parameters for a seek event.
51 * <title>performing a seek on a pipeline</title>
56 * // construct a seek event to play the media from second 2 to 5, flush
57 * // the pipeline to decrease latency.
58 * event = gst_event_new_seek (1.0,
60 * GST_SEEK_FLAG_FLUSH,
61 * GST_SEEK_TYPE_SET, 2 * GST_SECOND,
62 * GST_SEEK_TYPE_SET, 5 * GST_SECOND);
64 * result = gst_element_send_event (pipeline, event);
66 * g_warning ("seek failed");
71 #include <string.h> /* memcpy */
73 #include "gst_private.h"
77 #include "gstenumtypes.h"
80 static void gst_event_init (GTypeInstance * instance, gpointer g_class);
81 static void gst_event_class_init (gpointer g_class, gpointer class_data);
82 static void gst_event_finalize (GstEvent * event);
83 static GstEvent *_gst_event_copy (GstEvent * event);
86 _gst_event_initialize (void)
88 gst_event_get_type ();
98 static GstEventQuarks event_quarks[] = {
99 {GST_EVENT_UNKNOWN, "unknown", 0},
100 {GST_EVENT_FLUSH_START, "flush-start", 0},
101 {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
102 {GST_EVENT_EOS, "eos", 0},
103 {GST_EVENT_NEWSEGMENT, "newsegment", 0},
104 {GST_EVENT_TAG, "tag", 0},
105 {GST_EVENT_BUFFERSIZE, "buffersize", 0},
106 {GST_EVENT_QOS, "qos", 0},
107 {GST_EVENT_SEEK, "seek", 0},
108 {GST_EVENT_NAVIGATION, "navigation", 0},
109 {GST_EVENT_CUSTOM_UPSTREAM, "custom-upstream", 0},
110 {GST_EVENT_CUSTOM_DOWNSTREAM, "custom-downstream", 0},
111 {GST_EVENT_CUSTOM_DOWNSTREAM_OOB, "custom-downstream-oob", 0},
112 {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
113 {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
119 * gst_event_type_get_name:
120 * @type: the event type
122 * Get a printable name for the given event type. Do not modify or free.
124 * Returns: a reference to the static name of the event.
127 gst_event_type_get_name (GstEventType type)
131 for (i = 0; event_quarks[i].name; i++) {
132 if (type == event_quarks[i].type)
133 return event_quarks[i].name;
139 * gst_event_type_to_quark:
140 * @type: the event type
142 * Get the unique quark for the given event type.
144 * Returns: the quark associated with the event type
147 gst_event_type_to_quark (GstEventType type)
151 for (i = 0; event_quarks[i].name; i++) {
152 if (type == event_quarks[i].type)
153 return event_quarks[i].quark;
159 * gst_event_type_get_flags:
160 * @type: a #GstEventType
162 * Gets the #GstEventTypeFlags associated with @type.
164 * Returns: a #GstEventTypeFlags.
167 gst_event_type_get_flags (GstEventType type)
169 GstEventTypeFlags ret;
171 ret = type & ((1 << GST_EVENT_TYPE_SHIFT) - 1);
177 gst_event_get_type (void)
179 static GType _gst_event_type;
182 if (G_UNLIKELY (_gst_event_type == 0)) {
183 static const GTypeInfo event_info = {
184 sizeof (GstEventClass),
187 gst_event_class_init,
196 _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
197 "GstEvent", &event_info, 0);
199 for (i = 0; event_quarks[i].name; i++) {
200 event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
204 return _gst_event_type;
208 gst_event_class_init (gpointer g_class, gpointer class_data)
210 GstEventClass *event_class = GST_EVENT_CLASS (g_class);
212 event_class->mini_object_class.copy =
213 (GstMiniObjectCopyFunction) _gst_event_copy;
214 event_class->mini_object_class.finalize =
215 (GstMiniObjectFinalizeFunction) gst_event_finalize;
219 gst_event_init (GTypeInstance * instance, gpointer g_class)
223 event = GST_EVENT (instance);
225 GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
229 gst_event_finalize (GstEvent * event)
231 g_return_if_fail (event != NULL);
232 g_return_if_fail (GST_IS_EVENT (event));
234 GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event,
235 gst_event_type_get_name (GST_EVENT_TYPE (event)));
237 if (GST_EVENT_SRC (event)) {
238 gst_object_unref (GST_EVENT_SRC (event));
239 GST_EVENT_SRC (event) = NULL;
241 if (event->structure) {
242 gst_structure_set_parent_refcount (event->structure, NULL);
243 gst_structure_free (event->structure);
248 _gst_event_copy (GstEvent * event)
252 copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
254 GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
255 GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
257 if (GST_EVENT_SRC (event)) {
258 GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
260 if (event->structure) {
261 copy->structure = gst_structure_copy (event->structure);
262 gst_structure_set_parent_refcount (copy->structure,
263 &event->mini_object.refcount);
269 gst_event_new (GstEventType type)
273 event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
275 GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s", event,
276 gst_event_type_get_name (type));
280 event->structure = NULL;
286 * gst_event_new_custom:
287 * @type: The type of the new event
288 * @structure: The structure for the event. The event will take ownership of
291 * Create a new custom-typed event. This can be used for anything not
292 * handled by other event-specific functions to pass an event to another
295 * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
296 * assigning a free number and filling in the correct direction and
297 * serialization flags.
299 * New custom events can also be created by subclassing the event type if
302 * Returns: The new custom event.
305 gst_event_new_custom (GstEventType type, GstStructure * structure)
309 event = gst_event_new (type);
311 gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
312 event->structure = structure;
318 * gst_event_get_structure:
319 * @event: The #GstEvent.
321 * Access the structure of the event.
323 * Returns: The structure of the event. The structure is still
324 * owned by the event, which means that you should not free it and
325 * that the pointer becomes invalid when you free the event.
330 gst_event_get_structure (GstEvent * event)
332 g_return_val_if_fail (GST_IS_EVENT (event), NULL);
334 return event->structure;
338 * gst_event_new_flush_start:
340 * Allocate a new flush start event. The flush start event can be send
341 * upstream and downstream and travels out-of-bounds with the dataflow.
342 * It marks pads as being in a WRONG_STATE to process more data.
344 * Elements unlock and blocking functions and exit their streaming functions
345 * as fast as possible.
347 * This event is typically generated after a seek to minimize the latency
350 * Returns: A new flush start event.
353 gst_event_new_flush_start (void)
355 return gst_event_new (GST_EVENT_FLUSH_START);
359 * gst_event_new_flush_stop:
361 * Allocate a new flush stop event. The flush start event can be send
362 * upstream and downstream and travels out-of-bounds with the dataflow.
363 * It is typically send after sending a FLUSH_START event to make the
364 * pads accept data again.
366 * Elements can process this event synchronized with the dataflow since
367 * the preceeding FLUSH_START event stopped the dataflow.
369 * This event is typically generated to complete a seek and to resume
372 * Returns: A new flush stop event.
375 gst_event_new_flush_stop (void)
377 return gst_event_new (GST_EVENT_FLUSH_STOP);
383 * Create a new EOS event. The eos event can only travel downstream
384 * synchronized with the buffer flow. Elements that receive the EOS
385 * event on a pad can return UNEXPECTED as a GstFlowReturn when data
386 * after the EOS event arrives.
388 * The EOS event will travel up to the sink elements in the pipeline
389 * which will then post the GST_MESSAGE_EOS on the bus.
391 * When all sinks have posted an EOS message, the EOS message is
392 * forwarded to the application.
394 * Returns: The new EOS event.
397 gst_event_new_eos (void)
399 return gst_event_new (GST_EVENT_EOS);
403 * gst_event_new_new_segment:
404 * @update: is this segment an update to a previous one
405 * @rate: a new rate for playback
406 * @format: The format of the segment values
407 * @start_value: the start value of the segment
408 * @stop_value: the stop value of the segment
409 * @stream_time: stream time for buffer timestamps.
411 * Allocate a new newsegment event with the given format/values tripplets.
413 * The newsegment event marks the range of buffers to be processed. All
414 * data not within the segment range is not to be processed. This can be
415 * used intelligently by plugins to use more efficient methods of skipping
418 * The stream time of the segment is used to convert the buffer timestamps
419 * into the stream time again, this is usually done in sinks to report the
420 * current stream_time. @stream_time cannot be -1.
422 * The @start_value cannot be -1, the @stop_value can be -1. If there
423 * is a valid @stop_value given, it must be greater or equal than @start_value.
425 * After a newsegment event, the buffer stream time is calculated with:
427 * stream_time + (TIMESTAMP(buf) - start_value) * ABS (rate)
429 * Returns: A new newsegment event.
432 gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
433 gint64 start_value, gint64 stop_value, gint64 stream_time)
435 g_return_val_if_fail (rate != 0.0, NULL);
437 if (format == GST_FORMAT_TIME) {
438 GST_CAT_INFO (GST_CAT_EVENT,
439 "creating newsegment update %d, rate %lf, format GST_FORMAT_TIME, "
440 "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
441 ", stream_time %" GST_TIME_FORMAT,
442 update, rate, GST_TIME_ARGS (start_value),
443 GST_TIME_ARGS (stop_value), GST_TIME_ARGS (stream_time));
445 GST_CAT_INFO (GST_CAT_EVENT,
446 "creating newsegment update %d, rate %lf, format %d, "
447 "start %lld, stop %lld, stream_time %lld",
448 update, rate, format, start_value, stop_value, stream_time);
450 if (stream_time == -1)
451 g_return_val_if_fail (stream_time != -1, NULL);
453 if (start_value == -1)
454 g_return_val_if_fail (start_value != -1, NULL);
456 if (stop_value != -1)
457 g_return_val_if_fail (start_value <= stop_value, NULL);
459 return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
460 gst_structure_new ("GstEventNewsegment",
461 "update", G_TYPE_BOOLEAN, update,
462 "rate", G_TYPE_DOUBLE, rate,
463 "format", GST_TYPE_FORMAT, format,
464 "start_val", G_TYPE_INT64, start_value,
465 "stop_val", G_TYPE_INT64, stop_value,
466 "stream_time", G_TYPE_INT64, stream_time, NULL));
470 * gst_event_parse_new_segment:
471 * @event: The event to query
472 * @update: A pointer to the update flag of the segment
473 * @rate: A pointer to the rate of the segment
474 * @format: A pointer to the format of the newsegment values
475 * @start_value: A pointer to store the start value in
476 * @stop_value: A pointer to store the stop value in
477 * @stream_time: A pointer to store the stream time in
479 * Get the start, stop and format in the newsegment event.
482 gst_event_parse_new_segment (GstEvent * event, gboolean * update,
483 gdouble * rate, GstFormat * format, gint64 * start_value,
484 gint64 * stop_value, gint64 * stream_time)
486 const GstStructure *structure;
488 g_return_if_fail (GST_IS_EVENT (event));
489 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
491 structure = gst_event_get_structure (event);
494 g_value_get_boolean (gst_structure_get_value (structure, "update"));
496 *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
498 *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
501 g_value_get_int64 (gst_structure_get_value (structure, "start_val"));
504 g_value_get_int64 (gst_structure_get_value (structure, "stop_val"));
507 g_value_get_int64 (gst_structure_get_value (structure, "stream_time"));
512 * @taglist: metadata list
514 * Generates a metadata tag event from the given @taglist.
516 * Returns: a new #GstEvent
519 gst_event_new_tag (GstTagList * taglist)
521 g_return_val_if_fail (taglist != NULL, NULL);
523 return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
527 * gst_event_parse_tag:
528 * @event: a tag event
529 * @taglist: pointer to metadata list
531 * Parses a tag @event and stores the results in the given @taglist location.
534 gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
536 g_return_if_fail (GST_IS_EVENT (event));
537 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
540 *taglist = (GstTagList *) event->structure;
543 /* buffersize event */
545 * gst_event_new_buffer_size:
546 * @format: buffer format
547 * @minsize: minimum buffer size
548 * @maxsize: maximum buffer size
549 * @async: thread behavior
551 * Create a new buffersize event. The event is sent downstream and notifies
552 * elements that they should provide a buffer of the specified dimensions.
554 * When the async flag is set, a thread boundary is prefered.
556 * Returns: a new #GstEvent
559 gst_event_new_buffer_size (GstFormat format, gint64 minsize,
560 gint64 maxsize, gboolean async)
562 GST_CAT_INFO (GST_CAT_EVENT,
563 "creating buffersize format %d, minsize %" G_GINT64_FORMAT
564 ", maxsize %" G_GINT64_FORMAT ", async %d", format,
565 minsize, maxsize, async);
567 return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
568 gst_structure_new ("GstEventBufferSize",
569 "format", GST_TYPE_FORMAT, format,
570 "minsize", G_TYPE_INT64, minsize,
571 "maxsize", G_TYPE_INT64, maxsize,
572 "async", G_TYPE_BOOLEAN, async, NULL));
576 * gst_event_parse_buffer_size:
577 * @event: The event to query
578 * @format: A pointer to store the format in
579 * @minsize: A pointer to store the minsize in
580 * @maxsize: A pointer to store the maxsize in
581 * @async: A pointer to store the async-flag in
583 * Get the format, minsize, maxsize and async-flag in the buffersize event.
586 gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
587 gint64 * minsize, gint64 * maxsize, gboolean * async)
589 const GstStructure *structure;
591 g_return_if_fail (GST_IS_EVENT (event));
592 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
594 structure = gst_event_get_structure (event);
596 *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
599 g_value_get_int64 (gst_structure_get_value (structure, "minsize"));
602 g_value_get_int64 (gst_structure_get_value (structure, "maxsize"));
604 *async = g_value_get_boolean (gst_structure_get_value (structure, "async"));
609 * @proportion: the proportion of the qos message
610 * @diff: The time difference of the last Clock sync
611 * @timestamp: The timestamp of the buffer
613 * Allocate a new qos event with the given values.
614 * The QOS event is generated in an element that wants an upstream
615 * element to either reduce or increase its rate because of
618 * proportion is the requested adjustment in datarate, 1.0 is the normal
619 * datarate, 0.75 means increase datarate by 75%, 1.5 is 150%. Negative
620 * values request a slow down, so -0.75 means a decrease by 75%.
622 * diff is the difference against the clock in stream time of the last
623 * buffer that caused the element to generate the QOS event.
625 * timestamp is the timestamp of the last buffer that cause the element
626 * to generate the QOS event.
628 * Returns: A new QOS event.
631 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
632 GstClockTime timestamp)
634 GST_CAT_INFO (GST_CAT_EVENT,
635 "creating qos proportion %lf, diff %" GST_TIME_FORMAT
636 ", timestamp %" GST_TIME_FORMAT, proportion,
637 GST_TIME_ARGS (diff), GST_TIME_ARGS (timestamp));
639 return gst_event_new_custom (GST_EVENT_QOS,
640 gst_structure_new ("GstEventQOS",
641 "proportion", G_TYPE_DOUBLE, proportion,
642 "diff", G_TYPE_INT64, diff,
643 "timestamp", G_TYPE_UINT64, timestamp, NULL));
647 * gst_event_parse_qos:
648 * @event: The event to query
649 * @proportion: A pointer to store the proportion in
650 * @diff: A pointer to store the diff in
651 * @timestamp: A pointer to store the timestamp in
653 * Get the proportion, diff and timestamp in the qos event.
656 gst_event_parse_qos (GstEvent * event, gdouble * proportion,
657 GstClockTimeDiff * diff, GstClockTime * timestamp)
659 const GstStructure *structure;
661 g_return_if_fail (GST_IS_EVENT (event));
662 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
664 structure = gst_event_get_structure (event);
667 g_value_get_double (gst_structure_get_value (structure, "proportion"));
669 *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
672 g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
676 * gst_event_new_seek:
677 * @rate: The new playback rate
678 * @format: The format of the seek values
679 * @flags: The optional seek flags
680 * @cur_type: The type and flags for the new current position
681 * @cur: The value of the new current position
682 * @stop_type: The type and flags for the new stop position
683 * @stop: The value of the new stop position
685 * Allocate a new seek event with the given parameters.
687 * The seek event configures playback of the pipeline from
688 * @cur to @stop at the speed given in @rate, also called a segment.
689 * The @cur and @stop values are expressed in format @format.
691 * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
692 * Negatives values means backwards playback. A value of 0.0 for the
693 * rate is not allowed.
695 * @cur_type and @stop_type specify how to adjust the current and stop
696 * time, relative or absolute. A type of #GST_SEEK_TYPE_NONE means that
697 * the position should not be updated. The currently configured playback
698 * segment can be queried with #GST_QUERY_SEGMENT.
700 * Note that updating the @cur position will actually move the current
701 * playback pointer to that new position. It is not possible to seek
702 * relative to the current playing position, to do this, pause the pipeline,
703 * get the current position and perform a GST_SEEK_TYPE_SET to the desired
706 * Returns: A new seek event.
709 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
710 GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
712 if (format == GST_FORMAT_TIME) {
713 GST_CAT_INFO (GST_CAT_EVENT,
714 "creating seek rate %lf, format TIME, flags %d, "
715 "cur_type %d, cur %" GST_TIME_FORMAT ", "
716 "stop_type %d, stop %" GST_TIME_FORMAT,
717 rate, flags, cur_type, GST_TIME_ARGS (cur),
718 stop_type, GST_TIME_ARGS (stop));
720 GST_CAT_INFO (GST_CAT_EVENT,
721 "creating seek rate %lf, format %d, flags %d, "
722 "cur_type %d, cur %" G_GINT64_FORMAT ", "
723 "stop_type %d, stop %" G_GINT64_FORMAT,
724 rate, format, flags, cur_type, cur, stop_type, stop);
727 return gst_event_new_custom (GST_EVENT_SEEK,
728 gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
729 "format", GST_TYPE_FORMAT, format,
730 "flags", GST_TYPE_SEEK_FLAGS, flags,
731 "cur_type", GST_TYPE_SEEK_TYPE, cur_type,
732 "cur", G_TYPE_INT64, cur,
733 "stop_type", GST_TYPE_SEEK_TYPE, stop_type,
734 "stop", G_TYPE_INT64, stop, NULL));
738 * gst_event_parse_seek:
739 * @event: a seek event
740 * @rate: result location for the rate
741 * @format: result location for the stream format
742 * @flags: result location for the #GstSeekFlags
743 * @cur_type: result location for the #GstSeekType of the current position
744 * @cur: result location for the current postion expressed in @format
745 * @stop_type: result location for the #GstSeekType of the stop position
746 * @stop: result location for the stop postion expressed in @format
748 * Parses a seek @event and stores the results in the given result locations.
751 gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
752 GstSeekFlags * flags,
753 GstSeekType * cur_type, gint64 * cur,
754 GstSeekType * stop_type, gint64 * stop)
756 const GstStructure *structure;
758 g_return_if_fail (GST_IS_EVENT (event));
759 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
761 structure = gst_event_get_structure (event);
763 *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
765 *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
767 *flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
770 g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
772 *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
775 g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
777 *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
781 * gst_event_new_navigation:
782 * @structure: description of the event
784 * Create a new navigation event from the given description.
786 * Returns: a new #GstEvent
789 gst_event_new_navigation (GstStructure * structure)
791 g_return_val_if_fail (structure != NULL, NULL);
793 return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);