1 /* GStreamer
2 * Copyright (C) <2010> Edward Hervey <edward.hervey@collabora.co.uk>
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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "gstcapslist.h"
21
22 /*
23 * Caps listing convenience functions
24 */
25
26 static gboolean
remove_range_foreach(GQuark field_id,const GValue * value,GstStructure * st)27 remove_range_foreach (GQuark field_id, const GValue * value, GstStructure * st)
28 {
29 GType ftype = G_VALUE_TYPE (value);
30 /* const gchar *fname; */
31
32 if (ftype == GST_TYPE_INT_RANGE || ftype == GST_TYPE_DOUBLE_RANGE ||
33 ftype == GST_TYPE_FRACTION_RANGE) {
34 gst_structure_remove_field (st, g_quark_to_string (field_id));
35 return FALSE;
36 }
37
38 /* fname = g_quark_to_string (field_id); */
39 /* if (strstr (fname, "framerate") || strstr (fname, "pixel-aspect-ratio") || */
40 /* strstr (fname, "rate")) { */
41 /* gst_structure_remove_field (st, g_quark_to_string (field_id)); */
42 /* return FALSE; */
43 /* } */
44
45 return TRUE;
46 }
47
48 static void
clear_caps(GstCaps * caps,GstCaps * rescaps)49 clear_caps (GstCaps * caps, GstCaps * rescaps)
50 {
51 GstCaps *res;
52 GstStructure *st;
53 guint i;
54
55 res = gst_caps_make_writable (caps);
56
57 GST_DEBUG ("incoming caps %" GST_PTR_FORMAT, res);
58
59 /* Remove width/height/framerate/depth/width fields */
60 for (i = gst_caps_get_size (res); i; i--) {
61 st = gst_caps_get_structure (res, i - 1);
62
63 /* Remove range fields */
64 while (!gst_structure_foreach (st,
65 (GstStructureForeachFunc) remove_range_foreach, st));
66 }
67
68 GST_DEBUG ("stripped %" GST_PTR_FORMAT, res);
69
70 /* And append to list without duplicates */
71 while ((st = gst_caps_steal_structure (res, 0))) {
72 /* Skip fake codecs/containers */
73 if (gst_structure_has_name (st, "audio/x-raw") ||
74 gst_structure_has_name (st, "video/x-raw") ||
75 gst_structure_has_name (st, "unknown/unknown")) {
76 gst_structure_free (st);
77 continue;
78 }
79
80 gst_caps_append_structure (rescaps, st);
81 }
82
83 gst_caps_unref (res);
84 }
85
86 static GstCaps *
get_all_caps(GList * elements,GstPadDirection direction)87 get_all_caps (GList * elements, GstPadDirection direction)
88 {
89 GstCaps *res;
90 GList *tmp;
91
92 res = gst_caps_new_empty ();
93
94 for (tmp = elements; tmp; tmp = tmp->next) {
95 GstElementFactory *factory = (GstElementFactory *) tmp->data;
96 const GList *templates;
97 GList *walk;
98
99 templates = gst_element_factory_get_static_pad_templates (factory);
100 for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
101 GstStaticPadTemplate *templ = walk->data;
102 if (templ->direction == direction)
103 clear_caps (gst_static_caps_get (&templ->static_caps), res);
104 }
105 }
106
107 res = gst_caps_normalize (res);
108
109 return res;
110 }
111
112 /**
113 * gst_caps_list_container_formats:
114 * @minrank: The minimum #GstRank
115 *
116 * Returns a #GstCaps corresponding to all the container formats
117 * one can mux to on this system.
118 *
119 * Returns: A #GstCaps. Unref with %gst_caps_unref when done with it.
120 */
121 GstCaps *
gst_caps_list_container_formats(GstRank minrank)122 gst_caps_list_container_formats (GstRank minrank)
123 {
124 GstCaps *res;
125 GList *muxers;
126
127 muxers =
128 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
129 minrank);
130 res = get_all_caps (muxers, GST_PAD_SRC);
131 gst_plugin_feature_list_free (muxers);
132
133 return res;
134 }
135
136 static GstCaps *
gst_caps_list_encoding_formats(GstRank minrank)137 gst_caps_list_encoding_formats (GstRank minrank)
138 {
139 GstCaps *res;
140 GList *encoders;
141
142 encoders =
143 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
144 minrank);
145 res = get_all_caps (encoders, GST_PAD_SRC);
146 gst_plugin_feature_list_free (encoders);
147
148 return res;
149 }
150
151 /**
152 * gst_caps_list_video_encoding_formats:
153 * @minrank: The minimum #GstRank
154 *
155 * Returns a #GstCaps corresponding to all the video or image formats one
156 * can encode to on this system.
157 *
158 * Returns: A #GstCaps. Unref with %gst_caps_unref when done with it.
159 */
160 GstCaps *
gst_caps_list_video_encoding_formats(GstRank minrank)161 gst_caps_list_video_encoding_formats (GstRank minrank)
162 {
163 GstCaps *res;
164 GList *encoders;
165
166 encoders =
167 gst_element_factory_list_get_elements
168 (GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER, minrank);
169 res = get_all_caps (encoders, GST_PAD_SRC);
170 gst_plugin_feature_list_free (encoders);
171
172 return res;
173 }
174
175
176 /**
177 * gst_caps_list_audio_encoding_formats:
178 * @minrank: The minimum #GstRank
179 *
180 * Returns a #GstCaps corresponding to all the audio formats one
181 * can encode to on this system.
182 *
183 * Returns: A #GstCaps. Unref with %gst_caps_unref when done with it.
184 */
185 GstCaps *
gst_caps_list_audio_encoding_formats(GstRank minrank)186 gst_caps_list_audio_encoding_formats (GstRank minrank)
187 {
188 GstCaps *res;
189 GList *encoders;
190
191 encoders =
192 gst_element_factory_list_get_elements
193 (GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER, minrank);
194 res = get_all_caps (encoders, GST_PAD_SRC);
195 gst_plugin_feature_list_free (encoders);
196
197 return res;
198 }
199
200 /**
201 * gst_caps_list_compatible_codecs:
202 * @containerformat: A #GstCaps corresponding to a container format
203 * @codecformats: An optional #GstCaps of codec formats
204 * @muxers: An optional #GList of muxer #GstElementFactory.
205 *
206 * Returns an array of #GstCaps corresponding to the audio/video/text formats
207 * one can encode to and that can be muxed in the provided @containerformat.
208 *
209 * If specified, only the #GstCaps contained in @codecformats will be checked
210 * against, else all compatible audio/video formats will be returned.
211 *
212 * If specified, only the #GstElementFactory contained in @muxers will be checked,
213 * else all available muxers on the system will be checked.
214 *
215 * Returns: A #GstCaps containing all compatible formats. Unref with %gst_caps_unref
216 * when done.
217 */
218 GstCaps *
gst_caps_list_compatible_codecs(const GstCaps * containerformat,GstCaps * codecformats,GList * muxers)219 gst_caps_list_compatible_codecs (const GstCaps * containerformat,
220 GstCaps * codecformats, GList * muxers)
221 {
222 const GList *templates;
223 GstElementFactory *factory;
224 GList *walk;
225 GstCaps *res = NULL;
226 GstCaps *tmpcaps;
227 GList *tmp;
228 gboolean hadmuxers = (muxers != NULL);
229 gboolean hadcodecs = (codecformats != NULL);
230
231 GST_DEBUG ("containerformat: %" GST_PTR_FORMAT, containerformat);
232 GST_DEBUG ("codecformats: %" GST_PTR_FORMAT, codecformats);
233
234 if (!hadmuxers)
235 muxers =
236 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
237 GST_RANK_NONE);
238 if (!hadcodecs)
239 codecformats = gst_caps_list_encoding_formats (GST_RANK_NONE);
240
241 /* Get the highest rank muxer matching containerformat */
242 tmp =
243 gst_element_factory_list_filter (muxers, containerformat, GST_PAD_SRC,
244 TRUE);
245 if (G_UNLIKELY (tmp == NULL))
246 goto beach;
247
248 factory = (GstElementFactory *) tmp->data;
249
250 GST_DEBUG ("Trying with factory %s",
251 gst_element_factory_get_metadata (factory,
252 GST_ELEMENT_METADATA_LONGNAME));
253
254 /* Match all muxer sink pad templates against the available codec formats */
255 templates = gst_element_factory_get_static_pad_templates (factory);
256 gst_plugin_feature_list_free (tmp);
257
258 tmpcaps = gst_caps_new_empty ();
259
260 for (walk = (GList *) templates; walk; walk = walk->next) {
261 GstStaticPadTemplate *templ = walk->data;
262
263 if (templ->direction == GST_PAD_SINK) {
264 GstCaps *templ_caps;
265
266 templ_caps = gst_static_caps_get (&templ->static_caps);
267 gst_caps_append (tmpcaps, gst_caps_copy (templ_caps));
268 }
269 }
270
271 res = gst_caps_intersect (tmpcaps, codecformats);
272 gst_caps_unref (tmpcaps);
273
274 beach:
275 if (!hadmuxers)
276 gst_plugin_feature_list_free (muxers);
277 if (!hadcodecs)
278 gst_caps_unref (codecformats);
279
280 res = gst_caps_normalize (res);
281
282 return res;
283 }
284