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 a pipeline
25 * @see_also: #GstPad, #GstElement
27 * The event classes are used to construct and query events.
29 * Events are usually created with gst_event_new_*() which takes the extra event
30 * paramters as arguments.
31 * Events can be parsed with their respective gst_event_parse_*() functions.
32 * The event should be unreferenced with gst_event_unref().
34 * gst_event_new_seek() is a usually used to create a seek event and it takes
35 * the needed parameters for a seek event.
37 * gst_event_new_flush() creates a new flush event.
40 #include <string.h> /* memcpy */
42 #include "gst_private.h"
46 #include "gstenumtypes.h"
49 static void gst_event_init (GTypeInstance * instance, gpointer g_class);
50 static void gst_event_class_init (gpointer g_class, gpointer class_data);
51 static void gst_event_finalize (GstEvent * event);
52 static GstEvent *_gst_event_copy (GstEvent * event);
55 _gst_event_initialize (void)
57 gst_event_get_type ();
67 static GstEventQuarks event_quarks[] = {
68 {GST_EVENT_UNKNOWN, "unknown", 0},
69 {GST_EVENT_FLUSH_START, "flush-start", 0},
70 {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
71 {GST_EVENT_EOS, "eos", 0},
72 {GST_EVENT_NEWSEGMENT, "newsegment", 0},
73 {GST_EVENT_TAG, "tag", 0},
74 {GST_EVENT_FILLER, "filler", 0},
75 {GST_EVENT_BUFFERSIZE, "buffersize", 0},
76 {GST_EVENT_QOS, "qos", 0},
77 {GST_EVENT_SEEK, "seek", 0},
78 {GST_EVENT_NAVIGATION, "navigation", 0},
79 {GST_EVENT_CUSTOM_UP, "custom-up", 0},
80 {GST_EVENT_CUSTOM_DS, "custom-ds", 0},
81 {GST_EVENT_CUSTOM_DS_OOB, "custom-ds-oob", 0},
82 {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
83 {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
89 * gst_event_type_get_name:
90 * @type: the event type
92 * Get a printable name for the given event type. Do not modify or free.
94 * Returns: a reference to the static name of the event.
97 gst_event_type_get_name (GstEventType type)
101 for (i = 0; event_quarks[i].name; i++) {
102 if (type == event_quarks[i].type)
103 return event_quarks[i].name;
109 * gst_event_type_to_quark:
110 * @type: the event type
112 * Get the unique quark for the given event type.
114 * Returns: the quark associated with the event type
117 gst_event_type_to_quark (GstEventType type)
121 for (i = 0; event_quarks[i].name; i++) {
122 if (type == event_quarks[i].type)
123 return event_quarks[i].quark;
129 gst_event_get_type (void)
131 static GType _gst_event_type;
134 if (G_UNLIKELY (_gst_event_type == 0)) {
135 static const GTypeInfo event_info = {
136 sizeof (GstEventClass),
139 gst_event_class_init,
148 _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
149 "GstEvent", &event_info, 0);
151 for (i = 0; event_quarks[i].name; i++) {
152 event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
156 return _gst_event_type;
160 gst_event_class_init (gpointer g_class, gpointer class_data)
162 GstEventClass *event_class = GST_EVENT_CLASS (g_class);
164 event_class->mini_object_class.copy =
165 (GstMiniObjectCopyFunction) _gst_event_copy;
166 event_class->mini_object_class.finalize =
167 (GstMiniObjectFinalizeFunction) gst_event_finalize;
171 gst_event_init (GTypeInstance * instance, gpointer g_class)
175 event = GST_EVENT (instance);
177 GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
181 gst_event_finalize (GstEvent * event)
183 g_return_if_fail (event != NULL);
184 g_return_if_fail (GST_IS_EVENT (event));
186 GST_CAT_INFO (GST_CAT_EVENT, "freeing event %p type %s", event,
187 gst_event_type_get_name (GST_EVENT_TYPE (event)));
189 if (GST_EVENT_SRC (event)) {
190 gst_object_unref (GST_EVENT_SRC (event));
191 GST_EVENT_SRC (event) = NULL;
193 if (event->structure) {
194 gst_structure_set_parent_refcount (event->structure, NULL);
195 gst_structure_free (event->structure);
200 _gst_event_copy (GstEvent * event)
204 copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
206 GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
207 GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
209 if (GST_EVENT_SRC (event)) {
210 GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
212 if (event->structure) {
213 copy->structure = gst_structure_copy (event->structure);
214 gst_structure_set_parent_refcount (copy->structure,
215 &event->mini_object.refcount);
221 gst_event_new (GstEventType type)
225 event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
227 GST_CAT_INFO (GST_CAT_EVENT, "creating new event %p %s", event,
228 gst_event_type_get_name (type));
232 event->structure = NULL;
238 * gst_event_new_custom:
239 * @type: The type of the new event
240 * @structure: The structure for the event. The event will take ownership of
243 * Create a new custom-typed event. This can be used for anything not
244 * handled by other event-specific functions to pass an event to another
247 * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
248 * assigning a free number and filling in the correct direction and
249 * serialization flags.
251 * New custom events can also be created by subclassing the event type if
254 * Returns: The new custom event.
257 gst_event_new_custom (GstEventType type, GstStructure * structure)
261 event = gst_event_new (type);
263 gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
264 event->structure = structure;
270 * gst_event_get_structure:
271 * @event: The #GstEvent.
273 * Access the structure of the event.
275 * Returns: The structure of the event. The structure is still
276 * owned by the event, which means that you should not free it and
277 * that the pointer becomes invalid when you free the event.
282 gst_event_get_structure (GstEvent * event)
284 g_return_val_if_fail (GST_IS_EVENT (event), NULL);
286 return event->structure;
290 * gst_event_new_flush_start:
292 * Allocate a new flush start event. The flush start event can be send
293 * upstream and downstream and travels out-of-bounds with the dataflow.
294 * It marks pads as being in a WRONG_STATE to process more data.
296 * Elements unlock and blocking functions and exit their streaming functions
297 * as fast as possible.
299 * This event is typically generated after a seek to minimize the latency
302 * Returns: A new flush start event.
305 gst_event_new_flush_start (void)
307 return gst_event_new (GST_EVENT_FLUSH_START);
311 * gst_event_new_flush_stop:
313 * Allocate a new flush stop event. The flush start event can be send
314 * upstream and downstream and travels out-of-bounds with the dataflow.
315 * It is typically send after sending a FLUSH_START event to make the
316 * pads accept data again.
318 * Elements can process this event synchronized with the dataflow since
319 * the preceeding FLUSH_START event stopped the dataflow.
321 * This event is typically generated to complete a seek and to resume
324 * Returns: A new flush stop event.
327 gst_event_new_flush_stop (void)
329 return gst_event_new (GST_EVENT_FLUSH_STOP);
335 * Create a new EOS event. The eos event can only travel downstream
336 * synchronized with the buffer flow. Elements that receive the EOS
337 * event on a pad can return UNEXPECTED as a GstFlowReturn when data
338 * after the EOS event arrives.
340 * The EOS event will travel up to the sink elements in the pipeline
341 * which will then post the GST_MESSAGE_EOS on the bus.
343 * When all sinks have posted an EOS message, the EOS message is
344 * forwarded to the application.
346 * Returns: The new EOS event.
349 gst_event_new_eos (void)
351 return gst_event_new (GST_EVENT_EOS);
355 * gst_event_new_newsegment:
356 * @rate: a new rate for playback
357 * @format: The format of the segment values
358 * @start_value: the start value of the segment
359 * @stop_value: the stop value of the segment
360 * @base: base value for buffer timestamps.
362 * Allocate a new newsegment event with the given format/values tripplets.
364 * The newsegment event marks the range of buffers to be processed. All
365 * data not within the segment range is not to be processed. This can be
366 * used intelligently by plugins to use more efficient methods of skipping
369 * The base time of the segment is also used to convert the buffer timestamps
370 * into the stream time again.
372 * The @start_value cannot be -1, the @stop_value can be -1. If there
373 * is a valid @stop_value given, it must be smaller than @start_value.
375 * After a newsegment event, the buffer stream time is calculated with:
377 * TIMESTAMP(buf) - start_time + base
379 * Returns: A new newsegment event.
382 gst_event_new_newsegment (gdouble rate, GstFormat format,
383 gint64 start_value, gint64 stop_value, gint64 base)
385 if (format == GST_FORMAT_TIME) {
386 GST_CAT_INFO (GST_CAT_EVENT,
387 "creating newsegment rate %lf, format GST_FORMAT_TIME, "
388 "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
389 ", base %" GST_TIME_FORMAT,
390 rate, GST_TIME_ARGS (start_value),
391 GST_TIME_ARGS (stop_value), GST_TIME_ARGS (base));
393 GST_CAT_INFO (GST_CAT_EVENT,
394 "creating newsegment rate %lf, format %d, "
395 "start %lld, stop %lld, base %lld",
396 rate, format, start_value, stop_value, base);
398 if (start_value == -1)
399 g_return_val_if_fail (start_value != -1, NULL);
401 if (stop_value != -1)
402 g_return_val_if_fail (start_value <= stop_value, NULL);
404 return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
405 gst_structure_new ("GstEventNewsegment", "rate", G_TYPE_DOUBLE, rate,
406 "format", GST_TYPE_FORMAT, format,
407 "start_val", G_TYPE_INT64, start_value,
408 "stop_val", G_TYPE_INT64, stop_value,
409 "base", G_TYPE_INT64, base, NULL));
413 * gst_event_parse_newsegment:
414 * @event: The event to query
415 * @rate: A pointer to the rate of the segment
416 * @format: A pointer to the format of the newsegment values
417 * @start_value: A pointer to store the start value in
418 * @stop_value: A pointer to store the stop value in
419 * @base: A pointer to store the base time in
421 * Get the start, stop and format in the newsegment event.
424 gst_event_parse_newsegment (GstEvent * event, gdouble * rate,
425 GstFormat * format, gint64 * start_value, gint64 * stop_value,
428 const GstStructure *structure;
430 g_return_if_fail (GST_IS_EVENT (event));
431 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
433 structure = gst_event_get_structure (event);
435 *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
437 *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
440 g_value_get_int64 (gst_structure_get_value (structure, "start_val"));
443 g_value_get_int64 (gst_structure_get_value (structure, "stop_val"));
445 *base = g_value_get_int64 (gst_structure_get_value (structure, "base"));
450 * @taglist: metadata list
452 * Generates a metadata tag event from the given @taglist.
454 * Returns: a new #GstEvent
457 gst_event_new_tag (GstTagList * taglist)
459 g_return_val_if_fail (taglist != NULL, NULL);
461 return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
465 * gst_event_parse_tag:
466 * @event: a tag event
467 * @taglist: pointer to metadata list
469 * Parses a tag @event and stores the results in the given @taglist location.
472 gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
474 g_return_if_fail (GST_IS_EVENT (event));
475 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
478 *taglist = (GstTagList *) event->structure;
483 * gst_event_new_filler:
485 * Create a new dummy event that should be ignored.
487 * Returns: a new #GstEvent
490 gst_event_new_filler (void)
492 return gst_event_new (GST_EVENT_FILLER);
495 /* buffersize event */
497 * gst_event_new_buffersize:
498 * @format: buffer format
499 * @minsize: minimum buffer size
500 * @maxsize: maximum buffer size
501 * @async: thread behavior
503 * Create a new buffersize event. The event is sent downstream and notifies
504 * elements that they should provide a buffer of the specified dimensions.
506 * When the async flag is set, a thread boundary is prefered.
508 * Returns: a new #GstEvent
511 gst_event_new_buffersize (GstFormat format, gint64 minsize,
512 gint64 maxsize, gboolean async)
514 GST_CAT_INFO (GST_CAT_EVENT,
515 "creating buffersize format %d, minsize %" G_GINT64_FORMAT
516 ", maxsize %" G_GINT64_FORMAT ", async %d", format,
517 minsize, maxsize, async);
519 return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
520 gst_structure_new ("GstEventBufferSize",
521 "format", GST_TYPE_FORMAT, format,
522 "minsize", G_TYPE_INT64, minsize,
523 "maxsize", G_TYPE_INT64, maxsize,
524 "async", G_TYPE_BOOLEAN, async, NULL));
528 * gst_event_parse_buffersize:
529 * @event: The event to query
530 * @format: A pointer to store the format in
531 * @minsize: A pointer to store the minsize in
532 * @maxsize: A pointer to store the maxsize in
533 * @async: A pointer to store the async-flag in
535 * Get the format, minsize, maxsize and async-flag in the buffersize event.
538 gst_event_parse_buffersize (GstEvent * event, GstFormat * format,
539 gint64 * minsize, gint64 * maxsize, gboolean * async)
541 const GstStructure *structure;
543 g_return_if_fail (GST_IS_EVENT (event));
544 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
546 structure = gst_event_get_structure (event);
548 *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
551 g_value_get_int64 (gst_structure_get_value (structure, "minsize"));
554 g_value_get_int64 (gst_structure_get_value (structure, "maxsize"));
556 *async = g_value_get_boolean (gst_structure_get_value (structure, "async"));
561 * @proportion: the proportion of the qos message
562 * @diff: The time difference of the last Clock sync
563 * @timestamp: The timestamp of the buffer
565 * Allocate a new qos event with the given values.
566 * The QOS event is generated in an element that wants an upstream
567 * element to either reduce or increase its rate because of
570 * proportion is the requested adjustment in datarate, 1.0 is the normal
571 * datarate, 0.75 means increase datarate by 75%, 1.5 is 150%. Negative
572 * values request a slow down, so -0.75 means a decrease by 75%.
574 * diff is the difference against the clock in stream time of the last
575 * buffer that caused the element to generate the QOS event.
577 * timestamp is the timestamp of the last buffer that cause the element
578 * to generate the QOS event.
580 * Returns: A new QOS event.
583 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
584 GstClockTime timestamp)
586 GST_CAT_INFO (GST_CAT_EVENT,
587 "creating qos proportion %lf, diff %" GST_TIME_FORMAT
588 ", timestamp %" GST_TIME_FORMAT, proportion,
589 GST_TIME_ARGS (diff), GST_TIME_ARGS (timestamp));
591 return gst_event_new_custom (GST_EVENT_QOS,
592 gst_structure_new ("GstEventQOS",
593 "proportion", G_TYPE_DOUBLE, proportion,
594 "diff", G_TYPE_INT64, diff,
595 "timestamp", G_TYPE_UINT64, timestamp, NULL));
599 * gst_event_parse_qos:
600 * @event: The event to query
601 * @proportion: A pointer to store the proportion in
602 * @diff: A pointer to store the diff in
603 * @timestamp: A pointer to store the timestamp in
605 * Get the proportion, diff and timestamp in the qos event.
608 gst_event_parse_qos (GstEvent * event, gdouble * proportion,
609 GstClockTimeDiff * diff, GstClockTime * timestamp)
611 const GstStructure *structure;
613 g_return_if_fail (GST_IS_EVENT (event));
614 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
616 structure = gst_event_get_structure (event);
619 g_value_get_double (gst_structure_get_value (structure, "proportion"));
621 *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
624 g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
628 * gst_event_new_seek:
629 * @rate: The new playback rate
630 * @format: The format of the seek values
631 * @flags: The optional seek flags.
632 * @cur_type: The type and flags for the new current position
633 * @cur: The value of the new current position
634 * @stop_type: The type and flags for the new stop position
635 * @stop: The value of the new stop position
637 * Allocate a new seek event with the given parameters.
639 * The seek event configures playback of the pipeline from
640 * @cur to @stop at the speed given in @rate.
641 * The @cur and @stop values are expressed in format @format.
643 * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
644 * Negatives values means backwards playback. A value of 0.0 for the
645 * rate is not allowed.
647 * @cur_type and @stop_type specify how to adjust the current and stop
648 * time, relative or absolute. A type of #GST_EVENT_TYPE_NONE means that
649 * the position should not be updated.
651 * Returns: A new seek event.
654 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
655 GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
657 if (format == GST_FORMAT_TIME) {
658 GST_CAT_INFO (GST_CAT_EVENT,
659 "creating seek rate %lf, format TIME, flags %d, "
660 "cur_type %d, cur %" GST_TIME_FORMAT ", "
661 "stop_type %d, stop %" GST_TIME_FORMAT,
662 rate, flags, cur_type, GST_TIME_ARGS (cur),
663 stop_type, GST_TIME_ARGS (stop));
665 GST_CAT_INFO (GST_CAT_EVENT,
666 "creating seek rate %lf, format %d, flags %d, "
667 "cur_type %d, cur %" G_GINT64_FORMAT ", "
668 "stop_type %d, stop %" G_GINT64_FORMAT,
669 rate, format, flags, cur_type, cur, stop_type, stop);
672 return gst_event_new_custom (GST_EVENT_SEEK,
673 gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
674 "format", GST_TYPE_FORMAT, format,
675 "flags", GST_TYPE_SEEK_FLAGS, flags,
676 "cur_type", GST_TYPE_SEEK_TYPE, cur_type,
677 "cur", G_TYPE_INT64, cur,
678 "stop_type", GST_TYPE_SEEK_TYPE, stop_type,
679 "stop", G_TYPE_INT64, stop, NULL));
683 * gst_event_parse_seek:
684 * @event: a seek event
685 * @rate: result location for the rate
686 * @format: result location for the stream format
687 * @flags: result location for the #GstSeekFlags
688 * @cur_type: result location for the #GstSeekType of the current position
689 * @cur: result location for the current postion expressed in @format
690 * @stop_type: result location for the #GstSeekType of the stop position
691 * @stop: result location for the stop postion expressed in @format
693 * Parses a seek @event and stores the results in the given result locations.
696 gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
697 GstSeekFlags * flags,
698 GstSeekType * cur_type, gint64 * cur,
699 GstSeekType * stop_type, gint64 * stop)
701 const GstStructure *structure;
703 g_return_if_fail (GST_IS_EVENT (event));
704 g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
706 structure = gst_event_get_structure (event);
708 *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
710 *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
712 *flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
715 g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
717 *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
720 g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
722 *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
726 * gst_event_new_navigation:
727 * @structure: description of the event
729 * Create a new navigation event from the given description.
731 * Returns: a new #GstEvent
734 gst_event_new_navigation (GstStructure * structure)
736 g_return_val_if_fail (structure != NULL, NULL);
738 return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);