context: Change GstContext to contain only a single 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   gchar *context_type;
67   GstStructure *structure;
68   gboolean persistent;
69 };
70
71 #define GST_CONTEXT_STRUCTURE(c)  (((GstContext *)(c))->structure)
72
73 static GType _gst_context_type = 0;
74 GST_DEFINE_MINI_OBJECT_TYPE (GstContext, gst_context);
75
76 void
77 _priv_gst_context_initialize (void)
78 {
79   GST_CAT_INFO (GST_CAT_GST_INIT, "init contexts");
80
81   /* the GstMiniObject types need to be class_ref'd once before it can be
82    * done from multiple threads;
83    * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
84   gst_context_get_type ();
85
86   _gst_context_type = gst_context_get_type ();
87 }
88
89 static void
90 _gst_context_free (GstContext * context)
91 {
92   GstStructure *structure;
93
94   g_return_if_fail (context != NULL);
95
96   GST_CAT_LOG (GST_CAT_CONTEXT, "finalize context %p: %" GST_PTR_FORMAT,
97       context, GST_CONTEXT_STRUCTURE (context));
98
99   structure = GST_CONTEXT_STRUCTURE (context);
100   if (structure) {
101     gst_structure_set_parent_refcount (structure, NULL);
102     gst_structure_free (structure);
103   }
104
105   g_slice_free1 (sizeof (GstContext), context);
106 }
107
108 static void gst_context_init (GstContext * context);
109
110 static GstContext *
111 _gst_context_copy (GstContext * context)
112 {
113   GstContext *copy;
114   GstStructure *structure;
115
116   GST_CAT_LOG (GST_CAT_CONTEXT, "copy context %p: %" GST_PTR_FORMAT, context,
117       GST_CONTEXT_STRUCTURE (context));
118
119   copy = g_slice_new0 (GstContext);
120
121   gst_context_init (copy);
122
123   copy->context_type = g_strdup (context->context_type);
124
125   structure = GST_CONTEXT_STRUCTURE (context);
126   GST_CONTEXT_STRUCTURE (copy) = gst_structure_copy (structure);
127   gst_structure_set_parent_refcount (GST_CONTEXT_STRUCTURE (copy),
128       &copy->mini_object.refcount);
129
130   copy->persistent = context->persistent;
131
132   return GST_CONTEXT_CAST (copy);
133 }
134
135 static void
136 gst_context_init (GstContext * context)
137 {
138   gst_mini_object_init (GST_MINI_OBJECT_CAST (context), 0, _gst_context_type,
139       (GstMiniObjectCopyFunction) _gst_context_copy, NULL,
140       (GstMiniObjectFreeFunction) _gst_context_free);
141 }
142
143 /**
144  * gst_context_new:
145  * @persistent: Persistent context
146  *
147  * Create a new context.
148  *
149  * Returns: (transfer full): The new context.
150  *
151  * Since: 1.2
152  */
153 GstContext *
154 gst_context_new (const gchar * context_type, gboolean persistent)
155 {
156   GstContext *context;
157   GstStructure *structure;
158
159   g_return_val_if_fail (context_type != NULL, NULL);
160
161   context = g_slice_new0 (GstContext);
162
163   GST_CAT_LOG (GST_CAT_CONTEXT, "creating new context %p", context);
164
165   structure = gst_structure_new_id_empty (GST_QUARK (CONTEXT));
166   gst_structure_set_parent_refcount (structure, &context->mini_object.refcount);
167   gst_context_init (context);
168
169   context->context_type = g_strdup (context_type);
170   GST_CONTEXT_STRUCTURE (context) = structure;
171   context->persistent = persistent;
172
173   return context;
174 }
175
176 /**
177  * gst_context_get_context_type:
178  * @context: The #GstContext.
179  *
180  * Get the type of @context.
181  *
182  * Returns: The type of the context.
183  *
184  * Since: 1.2
185  */
186 const gchar *
187 gst_context_get_context_type (const GstContext * context)
188 {
189   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
190
191   return context->context_type;
192 }
193
194 /**
195  * gst_context_get_structure:
196  * @context: The #GstContext.
197  *
198  * Access the structure of the context.
199  *
200  * Returns: (transfer none): The structure of the context. The structure is
201  * still owned by the context, which means that you should not modify it,
202  * free it and that the pointer becomes invalid when you free the context.
203  *
204  * Since: 1.2
205  */
206 const GstStructure *
207 gst_context_get_structure (const GstContext * context)
208 {
209   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
210
211   return GST_CONTEXT_STRUCTURE (context);
212 }
213
214 /**
215  * gst_context_writable_structure:
216  * @context: The #GstContext.
217  *
218  * Get a writable version of the structure.
219  *
220  * Returns: The structure of the context. The structure is still
221  * owned by the event, which means that you should not free it and
222  * that the pointer becomes invalid when you free the event.
223  * This function checks if @context is writable.
224  *
225  * Since: 1.2
226  */
227 GstStructure *
228 gst_context_writable_structure (GstContext * context)
229 {
230   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
231   g_return_val_if_fail (gst_context_is_writable (context), NULL);
232
233   return GST_CONTEXT_STRUCTURE (context);
234 }
235
236 /**
237  * gst_context_is_persistent:
238  * @context: The #GstContext.
239  *
240  * Check if @context is persistent.
241  *
242  * Returns: %TRUE if the context is persistent.
243  *
244  * Since: 1.2
245  */
246 gboolean
247 gst_context_is_persistent (const GstContext * context)
248 {
249   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
250
251   return context->persistent;
252 }