|
1 /* GStreamer |
|
2 * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com> |
|
3 * |
|
4 * This library is free software; you can redistribute it and/or |
|
5 * modify it under the terms of the GNU Library General Public |
|
6 * License as published by the Free Software Foundation; either |
|
7 * version 2 of the License, or (at your option) any later version. |
|
8 * |
|
9 * This library is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 * Library General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU Library General Public |
|
15 * License along with this library; if not, write to the |
|
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
17 * Boston, MA 02111-1307, USA. |
|
18 */ |
|
19 #include <string.h> |
|
20 |
|
21 #include "gstfactorylists.h" |
|
22 |
|
23 typedef struct |
|
24 { |
|
25 GstFactoryListType type; |
|
26 } FilterData; |
|
27 |
|
28 /* function used to sort element features. We first sort on the rank, then |
|
29 * on the element name (to get a consistent, predictable list) */ |
|
30 static gint |
|
31 compare_ranks (GValue * v1, GValue * v2) |
|
32 { |
|
33 gint diff; |
|
34 const gchar *rname1, *rname2; |
|
35 GstPluginFeature *f1, *f2; |
|
36 |
|
37 f1 = g_value_get_object (v1); |
|
38 f2 = g_value_get_object (v2); |
|
39 |
|
40 diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1); |
|
41 if (diff != 0) |
|
42 return diff; |
|
43 |
|
44 rname1 = gst_plugin_feature_get_name (f1); |
|
45 rname2 = gst_plugin_feature_get_name (f2); |
|
46 |
|
47 diff = strcmp (rname2, rname1); |
|
48 |
|
49 return diff; |
|
50 } |
|
51 |
|
52 /* the filter function for selecting the elements we can use in |
|
53 * autoplugging */ |
|
54 static gboolean |
|
55 decoders_filter (GstElementFactory * factory) |
|
56 { |
|
57 guint rank; |
|
58 const gchar *klass; |
|
59 |
|
60 klass = gst_element_factory_get_klass (factory); |
|
61 /* only demuxers, decoders, depayloaders and parsers can play */ |
|
62 if (strstr (klass, "Demux") == NULL && |
|
63 strstr (klass, "Decoder") == NULL && |
|
64 strstr (klass, "Depayloader") == NULL && |
|
65 strstr (klass, "Parse") == NULL) { |
|
66 return FALSE; |
|
67 } |
|
68 |
|
69 /* only select elements with autoplugging rank */ |
|
70 rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory)); |
|
71 if (rank < GST_RANK_MARGINAL) |
|
72 return FALSE; |
|
73 |
|
74 return TRUE; |
|
75 } |
|
76 |
|
77 /* the filter function for selecting the elements we can use in |
|
78 * autoplugging */ |
|
79 static gboolean |
|
80 sinks_filter (GstElementFactory * factory) |
|
81 { |
|
82 guint rank; |
|
83 const gchar *klass; |
|
84 |
|
85 klass = gst_element_factory_get_klass (factory); |
|
86 /* only sinks can play */ |
|
87 if (strstr (klass, "Sink") == NULL) { |
|
88 return FALSE; |
|
89 } |
|
90 |
|
91 /* must be audio or video sink */ |
|
92 if (strstr (klass, "Audio") == NULL && strstr (klass, "Video") == NULL) { |
|
93 return FALSE; |
|
94 } |
|
95 |
|
96 /* only select elements with autoplugging rank */ |
|
97 rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory)); |
|
98 if (rank < GST_RANK_MARGINAL) |
|
99 return FALSE; |
|
100 |
|
101 return TRUE; |
|
102 } |
|
103 |
|
104 /** |
|
105 * gst_factory_list_is_type: |
|
106 * @factory: a #GstElementFactory |
|
107 * @type: a #GstFactoryListType |
|
108 * |
|
109 * Check if @factory if of the given types. |
|
110 * |
|
111 * Returns: %TRUE if @factory is of @type. |
|
112 */ |
|
113 #ifdef __SYMBIAN32__ |
|
114 EXPORT_C |
|
115 #endif |
|
116 |
|
117 gboolean |
|
118 gst_factory_list_is_type (GstElementFactory * factory, GstFactoryListType type) |
|
119 { |
|
120 gboolean res = FALSE; |
|
121 |
|
122 if (!res && (type & GST_FACTORY_LIST_SINK)) |
|
123 res = sinks_filter (factory); |
|
124 if (!res && (type & GST_FACTORY_LIST_DECODER)) |
|
125 res = decoders_filter (factory); |
|
126 |
|
127 return res; |
|
128 } |
|
129 |
|
130 static gboolean |
|
131 element_filter (GstPluginFeature * feature, FilterData * data) |
|
132 { |
|
133 gboolean res; |
|
134 |
|
135 /* we only care about element factories */ |
|
136 if (!GST_IS_ELEMENT_FACTORY (feature)) |
|
137 return FALSE; |
|
138 |
|
139 res = gst_factory_list_is_type (GST_ELEMENT_FACTORY (feature), data->type); |
|
140 |
|
141 return res; |
|
142 } |
|
143 |
|
144 /** |
|
145 * gst_factory_list_get_elements: |
|
146 * @type: a #GstFactoryListType |
|
147 * |
|
148 * Get a sorted list of factories of @type. |
|
149 * |
|
150 * Returns: a #GValueArray of #GstElementFactory elements. Use |
|
151 * g_value_array_free() after usage. |
|
152 */ |
|
153 #ifdef __SYMBIAN32__ |
|
154 EXPORT_C |
|
155 #endif |
|
156 |
|
157 GValueArray * |
|
158 gst_factory_list_get_elements (GstFactoryListType type) |
|
159 { |
|
160 GValueArray *result; |
|
161 GList *walk, *list; |
|
162 FilterData data; |
|
163 |
|
164 result = g_value_array_new (0); |
|
165 |
|
166 /* prepare type */ |
|
167 data.type = type; |
|
168 |
|
169 /* get the feature list using the filter */ |
|
170 list = |
|
171 gst_default_registry_feature_filter ((GstPluginFeatureFilter) |
|
172 element_filter, FALSE, &data); |
|
173 |
|
174 /* convert to an array */ |
|
175 for (walk = list; walk; walk = g_list_next (walk)) { |
|
176 GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data); |
|
177 GValue val = { 0, }; |
|
178 |
|
179 g_value_init (&val, G_TYPE_OBJECT); |
|
180 g_value_set_object (&val, factory); |
|
181 g_value_array_append (result, &val); |
|
182 g_value_unset (&val); |
|
183 } |
|
184 gst_plugin_feature_list_free (list); |
|
185 |
|
186 /* sort on rank and name */ |
|
187 g_value_array_sort (result, (GCompareFunc) compare_ranks); |
|
188 |
|
189 return result; |
|
190 } |
|
191 |
|
192 /** |
|
193 * gst_factory_list_debug: |
|
194 * @array: an array of element factories |
|
195 * |
|
196 * Debug the element factory names in @array. |
|
197 */ |
|
198 #ifdef __SYMBIAN32__ |
|
199 EXPORT_C |
|
200 #endif |
|
201 |
|
202 void |
|
203 gst_factory_list_debug (GValueArray * array) |
|
204 { |
|
205 gint i; |
|
206 |
|
207 for (i = 0; i < array->n_values; i++) { |
|
208 GValue *value; |
|
209 GstPluginFeature *feature; |
|
210 |
|
211 value = g_value_array_get_nth (array, i); |
|
212 feature = g_value_get_object (value); |
|
213 |
|
214 GST_DEBUG ("%s", gst_plugin_feature_get_name (feature)); |
|
215 } |
|
216 } |
|
217 |
|
218 /** |
|
219 * gst_factory_list_filter: |
|
220 * @array: a #GValueArray to filter |
|
221 * @caps: a #GstCaps |
|
222 * |
|
223 * Filter out all the elementfactories in @array that can handle @caps as |
|
224 * input. |
|
225 * |
|
226 * Returns: a #GValueArray of #GstElementFactory elements. Use |
|
227 * g_value_array_free() after usage. |
|
228 */ |
|
229 #ifdef __SYMBIAN32__ |
|
230 EXPORT_C |
|
231 #endif |
|
232 |
|
233 GValueArray * |
|
234 gst_factory_list_filter (GValueArray * array, const GstCaps * caps) |
|
235 { |
|
236 GValueArray *result; |
|
237 gint i; |
|
238 |
|
239 result = g_value_array_new (0); |
|
240 |
|
241 GST_DEBUG ("finding factories"); |
|
242 |
|
243 /* loop over all the factories */ |
|
244 for (i = 0; i < array->n_values; i++) { |
|
245 GValue *value; |
|
246 GstElementFactory *factory; |
|
247 const GList *templates; |
|
248 GList *walk; |
|
249 |
|
250 value = g_value_array_get_nth (array, i); |
|
251 factory = g_value_get_object (value); |
|
252 |
|
253 /* get the templates from the element factory */ |
|
254 templates = gst_element_factory_get_static_pad_templates (factory); |
|
255 for (walk = (GList *) templates; walk; walk = g_list_next (walk)) { |
|
256 GstStaticPadTemplate *templ = walk->data; |
|
257 |
|
258 /* we only care about the sink templates */ |
|
259 if (templ->direction == GST_PAD_SINK) { |
|
260 GstCaps *intersect; |
|
261 GstCaps *tmpl_caps; |
|
262 |
|
263 /* try to intersect the caps with the caps of the template */ |
|
264 tmpl_caps = gst_static_caps_get (&templ->static_caps); |
|
265 |
|
266 /* FIXME, intersect is not the right method, we ideally want to check |
|
267 * for a subset here */ |
|
268 intersect = gst_caps_intersect (caps, tmpl_caps); |
|
269 gst_caps_unref (tmpl_caps); |
|
270 |
|
271 /* check if the intersection is empty */ |
|
272 if (!gst_caps_is_empty (intersect)) { |
|
273 /* non empty intersection, we can use this element */ |
|
274 GValue resval = { 0, }; |
|
275 g_value_init (&resval, G_TYPE_OBJECT); |
|
276 g_value_set_object (&resval, factory); |
|
277 g_value_array_append (result, &resval); |
|
278 g_value_unset (&resval); |
|
279 gst_caps_unref (intersect); |
|
280 break; |
|
281 } |
|
282 gst_caps_unref (intersect); |
|
283 } |
|
284 } |
|
285 } |
|
286 return result; |
|
287 } |