context: Add persistent qualifier for a context
[platform/upstream/gstreamer.git] / gst / gstcontext.c
1 /* GStreamer
2  * Copyright (C) 2013 Collabora Ltd.
3  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
4  * Copyright (C) 2013 Sebastian Dröge <slomo@circular-chaos.org>
5  *
6  * gstcontext.h: Header for GstContext subsystem
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 /**
25  * SECTION:gstcontext
26  * @short_description: Lightweight objects to represent element contexts
27  * @see_also: #GstMiniObject, #GstElement
28  *
29  * #GstContext is a container object used to store contexts like a device
30  * context, a display server connection and similar concepts that should
31  * be shared between multiple elements.
32  *
33  * Applications can set a context on a complete pipeline by using
34  * gst_element_set_context(), which will then be propagated to all
35  * child elements. Elements can handle these in GstElement::set_context()
36  * and merge them with the context information they already have.
37  *
38  * When an element needs a context it will do the following actions in this
39  * order until one step succeeds:
40  * 1) Check if the element already has a context
41  * 2) Query downstream with GST_QUERY_CONTEXT for the context
42  * 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required
43  *    context types and afterwards check if a usable context was set now
44  * 4) Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message
45  *    and send a GST_EVENT_CONTEXT event downstream, containing the complete
46  *    context information at this time.
47  *
48  * Applications should catch the GST_MESSAGE_HAVE_CONTEXT messages and remember
49  * any content from it unless it has a custom version of a specific context. If
50  * later an element is posting a GST_MESSAGE_NEED_CONTEXT message for a specific
51  * context that was created by an element before, the application should pass it
52  * to the element or the complete pipeline.
53  *
54  * Since: 1.2
55  */
56
57 #include "gst_private.h"
58 #include <string.h>
59 #include "gstcontext.h"
60 #include "gstquark.h"
61
62 struct _GstContext
63 {
64   GstMiniObject mini_object;
65
66   GstStructure *structure;
67   gboolean persistent;
68 };
69
70 #define GST_CONTEXT_STRUCTURE(c)  (((GstContext *)(c))->structure)
71
72 static GType _gst_context_type = 0;
73 GST_DEFINE_MINI_OBJECT_TYPE (GstContext, gst_context);
74
75 void
76 _priv_gst_context_initialize (void)
77 {
78   GST_CAT_INFO (GST_CAT_GST_INIT, "init contexts");
79
80   /* the GstMiniObject types need to be class_ref'd once before it can be
81    * done from multiple threads;
82    * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
83   gst_context_get_type ();
84
85   _gst_context_type = gst_context_get_type ();
86 }
87
88 static void
89 _gst_context_free (GstContext * context)
90 {
91   GstStructure *structure;
92
93   g_return_if_fail (context != NULL);
94
95   GST_CAT_LOG (GST_CAT_CONTEXT, "finalize context %p: %" GST_PTR_FORMAT,
96       context, GST_CONTEXT_STRUCTURE (context));
97
98   structure = GST_CONTEXT_STRUCTURE (context);
99   if (structure) {
100     gst_structure_set_parent_refcount (structure, NULL);
101     gst_structure_free (structure);
102   }
103
104   g_slice_free1 (sizeof (GstContext), context);
105 }
106
107 static void gst_context_init (GstContext * context);
108
109 static GstContext *
110 _gst_context_copy (GstContext * context)
111 {
112   GstContext *copy;
113   GstStructure *structure;
114
115   GST_CAT_LOG (GST_CAT_CONTEXT, "copy context %p: %" GST_PTR_FORMAT, context,
116       GST_CONTEXT_STRUCTURE (context));
117
118   copy = g_slice_new0 (GstContext);
119
120   gst_context_init (copy);
121
122   structure = GST_CONTEXT_STRUCTURE (context);
123   GST_CONTEXT_STRUCTURE (copy) = gst_structure_copy (structure);
124   gst_structure_set_parent_refcount (GST_CONTEXT_STRUCTURE (copy),
125       &copy->mini_object.refcount);
126
127   copy->persistent = context->persistent;
128
129   return GST_CONTEXT_CAST (copy);
130 }
131
132 static void
133 gst_context_init (GstContext * context)
134 {
135   gst_mini_object_init (GST_MINI_OBJECT_CAST (context), 0, _gst_context_type,
136       (GstMiniObjectCopyFunction) _gst_context_copy, NULL,
137       (GstMiniObjectFreeFunction) _gst_context_free);
138 }
139
140 /**
141  * gst_context_new:
142  * @persistent: Persistent context
143  *
144  * Create a new context.
145  *
146  * Returns: (transfer full): The new context.
147  *
148  * Since: 1.2
149  */
150 GstContext *
151 gst_context_new (gboolean persistent)
152 {
153   GstContext *context;
154   GstStructure *structure;
155
156   context = g_slice_new0 (GstContext);
157
158   GST_CAT_LOG (GST_CAT_CONTEXT, "creating new context %p", context);
159
160   structure = gst_structure_new_id_empty (GST_QUARK (CONTEXT));
161   gst_structure_set_parent_refcount (structure, &context->mini_object.refcount);
162   gst_context_init (context);
163
164   GST_CONTEXT_STRUCTURE (context) = structure;
165   context->persistent = persistent;
166
167   return context;
168 }
169
170 /**
171  * gst_context_get_structure:
172  * @context: The #GstContext.
173  *
174  * Access the structure of the context.
175  *
176  * Returns: (transfer none): The structure of the context. The structure is
177  * still owned by the context, which means that you should not modify it,
178  * free it and that the pointer becomes invalid when you free the context.
179  *
180  * Since: 1.2
181  */
182 const GstStructure *
183 gst_context_get_structure (const GstContext * context)
184 {
185   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
186
187   return GST_CONTEXT_STRUCTURE (context);
188 }
189
190 /**
191  * gst_context_writable_structure:
192  * @context: The #GstContext.
193  *
194  * Get a writable version of the structure.
195  *
196  * Returns: The structure of the context. The structure is still
197  * owned by the event, which means that you should not free it and
198  * that the pointer becomes invalid when you free the event.
199  * This function checks if @context is writable.
200  *
201  * Since: 1.2
202  */
203 GstStructure *
204 gst_context_writable_structure (GstContext * context)
205 {
206   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
207   g_return_val_if_fail (gst_context_is_writable (context), NULL);
208
209   return GST_CONTEXT_STRUCTURE (context);
210 }
211
212 /**
213  * gst_context_is_persistent:
214  * @context: The #GstContext.
215  *
216  * Check if @context is persistent.
217  *
218  * Returns: %TRUE if the context is persistent.
219  *
220  * Since: 1.2
221  */
222 gboolean
223 gst_context_is_persistent (const GstContext * context)
224 {
225   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
226
227   return context->persistent;
228 }