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.
24 * @short_description: Structure describing events that are passed up and down
26 * @see_also: #GstPad, #GstElement
28 * The event classes are used to construct and query events.
30 * Events are usually created with gst_event_new_*() which takes the extra
31 * event parameters as arguments.
32 * Events can be parsed with their respective gst_event_parse_*() functions.
33 * The event should be unreffed with gst_event_unref().
35 * gst_event_new_seek() is usually used to create a seek event and it takes
36 * the needed parameters for a seek event.
38 * gst_event_new_flush() creates a new flush event.
41 #include <string.h> /* memcpy */
43 #include "gst_private.h"
47 #include "gstenumtypes.h"
50 static void gst_event_init (GTypeInstance * instance, gpointer g_class);
51 static void gst_event_class_init (gpointer g_class, gpointer class_data);
52 static void gst_event_finalize (GstEvent * event);
53 static GstEvent *_gst_event_copy (GstEvent * event);
56 _gst_event_initialize (void)
58 gst_event_get_type ();
68 static GstEventQuarks event_quarks[] = {
69 {GST_EVENT_UNKNOWN, "unknown", 0},
70 {GST_EVENT_FLUSH_START, "flush-start", 0},
71 {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
72 {GST_EVENT_EOS, "eos", 0},
73 {GST_EVENT_NEWSEGMENT, "newsegment", 0},
74 {GST_EVENT_TAG, "tag", 0},
75 {GST_EVENT_FILLER, "filler", 0},
76 {GST_EVENT_BUFFERSIZE, "buffersize", 0},
77 {GST_EVENT_QOS, "qos", 0},
78 {GST_EVENT_SEEK, "seek", 0},
79 {GST_EVENT_NAVIGATION, "navigation", 0},
80 {GST_EVENT_CUSTOM_UP, "custom-up", 0},
81 {GST_EVENT_CUSTOM_DS, "custom-ds", 0},
82 {GST_EVENT_CUSTOM_DS_OOB, "custom-ds-oob", 0},
83 {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
84 {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
90 * gst_event_type_get_name:
91 * @type: the event type
93 * Get a printable name for the given event type. Do not modify or free.
95 * Returns: a reference to the static name of the event.
98 gst_event_type_get_name (GstEventType type)
102 for (i = 0; event_quarks[i].name; i++) {
103 if (type == event_quarks[i].type)
104 return event_quarks[i].name;
110 * gst_event_type_to_quark:
111 * @type: the event type
113 * Get the unique quark for the given event type.
115 * Returns: the quark associated with the event type
118 gst_event_type_to_quark (GstEventType type)
122 for (i = 0; event_quarks[i].name; i++) {
123 if (type == event_quarks[i].type)
124 return event_quarks[i].quark;
130 gst_event_get_type (void)
132 static GType _gst_event_type;
135 if (G_UNLIKELY (_gst_event_type == 0)) {
136 static const GTypeInfo event_info = {
137 sizeof (GstEventClass),
140 gst_event_class_init,
149 _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
150 "GstEvent", &event_info, 0);
152 for (i = 0; event_quarks[i].name; i++) {
153 event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
157 return _gst_event_type;
161 gst_event_class_init (gpointer g_class, gpointer class_data)
163 GstEventClass *event_class = GST_EVENT_CLASS (g_class);
165 event_class->mini_object_class.copy =
166 (GstMiniObjectCopyFunction) _gst_event_copy;
167 event_class->mini_object_class.finalize =
168 (GstMiniObjectFinalizeFunction) gst_event_finalize;
172 gst_event_init (GTypeInstance * instance, gpointer g_class)
176 event = GST_EVENT (instance);
178 GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
182 gst_event_finalize (GstEvent * event)
184 g_return_if_fail (event != NULL);
185 g_return_if_fail (GST_IS_EVENT (event));
187 GST_CAT_INFO (GST_CAT_EVENT, "freeing event %p type %s", event,
188 gst_event_type_get_name (GST_EVENT_TYPE (event)));
190 if (GST_EVENT_SRC (event)) {
191 gst_object_unref (GST_EVENT_SRC (event));
192 GST_EVENT_SRC (event) = NULL;
194 if (event->structure) {
195 gst_structure_set_parent_refcount (event->structure, NULL);
196 gst_structure_free (event->structure);
201 _gst_event_copy (GstEvent * event)
205 copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
207 GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
208 GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
210 if (GST_EVENT_SRC (event)) {
211 GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
213 if (event->structure) {
214 copy->structure = gst_structure_copy (event->structure);
215 gst_structure_set_parent_refcount (copy->structure,
216 &event->mini_object.refcount);
222 gst_event_new (GstEventType type)
226 event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
228 GST_CAT_INFO (GST_CAT_EVENT, "creating new event %p %s", event,
229 gst_event_type_get_name (type));
233 event->structure = NULL;
239 * gst_event_new_custom:
240 * @type: The type of the new event
241 * @structure: The structure for the event. The event will take ownership of
244 * Create a new custom-typed event. This can be used for anything not
245 * handled by other event-specific functions to pass an event to another
248 * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
249 * assigning a free number and filling in the correct direction and
250 * serialization flags.
252 * New custom events can also be created by subclassing the event type if
255 * Returns: The new custom event.
258 gst_event_new_custom (GstEventType type, GstStructure * structure)
262 event = gst_event_new (type);
264 gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
265 event->structure = structure;
271 * gst_event_get_structure:
272 * @event: The #GstEvent.
274 * Access the structure of the event.
276 * Returns: The structure of the event. The structure is still
277 * owned by the event, which means that you should not free it and
278 * that the pointer becomes invalid when you free the event.
283 gst_event_get_structure (GstEvent * event)
285 g_return_val_if_fail (GST_IS_EVENT (event), NULL);
287 return event->structure;
291 * gst_event_new_flush_start:
293 * Allocate a new flush start event. The flush start event can be send
294 * upstream and downstream and travels out-of-bounds with the dataflow.
295 * It marks pads as being in a WRONG_STATE to process more data.
297 * Elements unlock and blocking functions and exit their streaming functions
298 * as fast as possible.
300 * This event is typically generated after a seek to minimize the latency
303 * Returns: A new flush start event.
306 gst_event_new_flush_start (void)
308 return gst_event_new (GST_EVENT_FLUSH_START);
312 * gst_event_new_flush_stop:
314 * Allocate a new flush stop event. The flush start event can be send
315 * upstream and downstream and travels out-of-bounds with the dataflow.
316 * It is typically send after sending a FLUSH_START event to make the
317 * pads accept data again.
319 * Elements can process this event synchronized with the dataflow since
320 * the preceeding FLUSH_START event stopped the dataflow.
322 * This event is typically generated to complete a seek and to resume
325 * Returns: A new flush stop event.
328 gst_event_new_flush_stop (void)
330 return gst_event_new (GST_EVENT_FLUSH_STOP);
336 * Create a new EOS event. The eos event can only travel downstream
337 * synchronized with the buffer flow. Elements that receive the EOS
338 * event on a pad can return UNEXPECTED as a GstFlowReturn when data
339 * after the EOS event arrives.
341 * The EOS event will travel up to the sink elements in the pipeline
342 * which will then post the GST_MESSAGE_EOS on the bus.
344 * When all sinks have posted an EOS message, the EOS message is
345 * forwarded to the application.
347 * Returns: The new EOS event.
350 gst_event_new_eos (void)
352 return gst_event_new (GST_EVENT_EOS);
356 * gst_event_new_newsegment:
357 * @rate: a new rate for playback
358 * @format: The format of the segment values
359 * @start_value: the start value of the segment
360 * @stop_value: the stop value of the segment
361 * @base: base value for buffer timestamps.
363 * Allocate a new newsegment event with the given format/values tripplets.
365 * The newsegment event marks the range of buffers to be processed. All
366 * data not within the segment range is not to be processed. This can be
367 * used intelligently by plugins to use more efficient methods of skipping
370 * The base time of the segment is also used to convert the buffer timestamps
371 * into the stream time again.
373 * The @start_value cannot be -1, the @stop_value can be -1. If there
374 * is a valid @stop_value given, it must be smaller than @start_value.
376 * After a newsegment event, the buffer stream time is calculated with:
378 * TIMESTAMP(buf) - start_time + base
380 * Returns: A new newsegment event.
383 gst_event_new_newsegment (gdouble rate, GstFormat format,
384 gint64 start_value, gint64 stop_value, gint64 base)
386 if (format == GST_FORMAT_TIME) {
387 GST_CAT_INFO (GST_CAT_EVENT,
388 "creating newsegment rate %lf, format GST_FORMAT_TIME, "
389 "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
390 ", base %" GST_TIME_FORMAT,
391 rate, GST_TIME_ARGS (start_value),
392 GST_TIME_ARGS (stop_value), GST_TIME_ARGS (base));
394 GST_CAT_INFO (GST_CAT_EVENT,
395 "creating newsegment rate %lf, format %d, "
396 "start %lld, stop %lld, base %lld",
397 rate, format, start_value, stop_value, base);
399 if (start_value == -1)
400 g_return_val_if_fail (start_value != -1, NULL);
402 if (stop_value != -1)
403 g_return_val_if_fail (start_value <= stop_value, NULL);
405 return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
406 gst_structure_new ("GstEventNewsegment", "rate", G_TYPE_DOUBLE, rate,
407 "format", GST_TYPE_FORMAT, format,
408 "start_val", G_TYPE_INT64, start_value,
409 "stop_val", G_TYPE_INT64, stop_value,
410 "base", G_TYPE_INT64, base, NULL));
414 * gst_event_parse_newsegment:
415 * @event: The event to query
416 * @rate: A pointer to the rate of the segment
417 * @format: A pointer to the format of the newsegment values
418 * @start_value: A pointer to store the start value in
419 * @stop_value: A pointer to store the stop value in
420 * @base: A pointer to store the base time in
422 * Get the start, stop and format in the newsegment event.
425 gst_event_parse_newsegment (GstEvent * event, gdouble * rate,
426 GstFormat * format, gint64 * start_value, gint64 * stop_value,
429 const GstStructure *structure;
431 g_return_if_fail (GST_IS_EVENT (event));
432 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
434 structure = gst_event_get_structure (event);
436 *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
438 *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
441 g_value_get_int64 (gst_structure_get_value (structure, "start_val"));
444 g_value_get_int64 (gst_structure_get_value (structure, "stop_val"));
446 *base = g_value_get_int64 (gst_structure_get_value (structure, "base"));
451 * @taglist: metadata list
453 * Generates a metadata tag event from the given @taglist.
455 * Returns: a new #GstEvent
458 gst_event_new_tag (GstTagList * taglist)
460 g_return_val_if_fail (taglist != NULL, NULL);
462 return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
466 * gst_event_parse_tag:
467 * @event: a tag event
468 * @taglist: pointer to metadata list
470 * Parses a tag @event and stores the results in the given @taglist location.
473 gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
475 g_return_if_fail (GST_IS_EVENT (event));
476 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
479 *taglist = (GstTagList *) event->structure;
484 * gst_event_new_filler:
486 * Create a new dummy event that should be ignored.
488 * Returns: a new #GstEvent
491 gst_event_new_filler (void)
493 return gst_event_new (GST_EVENT_FILLER);
496 /* buffersize event */
498 * gst_event_new_buffersize:
499 * @format: buffer format
500 * @minsize: minimum buffer size
501 * @maxsize: maximum buffer size
502 * @async: thread behavior
504 * Create a new buffersize event. The event is sent downstream and notifies
505 * elements that they should provide a buffer of the specified dimensions.
507 * When the async flag is set, a thread boundary is prefered.
509 * Returns: a new #GstEvent
512 gst_event_new_buffersize (GstFormat format, gint64 minsize,
513 gint64 maxsize, gboolean async)
515 GST_CAT_INFO (GST_CAT_EVENT,
516 "creating buffersize format %d, minsize %" G_GINT64_FORMAT
517 ", maxsize %" G_GINT64_FORMAT ", async %d", format,
518 minsize, maxsize, async);
520 return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
521 gst_structure_new ("GstEventBufferSize",
522 "format", GST_TYPE_FORMAT, format,
523 "minsize", G_TYPE_INT64, minsize,
524 "maxsize", G_TYPE_INT64, maxsize,
525 "async", G_TYPE_BOOLEAN, async, NULL));
529 * gst_event_parse_buffersize:
530 * @event: The event to query
531 * @format: A pointer to store the format in
532 * @minsize: A pointer to store the minsize in
533 * @maxsize: A pointer to store the maxsize in
534 * @async: A pointer to store the async-flag in
536 * Get the format, minsize, maxsize and async-flag in the buffersize event.
539 gst_event_parse_buffersize (GstEvent * event, GstFormat * format,
540 gint64 * minsize, gint64 * maxsize, gboolean * async)
542 const GstStructure *structure;
544 g_return_if_fail (GST_IS_EVENT (event));
545 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
547 structure = gst_event_get_structure (event);
549 *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
552 g_value_get_int64 (gst_structure_get_value (structure, "minsize"));
555 g_value_get_int64 (gst_structure_get_value (structure, "maxsize"));
557 *async = g_value_get_boolean (gst_structure_get_value (structure, "async"));
562 * @proportion: the proportion of the qos message
563 * @diff: The time difference of the last Clock sync
564 * @timestamp: The timestamp of the buffer
566 * Allocate a new qos event with the given values.
567 * The QOS event is generated in an element that wants an upstream
568 * element to either reduce or increase its rate because of
571 * proportion is the requested adjustment in datarate, 1.0 is the normal
572 * datarate, 0.75 means increase datarate by 75%, 1.5 is 150%. Negative
573 * values request a slow down, so -0.75 means a decrease by 75%.
575 * diff is the difference against the clock in stream time of the last
576 * buffer that caused the element to generate the QOS event.
578 * timestamp is the timestamp of the last buffer that cause the element
579 * to generate the QOS event.
581 * Returns: A new QOS event.
584 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
585 GstClockTime timestamp)
587 GST_CAT_INFO (GST_CAT_EVENT,
588 "creating qos proportion %lf, diff %" GST_TIME_FORMAT
589 ", timestamp %" GST_TIME_FORMAT, proportion,
590 GST_TIME_ARGS (diff), GST_TIME_ARGS (timestamp));
592 return gst_event_new_custom (GST_EVENT_QOS,
593 gst_structure_new ("GstEventQOS",
594 "proportion", G_TYPE_DOUBLE, proportion,
595 "diff", G_TYPE_INT64, diff,
596 "timestamp", G_TYPE_UINT64, timestamp, NULL));
600 * gst_event_parse_qos:
601 * @event: The event to query
602 * @proportion: A pointer to store the proportion in
603 * @diff: A pointer to store the diff in
604 * @timestamp: A pointer to store the timestamp in
606 * Get the proportion, diff and timestamp in the qos event.
609 gst_event_parse_qos (GstEvent * event, gdouble * proportion,
610 GstClockTimeDiff * diff, GstClockTime * timestamp)
612 const GstStructure *structure;
614 g_return_if_fail (GST_IS_EVENT (event));
615 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
617 structure = gst_event_get_structure (event);
620 g_value_get_double (gst_structure_get_value (structure, "proportion"));
622 *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
625 g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
629 * gst_event_new_seek:
630 * @rate: The new playback rate
631 * @format: The format of the seek values
632 * @flags: The optional seek flags
633 * @cur_type: The type and flags for the new current position
634 * @cur: The value of the new current position
635 * @stop_type: The type and flags for the new stop position
636 * @stop: The value of the new stop position
638 * Allocate a new seek event with the given parameters.
640 * The seek event configures playback of the pipeline from
641 * @cur to @stop at the speed given in @rate.
642 * The @cur and @stop values are expressed in format @format.
644 * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
645 * Negatives values means backwards playback. A value of 0.0 for the
646 * rate is not allowed.
648 * @cur_type and @stop_type specify how to adjust the current and stop
649 * time, relative or absolute. A type of #GST_EVENT_TYPE_NONE means that
650 * the position should not be updated.
652 * Returns: A new seek event.
655 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
656 GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
658 if (format == GST_FORMAT_TIME) {
659 GST_CAT_INFO (GST_CAT_EVENT,
660 "creating seek rate %lf, format TIME, flags %d, "
661 "cur_type %d, cur %" GST_TIME_FORMAT ", "
662 "stop_type %d, stop %" GST_TIME_FORMAT,
663 rate, flags, cur_type, GST_TIME_ARGS (cur),
664 stop_type, GST_TIME_ARGS (stop));
666 GST_CAT_INFO (GST_CAT_EVENT,
667 "creating seek rate %lf, format %d, flags %d, "
668 "cur_type %d, cur %" G_GINT64_FORMAT ", "
669 "stop_type %d, stop %" G_GINT64_FORMAT,
670 rate, format, flags, cur_type, cur, stop_type, stop);
673 return gst_event_new_custom (GST_EVENT_SEEK,
674 gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
675 "format", GST_TYPE_FORMAT, format,
676 "flags", GST_TYPE_SEEK_FLAGS, flags,
677 "cur_type", GST_TYPE_SEEK_TYPE, cur_type,
678 "cur", G_TYPE_INT64, cur,
679 "stop_type", GST_TYPE_SEEK_TYPE, stop_type,
680 "stop", G_TYPE_INT64, stop, NULL));
684 * gst_event_parse_seek:
685 * @event: a seek event
686 * @rate: result location for the rate
687 * @format: result location for the stream format
688 * @flags: result location for the #GstSeekFlags
689 * @cur_type: result location for the #GstSeekType of the current position
690 * @cur: result location for the current postion expressed in @format
691 * @stop_type: result location for the #GstSeekType of the stop position
692 * @stop: result location for the stop postion expressed in @format
694 * Parses a seek @event and stores the results in the given result locations.
697 gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
698 GstSeekFlags * flags,
699 GstSeekType * cur_type, gint64 * cur,
700 GstSeekType * stop_type, gint64 * stop)
702 const GstStructure *structure;
704 g_return_if_fail (GST_IS_EVENT (event));
705 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
707 structure = gst_event_get_structure (event);
709 *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
711 *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
713 *flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
716 g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
718 *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
721 g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
723 *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
727 * gst_event_new_navigation:
728 * @structure: description of the event
730 * Create a new navigation event from the given description.
732 * Returns: a new #GstEvent
735 gst_event_new_navigation (GstStructure * structure)
737 g_return_val_if_fail (structure != NULL, NULL);
739 return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);