]> git.0d.be Git - empathy.git/blob - src/empathy-video-src.c
Update Simplified Chinese help translation.
[empathy.git] / src / empathy-video-src.c
1 /*
2  * empathy-gst-video-src.c - Source for EmpathyGstVideoSrc
3  * Copyright (C) 2008 Collabora Ltd.
4  * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 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  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <gst/interfaces/colorbalance.h>
26
27 #define DEBUG_FLAG EMPATHY_DEBUG_VOIP
28 #include <libempathy/empathy-debug.h>
29
30 #include "empathy-video-src.h"
31
32 G_DEFINE_TYPE(EmpathyGstVideoSrc, empathy_video_src, GST_TYPE_BIN)
33
34 /* Keep in sync with EmpathyGstVideoSrcChannel */
35 static const gchar *channel_names[NR_EMPATHY_GST_VIDEO_SRC_CHANNELS] = {
36   "contrast", "brightness", "gamma" };
37
38 /* signal enum */
39 #if 0
40 enum
41 {
42     LAST_SIGNAL
43 };
44
45 static guint signals[LAST_SIGNAL] = {0};
46 #endif
47
48 /* private structure */
49 typedef struct _EmpathyGstVideoSrcPrivate EmpathyGstVideoSrcPrivate;
50
51 struct _EmpathyGstVideoSrcPrivate
52 {
53   gboolean dispose_has_run;
54   GstElement *src;
55   /* Element implementing a ColorBalance interface */
56   GstElement *balance;
57 };
58
59 #define EMPATHY_GST_VIDEO_SRC_GET_PRIVATE(o) \
60   (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_VIDEO_SRC, \
61     EmpathyGstVideoSrcPrivate))
62 /**
63  * empathy_gst_add_to_bin - create a new gst element, add to bin and link it.
64  * @bin - bin to add the new element to.
65  * @src - src element for the new element (may be NULL).
66  * @name - name of the factory for the new element
67  *
68  * Returns: The newly created element ot %NULL on failure
69  */
70 static GstElement *
71 empathy_gst_add_to_bin (GstBin *bin,
72   GstElement *src,
73   const gchar *factoryname)
74 {
75   GstElement *ret;
76
77   if ((ret = gst_element_factory_make (factoryname, NULL)) == NULL)
78   {
79     g_message ("Element factory \"%s\" not found.", factoryname);
80     goto error;
81   }
82
83   if (!gst_bin_add (bin, ret))
84   {
85     g_warning ("Couldn't add \"%s\" to bin.", factoryname);
86     goto error;
87   }
88
89   /* do not link if src == NULL, just exit here */
90   if (src == NULL)
91     return ret;
92
93   if (!gst_element_link (src, ret))
94   {
95     g_warning ("Failed to link \"%s\".", factoryname);
96     gst_bin_remove (bin, ret);
97     goto error;
98   }
99
100   return ret;
101
102 error:
103   if (ret != NULL)
104     gst_object_unref (ret);
105   return NULL;
106 }
107
108
109 static void
110 empathy_video_src_init (EmpathyGstVideoSrc *obj)
111 {
112   EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (obj);
113   GstElement *element, *element_back;
114   GstPad *ghost, *src;
115   GstCaps *caps;
116   gchar *str;
117
118   /* allocate caps here, so we can update it by optional elements */
119   caps = gst_caps_new_simple ("video/x-raw-yuv",
120     "width", G_TYPE_INT, 320,
121     "height", G_TYPE_INT, 240,
122     NULL);
123
124   /* allocate any data required by the object here */
125   if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
126       NULL, "gconfvideosrc")) == NULL)
127     g_error ("Couldn't add \"gconfvideosrc\" (gst-plugins-good missing?)");
128
129   /* we need to save our source to priv->src */
130   priv->src = element;
131
132   /* videomaxrate is optional as it's part of gst-plugins-bad. So don't
133    * fail if it doesn't exist. */
134   element_back = element;
135   if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
136       element, "videomaxrate")) == NULL)
137     {
138       g_message ("Couldn't add \"videomaxrate\" (gst-plugins-bad missing?)");
139       element = element_back;
140     }
141   else
142     {
143       gst_caps_set_simple (caps,
144         "framerate", GST_TYPE_FRACTION, 15, 1,
145         NULL);
146     }
147
148   str = gst_caps_to_string (caps);
149   DEBUG ("Current video src caps are : %s", str);
150   g_free (str);
151
152   if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
153       element, "ffmpegcolorspace")) == NULL)
154     g_error ("Failed to add \"ffmpegcolorspace\" (gst-plugins-base missing?)");
155
156   if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
157       element, "videoscale")) == NULL)
158     g_error ("Failed to add \"videoscale\", (gst-plugins-base missing?)");
159
160   if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
161       element, "capsfilter")) == NULL)
162     g_error (
163       "Failed to add \"capsfilter\" (gstreamer core elements missing?)");
164
165   g_object_set (G_OBJECT (element), "caps", caps, NULL);
166
167
168   /* optionally add postproc_tmpnoise to improve the performance of encoders */
169   element_back = element;
170   if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
171       element, "postproc_tmpnoise")) == NULL)
172     {
173       g_message ("Failed to add \"postproc_tmpnoise\" (gst-ffmpeg missing?)");
174       element = element_back;
175     }
176
177   src = gst_element_get_static_pad (element, "src");
178   g_assert (src != NULL);
179
180   ghost = gst_ghost_pad_new ("src", src);
181   if (ghost == NULL)
182     g_error ("Unable to create ghost pad for the videosrc");
183
184   if (!gst_element_add_pad (GST_ELEMENT (obj), ghost))
185     g_error ("pad with the same name already existed or "
186             "the pad already had another parent.");
187
188   gst_object_unref (G_OBJECT (src));
189 }
190
191 static void empathy_video_src_dispose (GObject *object);
192 static void empathy_video_src_finalize (GObject *object);
193
194 static void
195 empathy_video_src_class_init (EmpathyGstVideoSrcClass *empathy_video_src_class)
196 {
197   GObjectClass *object_class = G_OBJECT_CLASS (empathy_video_src_class);
198
199   g_type_class_add_private (empathy_video_src_class,
200     sizeof (EmpathyGstVideoSrcPrivate));
201
202   object_class->dispose = empathy_video_src_dispose;
203   object_class->finalize = empathy_video_src_finalize;
204 }
205
206 void
207 empathy_video_src_dispose (GObject *object)
208 {
209   EmpathyGstVideoSrc *self = EMPATHY_GST_VIDEO_SRC (object);
210   EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (self);
211
212   if (priv->dispose_has_run)
213     return;
214
215   priv->dispose_has_run = TRUE;
216
217   /* release any references held by the object here */
218
219   if (G_OBJECT_CLASS (empathy_video_src_parent_class)->dispose)
220     G_OBJECT_CLASS (empathy_video_src_parent_class)->dispose (object);
221 }
222
223 void
224 empathy_video_src_finalize (GObject *object)
225 {
226   //EmpathyGstVideoSrc *self = EMPATHY_GST_VIDEO_SRC (object);
227   //EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (self);
228
229   /* free any data held directly by the object here */
230
231   G_OBJECT_CLASS (empathy_video_src_parent_class)->finalize (object);
232 }
233
234 GstElement *
235 empathy_video_src_new (void)
236 {
237   static gboolean registered = FALSE;
238
239   if (!registered) {
240     if (!gst_element_register (NULL, "empathyvideosrc",
241             GST_RANK_NONE, EMPATHY_TYPE_GST_VIDEO_SRC))
242       return NULL;
243     registered = TRUE;
244   }
245   return gst_element_factory_make ("empathyvideosrc", NULL);
246 }
247
248 void
249 empathy_video_src_set_channel (GstElement *src,
250   EmpathyGstVideoSrcChannel channel, guint percent)
251 {
252   GstElement *color;
253   GstColorBalance *balance;
254   const GList *channels;
255   GList *l;
256
257   /* Find something supporting GstColorBalance */
258   color = gst_bin_get_by_interface (GST_BIN (src), GST_TYPE_COLOR_BALANCE);
259
260   if (color == NULL)
261     return;
262
263   balance = GST_COLOR_BALANCE (color);
264
265   channels = gst_color_balance_list_channels (balance);
266
267   for (l = (GList *) channels; l != NULL; l = g_list_next (l))
268     {
269       GstColorBalanceChannel *c = GST_COLOR_BALANCE_CHANNEL (l->data);
270
271       if (g_ascii_strcasecmp (c->label, channel_names[channel]) == 0)
272         {
273           gst_color_balance_set_value (balance, c,
274             ((c->max_value - c->min_value) * percent)/100
275               + c->min_value);
276           break;
277         }
278     }
279
280   g_object_unref (color);
281 }
282
283 guint
284 empathy_video_src_get_channel (GstElement *src,
285   EmpathyGstVideoSrcChannel channel)
286 {
287   GstElement *color;
288   GstColorBalance *balance;
289   const GList *channels;
290   GList *l;
291   guint percent = 0;
292
293   /* Find something supporting GstColorBalance */
294   color = gst_bin_get_by_interface (GST_BIN (src), GST_TYPE_COLOR_BALANCE);
295
296   if (color == NULL)
297     return percent;
298
299   balance = GST_COLOR_BALANCE (color);
300
301   channels = gst_color_balance_list_channels (balance);
302
303   for (l = (GList *) channels; l != NULL; l = g_list_next (l))
304     {
305       GstColorBalanceChannel *c = GST_COLOR_BALANCE_CHANNEL (l->data);
306
307       if (g_ascii_strcasecmp (c->label, channel_names[channel]) == 0)
308         {
309           percent =
310             ((gst_color_balance_get_value (balance, c)
311                 - c->min_value) * 100) /
312               (c->max_value - c->min_value);
313
314           break;
315         }
316     }
317
318   g_object_unref (color);
319
320   return percent;
321 }
322
323
324 guint
325 empathy_video_src_get_supported_channels (GstElement *src)
326 {
327   GstElement *color;
328   GstColorBalance *balance;
329   const GList *channels;
330   GList *l;
331   guint result = 0;
332
333   /* Find something supporting GstColorBalance */
334   color = gst_bin_get_by_interface (GST_BIN (src), GST_TYPE_COLOR_BALANCE);
335
336   if (color == NULL)
337     goto out;
338
339   balance = GST_COLOR_BALANCE (color);
340
341   channels = gst_color_balance_list_channels (balance);
342
343   for (l = (GList *) channels; l != NULL; l = g_list_next (l))
344     {
345       GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (l->data);
346       int i;
347
348       for (i = 0; i < NR_EMPATHY_GST_VIDEO_SRC_CHANNELS; i++)
349         {
350           if (g_ascii_strcasecmp (channel->label, channel_names[i]) == 0)
351             {
352               result |= (1 << i);
353               break;
354             }
355         }
356     }
357
358   g_object_unref (color);
359
360 out:
361   return result;
362 }
363