1 /* GStreamer
2 * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
3 *
4 * gsttypefindfactory.c: 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., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 /**
23 * SECTION:gsttypefindfactory
24 * @title: GstTypeFindFactory
25 * @short_description: Information about registered typefind functions
26 *
27 * These functions allow querying information about registered typefind
28 * functions. How to create and register these functions is described in
29 * the section <link linkend="gstreamer-Writing-typefind-functions">
30 * "Writing typefind functions"</link>.
31 *
32 * The following example shows how to write a very simple typefinder that
33 * identifies the given data. You can get quite a bit more complicated than
34 * that though.
35 * |[<!-- language="C" -->
36 * typedef struct {
37 * guint8 *data;
38 * guint size;
39 * guint probability;
40 * GstCaps *data;
41 * } MyTypeFind;
42 * static void
43 * my_peek (gpointer data, gint64 offset, guint size)
44 * {
45 * MyTypeFind *find = (MyTypeFind *) data;
46 * if (offset >= 0 && offset + size <= find->size) {
47 * return find->data + offset;
48 * }
49 * return NULL;
50 * }
51 * static void
52 * my_suggest (gpointer data, guint probability, GstCaps *caps)
53 * {
54 * MyTypeFind *find = (MyTypeFind *) data;
55 * if (probability > find->probability) {
56 * find->probability = probability;
57 * gst_caps_replace (&find->caps, caps);
58 * }
59 * }
60 * static GstCaps *
61 * find_type (guint8 *data, guint size)
62 * {
63 * GList *walk, *type_list;
64 * MyTypeFind find = {data, size, 0, NULL};
65 * GstTypeFind gst_find = {my_peek, my_suggest, &find, };
66 * walk = type_list = gst_type_find_factory_get_list ();
67 * while (walk) {
68 * GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data);
69 * walk = g_list_next (walk)
70 * gst_type_find_factory_call_function (factory, &gst_find);
71 * }
72 * g_list_free (type_list);
73 * return find.caps;
74 * };
75 * ]|
76 */
77
78 #include "gst_private.h"
79 #include "gstinfo.h"
80 #include "gsttypefind.h"
81 #include "gsttypefindfactory.h"
82 #include "gstregistry.h"
83
84 GST_DEBUG_CATEGORY (type_find_debug);
85 #define GST_CAT_DEFAULT type_find_debug
86
87 static void gst_type_find_factory_dispose (GObject * object);
88
89 #define _do_init \
90 { \
91 GST_DEBUG_CATEGORY_INIT (type_find_debug, "GST_TYPEFIND", \
92 GST_DEBUG_FG_GREEN, "typefinding subsystem"); \
93 }
94
95 #define gst_type_find_factory_parent_class parent_class
96 G_DEFINE_TYPE_WITH_CODE (GstTypeFindFactory, gst_type_find_factory,
97 GST_TYPE_PLUGIN_FEATURE, _do_init);
98
99 static void
gst_type_find_factory_class_init(GstTypeFindFactoryClass * klass)100 gst_type_find_factory_class_init (GstTypeFindFactoryClass * klass)
101 {
102 GObjectClass *object_class = G_OBJECT_CLASS (klass);
103
104 object_class->dispose = gst_type_find_factory_dispose;
105 }
106
107 static void
gst_type_find_factory_init(GstTypeFindFactory * factory)108 gst_type_find_factory_init (GstTypeFindFactory * factory)
109 {
110 factory->user_data = factory;
111 factory->user_data_notify = NULL;
112 }
113
114 static void
gst_type_find_factory_dispose(GObject * object)115 gst_type_find_factory_dispose (GObject * object)
116 {
117 GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (object);
118
119 if (factory->caps) {
120 gst_caps_unref (factory->caps);
121 factory->caps = NULL;
122 }
123 if (factory->extensions) {
124 g_strfreev (factory->extensions);
125 factory->extensions = NULL;
126 }
127 if (factory->user_data_notify && factory->user_data) {
128 factory->user_data_notify (factory->user_data);
129 factory->user_data = NULL;
130 }
131
132 G_OBJECT_CLASS (parent_class)->dispose (object);
133 }
134
135 /**
136 * gst_type_find_factory_get_list:
137 *
138 * Gets the list of all registered typefind factories. You must free the
139 * list using gst_plugin_feature_list_free().
140 *
141 * The returned factories are sorted by highest rank first, and then by
142 * factory name.
143 *
144 * Free-function: gst_plugin_feature_list_free
145 *
146 * Returns: (transfer full) (element-type Gst.TypeFindFactory): the list of all
147 * registered #GstTypeFindFactory.
148 */
149 GList *
gst_type_find_factory_get_list(void)150 gst_type_find_factory_get_list (void)
151 {
152 return gst_registry_get_feature_list (gst_registry_get (),
153 GST_TYPE_TYPE_FIND_FACTORY);
154 }
155
156 /**
157 * gst_type_find_factory_get_caps:
158 * @factory: A #GstTypeFindFactory
159 *
160 * Gets the #GstCaps associated with a typefind factory.
161 *
162 * Returns: (transfer none): the #GstCaps associated with this factory
163 */
164 GstCaps *
gst_type_find_factory_get_caps(GstTypeFindFactory * factory)165 gst_type_find_factory_get_caps (GstTypeFindFactory * factory)
166 {
167 g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), NULL);
168
169 return factory->caps;
170 }
171
172 /**
173 * gst_type_find_factory_get_extensions:
174 * @factory: A #GstTypeFindFactory
175 *
176 * Gets the extensions associated with a #GstTypeFindFactory. The returned
177 * array should not be changed. If you need to change stuff in it, you should
178 * copy it using g_strdupv(). This function may return %NULL to indicate
179 * a 0-length list.
180 *
181 * Returns: (transfer none) (array zero-terminated=1) (element-type utf8) (nullable):
182 * a %NULL-terminated array of extensions associated with this factory
183 */
184 const gchar *const *
gst_type_find_factory_get_extensions(GstTypeFindFactory * factory)185 gst_type_find_factory_get_extensions (GstTypeFindFactory * factory)
186 {
187 g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), NULL);
188
189 return (const gchar * const *) factory->extensions;
190 }
191
192 /**
193 * gst_type_find_factory_call_function:
194 * @factory: A #GstTypeFindFactory
195 * @find: (transfer none): a properly setup #GstTypeFind entry. The get_data
196 * and suggest_type members must be set.
197 *
198 * Calls the #GstTypeFindFunction associated with this factory.
199 */
200 void
gst_type_find_factory_call_function(GstTypeFindFactory * factory,GstTypeFind * find)201 gst_type_find_factory_call_function (GstTypeFindFactory * factory,
202 GstTypeFind * find)
203 {
204 GstTypeFindFactory *new_factory;
205
206 g_return_if_fail (GST_IS_TYPE_FIND_FACTORY (factory));
207 g_return_if_fail (find != NULL);
208 g_return_if_fail (find->peek != NULL);
209 g_return_if_fail (find->suggest != NULL);
210
211 new_factory =
212 GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
213 (factory)));
214 if (new_factory) {
215 if (new_factory->function)
216 new_factory->function (find, new_factory->user_data);
217 gst_object_unref (new_factory);
218 }
219 }
220
221 /**
222 * gst_type_find_factory_has_function:
223 * @factory: A #GstTypeFindFactory
224 *
225 * Check whether the factory has a typefind function. Typefind factories
226 * without typefind functions are a last-effort fallback mechanism to
227 * e.g. assume a certain media type based on the file extension.
228 *
229 * Returns: %TRUE if the factory has a typefind functions set, otherwise %FALSE
230 */
231 gboolean
gst_type_find_factory_has_function(GstTypeFindFactory * factory)232 gst_type_find_factory_has_function (GstTypeFindFactory * factory)
233 {
234 g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), FALSE);
235
236 return (factory->function != NULL);
237 }
238