Merging gst-plugins-good
[platform/upstream/gstreamer.git] / subprojects / gstreamer / 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  * @title: GstContext
27  * @short_description: Lightweight objects to represent element contexts
28  * @see_also: #GstMiniObject, #GstElement
29  *
30  * #GstContext is a container object used to store contexts like a device
31  * context, a display server connection and similar concepts that should
32  * be shared between multiple elements.
33  *
34  * Applications can set a context on a complete pipeline by using
35  * gst_element_set_context(), which will then be propagated to all
36  * child elements. Elements can handle these in #GstElementClass::set_context
37  * and merge them with the context information they already have.
38  *
39  * When an element needs a context it will do the following actions in this
40  * order until one step succeeds:
41  *
42  * 1. Check if the element already has a context
43  * 2. Query downstream with %GST_QUERY_CONTEXT for the context
44  * 3. Query upstream with %GST_QUERY_CONTEXT for the context
45  * 4. Post a %GST_MESSAGE_NEED_CONTEXT message on the bus with the required
46  *    context types and afterwards check if a usable context was set now
47  * 5. Create a context by itself and post a %GST_MESSAGE_HAVE_CONTEXT message
48  *    on the bus.
49  *
50  * Bins will catch %GST_MESSAGE_NEED_CONTEXT messages and will set any previously
51  * known context on the element that asks for it if possible. Otherwise the
52  * application should provide one if it can.
53  *
54  * #GstContext can be persistent.
55  * A persistent #GstContext is kept in elements when they reach
56  * %GST_STATE_NULL, non-persistent ones will be removed.
57  * Also, a non-persistent context won't override a previous persistent
58  * context set to an element.
59  *
60  * Since: 1.2
61  */
62
63 #define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
64 #include "gst_private.h"
65 #include <string.h>
66 #include "gstcontext.h"
67 #include "gstquark.h"
68
69 struct _GstContext
70 {
71   GstMiniObject mini_object;
72
73   gchar *context_type;
74   GstStructure *structure;
75   gboolean persistent;
76 };
77
78 #define GST_CONTEXT_STRUCTURE(c)  (((GstContext *)(c))->structure)
79
80 GType _gst_context_type = 0;
81 GST_DEFINE_MINI_OBJECT_TYPE (GstContext, gst_context);
82
83 void
84 _priv_gst_context_initialize (void)
85 {
86   GST_CAT_INFO (GST_CAT_GST_INIT, "init contexts");
87
88   /* the GstMiniObject types need to be class_ref'd once before it can be
89    * done from multiple threads;
90    * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
91   gst_context_get_type ();
92
93   _gst_context_type = gst_context_get_type ();
94 }
95
96 static void
97 _gst_context_free (GstContext * context)
98 {
99   GstStructure *structure;
100
101   g_return_if_fail (context != NULL);
102
103   GST_CAT_LOG (GST_CAT_CONTEXT, "finalize context %p: %" GST_PTR_FORMAT,
104       context, GST_CONTEXT_STRUCTURE (context));
105
106   structure = GST_CONTEXT_STRUCTURE (context);
107   if (structure) {
108     gst_structure_set_parent_refcount (structure, NULL);
109     gst_structure_free (structure);
110   }
111   g_free (context->context_type);
112
113 #ifdef USE_POISONING
114   memset (context, 0xff, sizeof (GstContext));
115 #endif
116
117   g_slice_free1 (sizeof (GstContext), context);
118 }
119
120 static void gst_context_init (GstContext * context);
121
122 static GstContext *
123 _gst_context_copy (GstContext * context)
124 {
125   GstContext *copy;
126   GstStructure *structure;
127
128   GST_CAT_LOG (GST_CAT_CONTEXT, "copy context %p: %" GST_PTR_FORMAT, context,
129       GST_CONTEXT_STRUCTURE (context));
130
131   copy = g_slice_new0 (GstContext);
132
133   gst_context_init (copy);
134
135   copy->context_type = g_strdup (context->context_type);
136
137   structure = GST_CONTEXT_STRUCTURE (context);
138   GST_CONTEXT_STRUCTURE (copy) = gst_structure_copy (structure);
139   gst_structure_set_parent_refcount (GST_CONTEXT_STRUCTURE (copy),
140       &copy->mini_object.refcount);
141
142   copy->persistent = context->persistent;
143
144   return GST_CONTEXT_CAST (copy);
145 }
146
147 static void
148 gst_context_init (GstContext * context)
149 {
150   gst_mini_object_init (GST_MINI_OBJECT_CAST (context), 0, _gst_context_type,
151       (GstMiniObjectCopyFunction) _gst_context_copy, NULL,
152       (GstMiniObjectFreeFunction) _gst_context_free);
153 }
154
155 /**
156  * gst_context_new:
157  * @context_type: Context type
158  * @persistent: Persistent context
159  *
160  * Creates a new context.
161  *
162  * Returns: (transfer full): The new context.
163  *
164  * Since: 1.2
165  */
166 GstContext *
167 gst_context_new (const gchar * context_type, gboolean persistent)
168 {
169   GstContext *context;
170   GstStructure *structure;
171
172   g_return_val_if_fail (context_type != NULL, NULL);
173
174   context = g_slice_new0 (GstContext);
175
176   GST_CAT_LOG (GST_CAT_CONTEXT, "creating new context %p", context);
177
178   structure = gst_structure_new_id_empty (GST_QUARK (CONTEXT));
179   gst_structure_set_parent_refcount (structure, &context->mini_object.refcount);
180   gst_context_init (context);
181
182   context->context_type = g_strdup (context_type);
183   GST_CONTEXT_STRUCTURE (context) = structure;
184   context->persistent = persistent;
185
186   return context;
187 }
188
189 /**
190  * gst_context_get_context_type:
191  * @context: The #GstContext.
192  *
193  * Gets the type of @context.
194  *
195  * Returns: The type of the context.
196  *
197  * Since: 1.2
198  */
199 const gchar *
200 gst_context_get_context_type (const GstContext * context)
201 {
202   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
203
204   return context->context_type;
205 }
206
207 /**
208  * gst_context_has_context_type:
209  * @context: The #GstContext.
210  * @context_type: Context type to check.
211  *
212  * Checks if @context has @context_type.
213  *
214  * Returns: %TRUE if @context has @context_type.
215  *
216  * Since: 1.2
217  */
218 gboolean
219 gst_context_has_context_type (const GstContext * context,
220     const gchar * context_type)
221 {
222   g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE);
223   g_return_val_if_fail (context_type != NULL, FALSE);
224
225   return strcmp (context->context_type, context_type) == 0;
226 }
227
228 /**
229  * gst_context_get_structure:
230  * @context: The #GstContext.
231  *
232  * Accesses the structure of the context.
233  *
234  * Returns: (transfer none): The structure of the context. The structure is
235  * still owned by the context, which means that you should not modify it,
236  * free it and that the pointer becomes invalid when you free the context.
237  *
238  * Since: 1.2
239  */
240 const GstStructure *
241 gst_context_get_structure (const GstContext * context)
242 {
243   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
244
245   return GST_CONTEXT_STRUCTURE (context);
246 }
247
248 /**
249  * gst_context_writable_structure:
250  * @context: The #GstContext.
251  *
252  * Gets a writable version of the structure.
253  *
254  * Returns: The structure of the context. The structure is still
255  * owned by the context, which means that you should not free it and
256  * that the pointer becomes invalid when you free the context.
257  * This function checks if @context is writable.
258  *
259  * Since: 1.2
260  */
261 GstStructure *
262 gst_context_writable_structure (GstContext * context)
263 {
264   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
265   g_return_val_if_fail (gst_context_is_writable (context), NULL);
266
267   return GST_CONTEXT_STRUCTURE (context);
268 }
269
270 /**
271  * gst_context_is_persistent:
272  * @context: The #GstContext.
273  *
274  * Checks if @context is persistent.
275  *
276  * Returns: %TRUE if the context is persistent.
277  *
278  * Since: 1.2
279  */
280 gboolean
281 gst_context_is_persistent (const GstContext * context)
282 {
283   g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE);
284
285   return context->persistent;
286 }
287
288 /**
289  * gst_context_ref:
290  * @context: the context to ref
291  *
292  * Convenience macro to increase the reference count of the context.
293  *
294  * Returns: @context (for convenience when doing assignments)
295  *
296  * Since: 1.2
297  */
298 GstContext *
299 gst_context_ref (GstContext * context)
300 {
301   return (GstContext *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (context));
302 }
303
304 /**
305  * gst_context_unref:
306  * @context: the context to unref
307  *
308  * Convenience macro to decrease the reference count of the context, possibly
309  * freeing it.
310  *
311  * Since: 1.2
312  */
313 void
314 gst_context_unref (GstContext * context)
315 {
316   gst_mini_object_unref (GST_MINI_OBJECT_CAST (context));
317 }
318
319 /**
320  * gst_context_copy:
321  * @context: the context to copy
322  *
323  * Creates a copy of the context. Returns a copy of the context.
324  *
325  * Returns: (transfer full): a new copy of @context.
326  *
327  * MT safe
328  *
329  * Since: 1.2
330  */
331 GstContext *
332 gst_context_copy (const GstContext * context)
333 {
334   return
335       GST_CONTEXT_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST
336           (context)));
337 }
338
339 /**
340  * gst_context_replace:
341  * @old_context: (inout) (transfer full): pointer to a pointer to a #GstContext
342  *     to be replaced.
343  * @new_context: (allow-none) (transfer none): pointer to a #GstContext that will
344  *     replace the context pointed to by @old_context.
345  *
346  * Modifies a pointer to a #GstContext to point to a different #GstContext. The
347  * modification is done atomically (so this is useful for ensuring thread safety
348  * in some cases), and the reference counts are updated appropriately (the old
349  * context is unreffed, the new one is reffed).
350  *
351  * Either @new_context or the #GstContext pointed to by @old_context may be %NULL.
352  *
353  * Returns: %TRUE if @new_context was different from @old_context
354  *
355  * Since: 1.2
356  */
357 gboolean
358 gst_context_replace (GstContext ** old_context, GstContext * new_context)
359 {
360   return gst_mini_object_replace ((GstMiniObject **) old_context,
361       (GstMiniObject *) new_context);
362 }