blob: 1f620654321f2869e48d6f0a73dfd6b94e3169fe [file] [log] [blame]
Olivier Naudanb28313f2012-04-16 08:10:18 -04001/* GStreamer
2 * Copyright 2010 ST-Ericsson SA
3 * @author: Benjamin Gaignard <benjamin.gaignard@stericsson.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20/*
21 * test autovideoconvert:
22 * if rgb2bayer is present
23 * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-rgb,width=100,height=100,framerate=10/1" ! autovideoconvert ! "video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1" ! fakesink -v
24 * if bayer2rgb is present
25 * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1" ! autovideoconvert ! "video/x-raw-rgb,width=100,height=100,framerate=10/1" ! fakesink -v
26 * test with ffmpegvideoconvert
27 * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-rgb,bpp=32,width=100,height=100,framerate=10/1" ! autovideoconvert ! "video/x-raw-rgb,bpp=16,width=100,height=100,framerate=10/1" ! fakesink -v
28 */
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <string.h>
34
35#include "gstautovideoconvert.h"
36
37GST_DEBUG_CATEGORY (autovideoconvert_debug);
38#define GST_CAT_DEFAULT (autovideoconvert_debug)
39
40GStaticMutex factories_mutex = G_STATIC_MUTEX_INIT;
41guint32 factories_cookie = 0; /* Cookie from last time when factories was updated */
42GList *factories = NULL; /* factories we can use for selecting elements */
43
44/* element factory information */
45static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
46 GST_PAD_SINK,
47 GST_PAD_ALWAYS,
48 GST_STATIC_CAPS_ANY);
49
50static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
51 GST_PAD_SRC,
52 GST_PAD_ALWAYS,
53 GST_STATIC_CAPS_ANY);
54
55
56static GstStateChangeReturn gst_auto_video_convert_change_state (GstElement *
57 element, GstStateChange transition);
58
59void gst_auto_video_convert_update_factory_list (GstAutoVideoConvert *
60 autovideoconvert);
61
62static gboolean
63gst_auto_video_convert_element_filter (GstPluginFeature * feature,
64 GstAutoVideoConvert * autovideoconvert)
65{
66 const gchar *klass;
67
68 /* we only care about element factories */
69 if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature)))
70 return FALSE;
71
72 klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY_CAST (feature));
73 /* only select color space converter */
74 if (strstr (klass, "Filter") &&
75 strstr (klass, "Converter") && strstr (klass, "Video")) {
76 GST_DEBUG_OBJECT (autovideoconvert,
77 "gst_auto_video_convert_element_filter found %s\n",
78 gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (feature)));
79 return TRUE;
80 }
81 return FALSE;
82}
83
84
85static GList *
86gst_auto_video_convert_create_factory_list (GstAutoVideoConvert *
87 autovideoconvert)
88{
89 GList *result = NULL;
90
91 /* get the feature list using the filter */
92 result = gst_registry_feature_filter (gst_registry_get (),
93 (GstPluginFeatureFilter) gst_auto_video_convert_element_filter,
94 FALSE, autovideoconvert);
95
96 /* sort on rank and name */
97 result = g_list_sort (result, gst_plugin_feature_rank_compare_func);
98
99 return result;
100}
101
102void
103gst_auto_video_convert_update_factory_list (GstAutoVideoConvert *
104 autovideoconvert)
105{
106 /* use a static mutex to protect factories list and factories cookie */
107 g_static_mutex_lock (&factories_mutex);
108
109 /* test if a factories list already exist or not */
110 if (!factories) {
111 /* no factories list create it */
112 factories_cookie =
113 gst_registry_get_feature_list_cookie (gst_registry_get ());
114 factories = gst_auto_video_convert_create_factory_list (autovideoconvert);
115 } else {
116 /* a factories list exist but is it up to date? */
117 if (factories_cookie !=
118 gst_registry_get_feature_list_cookie (gst_registry_get ())) {
119 /* we need to update the factories list */
120 /* first free the old one */
121 gst_plugin_feature_list_free (factories);
122 /* then create an updated one */
123 factories_cookie =
124 gst_registry_get_feature_list_cookie (gst_registry_get ());
125 factories = gst_auto_video_convert_create_factory_list (autovideoconvert);
126 }
127 }
128
129 g_static_mutex_unlock (&factories_mutex);
130}
131
132G_DEFINE_TYPE (GstAutoVideoConvert, gst_auto_video_convert, GST_TYPE_BIN);
133
134static void
135gst_auto_video_convert_class_init (GstAutoVideoConvertClass * klass)
136{
137 GstElementClass *gstelement_class = (GstElementClass *) klass;
138
139 GST_DEBUG_CATEGORY_INIT (autovideoconvert_debug, "autovideoconvert", 0,
140 "Auto color space converter");
141
142 gst_element_class_add_pad_template (gstelement_class,
143 gst_static_pad_template_get (&srctemplate));
144 gst_element_class_add_pad_template (gstelement_class,
145 gst_static_pad_template_get (&sinktemplate));
146
147 gst_element_class_set_details_simple (gstelement_class,
148 "Select color space convertor based on caps", "Generic/Bin",
149 "Selects the right color space convertor based on the caps",
150 "Benjamin Gaignard <benjamin.gaignard@stericsson.com>");
151
152 gstelement_class->change_state =
153 GST_DEBUG_FUNCPTR (gst_auto_video_convert_change_state);
154
155}
156
157static gboolean
158gst_auto_video_convert_add_autoconvert (GstAutoVideoConvert * autovideoconvert)
159{
160 GstPad *pad;
161
162 if (autovideoconvert->autoconvert)
163 return TRUE;
164
165 autovideoconvert->autoconvert =
166 gst_element_factory_make ("autoconvert", "autoconvertchild");
167 if (!autovideoconvert->autoconvert) {
168 GST_ERROR_OBJECT (autovideoconvert,
169 "Could not create autoconvert instance");
170 return FALSE;
171 }
172
173 /* first add autoconvert in bin */
174 gst_bin_add (GST_BIN (autovideoconvert),
175 gst_object_ref (autovideoconvert->autoconvert));
176
177 /* get sinkpad and link it to ghost sink pad */
178 pad = gst_element_get_static_pad (autovideoconvert->autoconvert, "sink");
179 gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autovideoconvert->sinkpad),
180 pad);
181 gst_object_unref (pad);
182
183 /* get srcpad and link it to ghost src pad */
184 pad = gst_element_get_static_pad (autovideoconvert->autoconvert, "src");
185 gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autovideoconvert->srcpad), pad);
186 gst_object_unref (pad);
187
188 return TRUE;
189}
190
191static void
192gst_auto_video_convert_remove_autoconvert (GstAutoVideoConvert *
193 autovideoconvert)
194{
195 if (!autovideoconvert->autoconvert)
196 return;
197
198 gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autovideoconvert->srcpad),
199 NULL);
200 gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autovideoconvert->sinkpad),
201 NULL);
202
203 gst_bin_remove (GST_BIN (autovideoconvert), autovideoconvert->autoconvert);
204 gst_object_unref (autovideoconvert->autoconvert);
205 autovideoconvert->autoconvert = NULL;
206}
207
208static void
209gst_auto_video_convert_init (GstAutoVideoConvert * autovideoconvert)
210{
211 GstPadTemplate *pad_tmpl;
212
213 /* get sink pad template */
214 pad_tmpl = gst_static_pad_template_get (&sinktemplate);
215 autovideoconvert->sinkpad =
216 gst_ghost_pad_new_no_target_from_template ("sink", pad_tmpl);
217 /* add sink ghost pad */
218 gst_element_add_pad (GST_ELEMENT (autovideoconvert),
219 autovideoconvert->sinkpad);
220 gst_object_unref (pad_tmpl);
221
222 /* get src pad template */
223 pad_tmpl = gst_static_pad_template_get (&srctemplate);
224 autovideoconvert->srcpad =
225 gst_ghost_pad_new_no_target_from_template ("src", pad_tmpl);
226 /* add src ghost pad */
227 gst_element_add_pad (GST_ELEMENT (autovideoconvert),
228 autovideoconvert->srcpad);
229 gst_object_unref (pad_tmpl);
230
231 return;
232}
233
234static GstStateChangeReturn
235gst_auto_video_convert_change_state (GstElement * element,
236 GstStateChange transition)
237{
238 GstAutoVideoConvert *autovideoconvert = GST_AUTO_VIDEO_CONVERT (element);
239 GstStateChangeReturn ret;
240
241 switch (transition) {
242 case GST_STATE_CHANGE_NULL_TO_READY:
243 {
244 /* create and add autoconvert in bin */
245 if (!gst_auto_video_convert_add_autoconvert (autovideoconvert)) {
246 ret = GST_STATE_CHANGE_FAILURE;
247 return ret;
248 }
249 /* get an updated list of factories */
250 gst_auto_video_convert_update_factory_list (autovideoconvert);
251 GST_DEBUG_OBJECT (autovideoconvert, "set factories list");
252 /* give factory list to autoconvert */
253 g_object_set (GST_ELEMENT (autovideoconvert->autoconvert), "factories",
254 factories, NULL);
255 break;
256 }
257 default:
258 break;
259 }
260
261 ret = GST_ELEMENT_CLASS (gst_auto_video_convert_parent_class)->change_state
262 (element, transition);
263 if (ret == GST_STATE_CHANGE_FAILURE)
264 return ret;
265
266 switch (transition) {
267 case GST_STATE_CHANGE_READY_TO_NULL:
268 {
269 gst_auto_video_convert_remove_autoconvert (autovideoconvert);
270 break;
271 }
272 default:
273 break;
274 }
275
276 return ret;
277}