1 | /* GStreamer |
---|
2 | * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de> |
---|
3 | * |
---|
4 | * gsttypefind.h: typefinding subsystem |
---|
5 | * |
---|
6 | * This library is free software; you can redistribute it and/or |
---|
7 | * modify it under the terms of the GNU Library General Public |
---|
8 | * License as published by the Free Software Foundation; either |
---|
9 | * version 2 of the License, or (at your option) any later version. |
---|
10 | * |
---|
11 | * This library is distributed in the hope that it will be useful, |
---|
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
14 | * Library General Public License for more details. |
---|
15 | * |
---|
16 | * You should have received a copy of the GNU Library General Public |
---|
17 | * License along with this library; if not, write to the |
---|
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
19 | * Boston, MA 02111-1307, USA. |
---|
20 | */ |
---|
21 | |
---|
22 | #include "gst_private.h" |
---|
23 | #include "gstinfo.h" |
---|
24 | #include "gsttypefind.h" |
---|
25 | #include "gstregistrypool.h" |
---|
26 | |
---|
27 | GST_DEBUG_CATEGORY_STATIC (gst_type_find_debug); |
---|
28 | #define GST_CAT_DEFAULT gst_type_find_debug |
---|
29 | |
---|
30 | static void gst_type_find_factory_class_init (gpointer g_class, |
---|
31 | gpointer class_data); |
---|
32 | static void gst_type_find_factory_init (GTypeInstance * instance, |
---|
33 | gpointer g_class); |
---|
34 | static void gst_type_find_factory_dispose (GObject * object); |
---|
35 | |
---|
36 | static void gst_type_find_factory_unload_thyself (GstPluginFeature * feature); |
---|
37 | |
---|
38 | static void gst_type_find_load_plugin (GstTypeFind * find, gpointer data); |
---|
39 | |
---|
40 | static GstPluginFeatureClass *parent_class = NULL; |
---|
41 | |
---|
42 | GType |
---|
43 | gst_type_find_factory_get_type (void) |
---|
44 | { |
---|
45 | static GType typefind_type = 0; |
---|
46 | |
---|
47 | if (!typefind_type) { |
---|
48 | static const GTypeInfo typefind_info = { |
---|
49 | sizeof (GstTypeFindFactoryClass), |
---|
50 | NULL, |
---|
51 | NULL, |
---|
52 | gst_type_find_factory_class_init, |
---|
53 | NULL, |
---|
54 | NULL, |
---|
55 | sizeof (GstTypeFindFactory), |
---|
56 | 0, |
---|
57 | gst_type_find_factory_init, |
---|
58 | NULL |
---|
59 | }; |
---|
60 | |
---|
61 | typefind_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, |
---|
62 | "GstTypeFindFactory", &typefind_info, 0); |
---|
63 | GST_DEBUG_CATEGORY_INIT (gst_type_find_debug, "GST_TYPEFIND", |
---|
64 | GST_DEBUG_FG_GREEN, "typefinding subsystem"); |
---|
65 | } |
---|
66 | |
---|
67 | return typefind_type; |
---|
68 | } |
---|
69 | static void |
---|
70 | gst_type_find_factory_class_init (gpointer g_class, gpointer class_data) |
---|
71 | { |
---|
72 | GstPluginFeatureClass *gstpluginfeature_class = |
---|
73 | GST_PLUGIN_FEATURE_CLASS (g_class); |
---|
74 | GObjectClass *object_class = G_OBJECT_CLASS (g_class); |
---|
75 | |
---|
76 | parent_class = g_type_class_peek_parent (g_class); |
---|
77 | |
---|
78 | object_class->dispose = gst_type_find_factory_dispose; |
---|
79 | |
---|
80 | gstpluginfeature_class->unload_thyself = |
---|
81 | GST_DEBUG_FUNCPTR (gst_type_find_factory_unload_thyself); |
---|
82 | } |
---|
83 | static void |
---|
84 | gst_type_find_factory_init (GTypeInstance * instance, gpointer g_class) |
---|
85 | { |
---|
86 | GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (instance); |
---|
87 | |
---|
88 | factory->user_data = factory; |
---|
89 | factory->function = gst_type_find_load_plugin; |
---|
90 | } |
---|
91 | static void |
---|
92 | gst_type_find_factory_dispose (GObject * object) |
---|
93 | { |
---|
94 | GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (object); |
---|
95 | |
---|
96 | if (factory->caps) { |
---|
97 | gst_caps_free (factory->caps); |
---|
98 | factory->caps = NULL; |
---|
99 | } |
---|
100 | if (factory->extensions) { |
---|
101 | g_strfreev (factory->extensions); |
---|
102 | factory->extensions = NULL; |
---|
103 | } |
---|
104 | } |
---|
105 | static void |
---|
106 | gst_type_find_factory_unload_thyself (GstPluginFeature * feature) |
---|
107 | { |
---|
108 | GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature); |
---|
109 | |
---|
110 | factory->function = gst_type_find_load_plugin; |
---|
111 | factory->user_data = factory; |
---|
112 | } |
---|
113 | static void |
---|
114 | gst_type_find_load_plugin (GstTypeFind * find, gpointer data) |
---|
115 | { |
---|
116 | GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (data); |
---|
117 | |
---|
118 | GST_DEBUG_OBJECT (factory, "need to load typefind function %s", |
---|
119 | GST_PLUGIN_FEATURE_NAME (factory)); |
---|
120 | |
---|
121 | if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) { |
---|
122 | if (factory->function == gst_type_find_load_plugin) { |
---|
123 | /* looks like we didn't get a real typefind function */ |
---|
124 | g_warning ("could not load valid typefind function for feature '%s'\n", |
---|
125 | GST_PLUGIN_FEATURE_NAME (factory)); |
---|
126 | } else { |
---|
127 | g_assert (factory->function); |
---|
128 | gst_type_find_factory_call_function (factory, find); |
---|
129 | } |
---|
130 | } |
---|
131 | } |
---|
132 | |
---|
133 | /** |
---|
134 | * gst_type_find_factory_get_list: |
---|
135 | * |
---|
136 | * Gets the list of all registered typefind factories. You must free the |
---|
137 | * list using g_list_free. |
---|
138 | * |
---|
139 | * Returns: the list of all registered typefind factories |
---|
140 | */ |
---|
141 | GList * |
---|
142 | gst_type_find_factory_get_list (void) |
---|
143 | { |
---|
144 | return gst_registry_pool_feature_list (GST_TYPE_TYPE_FIND_FACTORY); |
---|
145 | } |
---|
146 | |
---|
147 | /** |
---|
148 | * gst_type_find_factory_get_caps: |
---|
149 | * @factory: a factory |
---|
150 | * |
---|
151 | * Gets the caps associated with a typefind factory. |
---|
152 | * |
---|
153 | * Returns: the #GstCaps associated with this factory |
---|
154 | */ |
---|
155 | const GstCaps * |
---|
156 | gst_type_find_factory_get_caps (const GstTypeFindFactory * factory) |
---|
157 | { |
---|
158 | g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), NULL); |
---|
159 | |
---|
160 | return factory->caps; |
---|
161 | } |
---|
162 | |
---|
163 | /** |
---|
164 | * gst_type_find_factory_get_extensions: |
---|
165 | * @factory: a factory |
---|
166 | * |
---|
167 | * Gets the extensions associated with a typefind factory. The returned |
---|
168 | * array should not be changed. If you need to change stuff in it, you should |
---|
169 | * copy it using g_stdupv(). This function may return NULL to indicate |
---|
170 | * a 0-length list. |
---|
171 | * |
---|
172 | * Returns: a NULL-terminated array of extensions associated with this factory |
---|
173 | */ |
---|
174 | gchar ** |
---|
175 | gst_type_find_factory_get_extensions (const GstTypeFindFactory * factory) |
---|
176 | { |
---|
177 | g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), NULL); |
---|
178 | |
---|
179 | return factory->extensions; |
---|
180 | } |
---|
181 | |
---|
182 | /** |
---|
183 | * gst_type_find_factory_call_function: |
---|
184 | * @factory: a factory |
---|
185 | * @find: a properly setup #GstTypeFind entry. The get_data and suggest_type |
---|
186 | * members must be set. |
---|
187 | * |
---|
188 | * Calls the typefinding function associated with this factory. |
---|
189 | */ |
---|
190 | void |
---|
191 | gst_type_find_factory_call_function (const GstTypeFindFactory * factory, |
---|
192 | GstTypeFind * find) |
---|
193 | { |
---|
194 | g_return_if_fail (GST_IS_TYPE_FIND_FACTORY (factory)); |
---|
195 | g_return_if_fail (find != NULL); |
---|
196 | g_return_if_fail (find->peek != NULL); |
---|
197 | g_return_if_fail (find->suggest != NULL); |
---|
198 | |
---|
199 | /* should never happen */ |
---|
200 | g_assert (factory->function != NULL); |
---|
201 | |
---|
202 | factory->function (find, factory->user_data); |
---|
203 | } |
---|
204 | |
---|
205 | /** |
---|
206 | * gst_type_find_register: |
---|
207 | * @plugin: the GstPlugin to register with |
---|
208 | * @name: the name for registering |
---|
209 | * @rank: rank (or importance) of this typefind function |
---|
210 | * @func: the function to use for typefinding |
---|
211 | * @extensions: optional extensions that could belong to this type |
---|
212 | * @possible_caps: optionally the caps that could be returned when typefinding succeeds |
---|
213 | * @data: optional user data. This user data must be available until the plugin |
---|
214 | * is unloaded. |
---|
215 | * |
---|
216 | * Registers a new typefind function to be used for typefinding. After |
---|
217 | * registering this function will be available for typefinding. |
---|
218 | * This function is typically called during an element's plugin initialization. |
---|
219 | * |
---|
220 | * Returns: TRUE on success, FALSE otherwise |
---|
221 | */ |
---|
222 | gboolean |
---|
223 | gst_type_find_register (GstPlugin * plugin, const gchar * name, guint rank, |
---|
224 | GstTypeFindFunction func, gchar ** extensions, |
---|
225 | const GstCaps * possible_caps, gpointer data) |
---|
226 | { |
---|
227 | GstTypeFindFactory *factory; |
---|
228 | |
---|
229 | g_return_val_if_fail (plugin != NULL, FALSE); |
---|
230 | g_return_val_if_fail (name != NULL, FALSE); |
---|
231 | g_return_val_if_fail (func != NULL, FALSE); |
---|
232 | |
---|
233 | GST_INFO ("registering typefind function for %s", name); |
---|
234 | factory = |
---|
235 | GST_TYPE_FIND_FACTORY (gst_registry_pool_find_feature (name, |
---|
236 | GST_TYPE_TYPE_FIND_FACTORY)); |
---|
237 | if (!factory) { |
---|
238 | factory = g_object_new (GST_TYPE_TYPE_FIND_FACTORY, NULL); |
---|
239 | GST_DEBUG_OBJECT (factory, "using new typefind factory for %s", name); |
---|
240 | g_assert (GST_IS_TYPE_FIND_FACTORY (factory)); |
---|
241 | gst_plugin_feature_set_name (GST_PLUGIN_FEATURE (factory), name); |
---|
242 | gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); |
---|
243 | } else { |
---|
244 | GST_DEBUG_OBJECT (factory, "using old typefind factory for %s", name); |
---|
245 | } |
---|
246 | |
---|
247 | gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank); |
---|
248 | if (factory->extensions) |
---|
249 | g_strfreev (factory->extensions); |
---|
250 | |
---|
251 | factory->extensions = g_strdupv (extensions); |
---|
252 | gst_caps_replace (&factory->caps, gst_caps_copy (possible_caps)); |
---|
253 | factory->function = func; |
---|
254 | factory->user_data = data; |
---|
255 | |
---|
256 | return TRUE; |
---|
257 | } |
---|
258 | |
---|
259 | /*** typefind function interface **********************************************/ |
---|
260 | |
---|
261 | /** |
---|
262 | * gst_type_find_peek: |
---|
263 | * @find: the find object the function was called with |
---|
264 | * @offset: the offset |
---|
265 | * @size: the number of bytes to return |
---|
266 | * |
---|
267 | * Returns size bytes of the stream to identify beginning at offset. If offset |
---|
268 | * is a positive number, the offset is relative to the beginning of the stream, |
---|
269 | * if offset is a negative number the offset is relative to the end of the |
---|
270 | * stream. The returned memory is valid until the typefinding function returns |
---|
271 | * and must not be freed. |
---|
272 | * If NULL is returned, that data is not available. |
---|
273 | * |
---|
274 | * Returns: the requested data or NULL if that data is not available. |
---|
275 | */ |
---|
276 | guint8 * |
---|
277 | gst_type_find_peek (GstTypeFind * find, gint64 offset, guint size) |
---|
278 | { |
---|
279 | g_return_val_if_fail (find->peek != NULL, NULL); |
---|
280 | |
---|
281 | return find->peek (find->data, offset, size); |
---|
282 | } |
---|
283 | |
---|
284 | /** |
---|
285 | * gst_type_find_suggest: |
---|
286 | * @find: the find object the function was called with |
---|
287 | * @probability: the probability in percent that the suggestion is right |
---|
288 | * @caps: the fixed caps to suggest |
---|
289 | * |
---|
290 | * If a typefind function calls this function it suggests the caps with the |
---|
291 | * given probability. A typefind function may supply different suggestions |
---|
292 | * in one call. |
---|
293 | * It is up to the caller of the typefind function to interpret these values. |
---|
294 | */ |
---|
295 | void |
---|
296 | gst_type_find_suggest (GstTypeFind * find, guint probability, |
---|
297 | const GstCaps * caps) |
---|
298 | { |
---|
299 | g_return_if_fail (find->suggest != NULL); |
---|
300 | g_return_if_fail (probability <= 100); |
---|
301 | g_return_if_fail (caps != NULL); |
---|
302 | g_return_if_fail (gst_caps_is_fixed (caps)); |
---|
303 | |
---|
304 | find->suggest (find->data, probability, caps); |
---|
305 | } |
---|
306 | |
---|
307 | /** |
---|
308 | * gst_type_find_get_length: |
---|
309 | * @find: the find object the function was called with |
---|
310 | * |
---|
311 | * Get the length of the data stream. |
---|
312 | * |
---|
313 | * Returns: the length of the data stream or 0 if it is not available. |
---|
314 | */ |
---|
315 | guint64 |
---|
316 | gst_type_find_get_length (GstTypeFind * find) |
---|
317 | { |
---|
318 | if (find->get_length == NULL) |
---|
319 | return 0; |
---|
320 | |
---|
321 | return find->get_length (find->data); |
---|
322 | } |
---|