~ubuntu-branches/ubuntu/jaunty/ekiga/jaunty-updates

« back to all changes in this revision

Viewing changes to lib/engine/components/gstreamer/gst-videoinput.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ken VanDine
  • Date: 2009-03-17 15:14:12 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090317151412-no6uq0wl8zz2hsw3
Tags: 3.2.0-0ubuntu1
* New upstream release (LP: #341367)
  - Better NAT support in case of Cone NAT
  - Uniformise detection of libnotify; fix compilation with mingw
  - Fix "URL completion combobox shows identical completions"
  - Fix "Assistant loosing values when going backward"
  - Fix GmConf settings when compiled with another package name
  - Fix unregistration of accounts
  - Fix build with --enable-kde
  - Fixed possible crash when retrieving presence information
  - New translations: crh, or
  - Updated translations: as, bg, bn_IN, da, de, el, eu, gl, gu, hi, hu,
    ja, kn, ko, ku, lt, ml, mr, or, pt, ro, ru, ta, te, tr
  - New help translation: en_GB
  - Updated help translation: fr
  - Better NAT support in case of Cone NAT
  - There is now only one H.263 plugin implementing both H.263 and H.263+
  - Allow several ALSA devices to have the same name
  - Added support for the G.722 audio codec: G.722 is a 16 kHz wideband
    audio codec advertised as HD Voice by the famous Polycom. It is a
    great boost in quality and interoperability
  - Added support for the CELT ultral-low delay audio codec: CELT delivers
    high quality audio at 32 kHz or 48 kHz, allowing to transmit music in
    high quality, with low delay and low bitrate
  - Added support for SIP dialog-info notifications: they allow displaying
    notifications of incoming calls in the roster. With software like
    kamailio or Asterisk, it allows being informed of incoming calls
    reaching your colleagues
  - Largely improved LDAP support: the OpenLDAP guys contributed several
    patches to provide state-of-the-art LDAP support in the Ekiga address
    book. The new code even supports authentication
  - Killed the gconf_test_age test, Ekiga can now finally work with
    badly installed GConf schemas
  - Better handling of multiple network interfaces with dynamic addition
    and removal
  - Added settings migration from Ekiga 2.0.x.
  - Other various fixes, cleanups, removal of deprecated symbols etc.
  - New translations: crh, or
  - New help translation: en_GB, eu
  - Updated many translations and help
  - Experimental features:
    * Significant improvements in IPv6 support
    * Gstreamer audio and video capture support near to be finished...
* debian/patches/migrate_2.0_settings.patch:
  - Removed, migration is now upstream
* debian/patches/00_news.patch
  - Removed
* debian/patches/ubuntu_lpi.patch:
  - Modified to work with 3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* Ekiga -- A VoIP and Video-Conferencing application
 
3
 * Copyright (C) 2000-2009 Damien Sandras <dsandras@seconix.com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program 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
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software Foundation,
 
17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 
18
 *
 
19
 *
 
20
 * Ekiga is licensed under the GPL license and as a special exception,
 
21
 * you have permission to link or otherwise combine this program with the
 
22
 * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
 
23
 * without applying the requirements of the GNU GPL to the OPAL, OpenH323
 
24
 * and PWLIB programs, as long as you do follow the requirements of the
 
25
 * GNU GPL for all the rest of the software thus combined.
 
26
 */
 
27
 
 
28
 
 
29
/*
 
30
 *                         gst-videoinput.cpp  -  description
 
31
 *                         ------------------------------------
 
32
 *   begin                : Wed 17 September 2008
 
33
 *   copyright            : (C) 2008 by Julien Puydt
 
34
 *   description          : Gstreamer video input code
 
35
 *
 
36
 */
 
37
 
 
38
#include <glib/gi18n.h>
 
39
 
 
40
#include "gst-videoinput.h"
 
41
 
 
42
#include <gst/interfaces/propertyprobe.h>
 
43
#include <gst/app/gstappsink.h>
 
44
 
 
45
#include <string.h>
 
46
 
 
47
GST::VideoInputManager::VideoInputManager (): pipeline(NULL)
 
48
{
 
49
  detect_devices (); // or we won't recognize the devices we'll be asked to use
 
50
}
 
51
 
 
52
GST::VideoInputManager::~VideoInputManager ()
 
53
{
 
54
  if (pipeline != NULL)
 
55
    g_object_unref (pipeline);
 
56
  pipeline = NULL;
 
57
}
 
58
 
 
59
void
 
60
GST::VideoInputManager::get_devices (std::vector<Ekiga::VideoInputDevice>& devices)
 
61
{
 
62
  detect_devices ();
 
63
 
 
64
  for (std::map<std::pair<std::string, std::string>, std::string>::const_iterator iter
 
65
         = devices_by_name.begin ();
 
66
       iter != devices_by_name.end ();
 
67
       ++iter) {
 
68
 
 
69
    Ekiga::VideoInputDevice device;
 
70
    device.type = "GStreamer";
 
71
    device.source = iter->first.first;
 
72
    device.name = iter->first.second;
 
73
    devices.push_back (device);
 
74
  }
 
75
}
 
76
 
 
77
bool
 
78
GST::VideoInputManager::set_device (const Ekiga::VideoInputDevice& device,
 
79
                                    int channel,
 
80
                                    Ekiga::VideoInputFormat format)
 
81
{
 
82
  bool result = false;
 
83
 
 
84
  if (device.type == "GStreamer"
 
85
      && devices_by_name.find (std::pair<std::string, std::string>(device.source, device.name)) != devices_by_name.end ()) {
 
86
 
 
87
    current_state.opened = false;
 
88
    current_state.width = 320;
 
89
    current_state.height = 240;
 
90
    current_state.fps = 30;
 
91
    current_state.device = device;
 
92
    current_state.format = format;
 
93
    current_state.channel = channel;
 
94
 
 
95
    result = true;
 
96
  }
 
97
 
 
98
  return result;
 
99
}
 
100
 
 
101
bool
 
102
GST::VideoInputManager::open (unsigned width,
 
103
                              unsigned height,
 
104
                              unsigned fps)
 
105
{
 
106
  bool result;
 
107
  gchar* command = NULL;
 
108
  GError* error = NULL;
 
109
  GstState current;
 
110
 
 
111
  command = g_strdup_printf ("%s ! appsink max_buffers=2 drop=true"
 
112
                             " caps=video/x-raw-yuv"
 
113
                             ",format=(fourcc)I420"
 
114
                             ",width=%d,height=%d"
 
115
                             ",framerate=(fraction)%d/1"
 
116
                             " name=ekiga_sink",
 
117
                             devices_by_name[std::pair<std::string,std::string>(current_state.device.source, current_state.device.name)].c_str (),
 
118
                             width, height, fps);
 
119
  g_print ("Pipeline: %s\n", command);
 
120
  pipeline = gst_parse_launch (command, &error);
 
121
 
 
122
  if (error == NULL) {
 
123
 
 
124
    (void)gst_element_set_state (pipeline, GST_STATE_PLAYING);
 
125
 
 
126
    // this will make us wait so we can return the right value...
 
127
    (void)gst_element_get_state (pipeline,
 
128
                                 &current,
 
129
                                 NULL,
 
130
                                 GST_SECOND);
 
131
 
 
132
    if (current != GST_STATE_PLAYING) {
 
133
 
 
134
      gst_element_set_state (pipeline, GST_STATE_NULL);
 
135
      gst_object_unref (GST_OBJECT (pipeline));
 
136
      pipeline = NULL;
 
137
      result = false;
 
138
    } else {
 
139
 
 
140
      Ekiga::VideoInputSettings settings;
 
141
      settings.modifyable = false;
 
142
      device_opened.emit (current_state.device, settings);
 
143
      result = true;
 
144
    }
 
145
  } else {
 
146
 
 
147
    g_error_free (error);
 
148
    result = false;
 
149
  }
 
150
 
 
151
  g_free (command);
 
152
 
 
153
  current_state.opened = result;
 
154
  return result;
 
155
}
 
156
 
 
157
void
 
158
GST::VideoInputManager::close ()
 
159
{
 
160
  if (pipeline != NULL) {
 
161
 
 
162
    device_closed.emit (current_state.device);
 
163
    g_object_unref (pipeline);
 
164
    pipeline = NULL;
 
165
  }
 
166
  current_state.opened = false;
 
167
}
 
168
 
 
169
bool
 
170
GST::VideoInputManager::get_frame_data (char* data)
 
171
{
 
172
  bool result = false;
 
173
  GstBuffer* buffer = NULL;
 
174
  GstElement* sink = NULL;
 
175
 
 
176
  g_return_val_if_fail (GST_IS_BIN (pipeline), false);
 
177
 
 
178
  sink = gst_bin_get_by_name (GST_BIN (pipeline), "ekiga_sink");
 
179
 
 
180
  if (sink != NULL) {
 
181
 
 
182
    buffer = gst_app_sink_pull_buffer (GST_APP_SINK (sink));
 
183
 
 
184
    if (buffer != NULL) {
 
185
 
 
186
      uint size = MIN (GST_BUFFER_SIZE (buffer),
 
187
                       current_state.width * current_state.height * 3 / 2);
 
188
      memcpy (data, GST_BUFFER_DATA (buffer), size);
 
189
      result = true;
 
190
      gst_buffer_unref (buffer);
 
191
    }
 
192
    g_object_unref (sink);
 
193
  }
 
194
 
 
195
  return result;
 
196
}
 
197
 
 
198
bool
 
199
GST::VideoInputManager::has_device (const std::string& source,
 
200
                                    const std::string& device_name,
 
201
                                    G_GNUC_UNUSED unsigned capabilities,
 
202
                                    G_GNUC_UNUSED Ekiga::VideoInputDevice& device)
 
203
{
 
204
  return (devices_by_name.find (std::pair<std::string,std::string> (source, device_name)) != devices_by_name.end ());
 
205
}
 
206
 
 
207
void
 
208
GST::VideoInputManager::detect_devices ()
 
209
{
 
210
  devices_by_name.clear ();
 
211
  detect_videotestsrc_devices ();
 
212
  detect_v4l2src_devices ();
 
213
  detect_dv1394src_devices ();
 
214
  detect_crazy_devices ();
 
215
}
 
216
 
 
217
void
 
218
GST::VideoInputManager::detect_videotestsrc_devices ()
 
219
{
 
220
  GstElement* elt = NULL;
 
221
 
 
222
  elt = gst_element_factory_make ("videotestsrc", "videotestsrcpresencetest");
 
223
 
 
224
  if (elt != NULL) {
 
225
 
 
226
    devices_by_name[std::pair<std::string,std::string>(_("Video test"),_("Video test"))] = "videotestsrc";
 
227
    gst_object_unref (GST_OBJECT (elt));
 
228
  }
 
229
}
 
230
 
 
231
void
 
232
GST::VideoInputManager::detect_v4l2src_devices ()
 
233
{
 
234
  bool problem = false;
 
235
  GstElement* elt = NULL;
 
236
 
 
237
  elt = gst_element_factory_make ("videoscale", "videoscalepresencetest");
 
238
  if (elt == NULL)
 
239
    problem = true;
 
240
  else
 
241
    gst_object_unref (elt);
 
242
 
 
243
  elt = gst_element_factory_make ("ffmpegcolorspace",
 
244
                                  "ffmpegcolorspacepresencetest");
 
245
  if (elt == NULL)
 
246
    problem = true;
 
247
  else
 
248
    gst_object_unref (elt);
 
249
 
 
250
  elt = gst_element_factory_make ("v4l2src", "v4l2srcpresencetest");
 
251
 
 
252
  if (elt != NULL && problem == false) {
 
253
 
 
254
    GstPropertyProbe* probe = NULL;
 
255
    const GParamSpec* pspec = NULL;
 
256
    GValueArray* array = NULL;
 
257
 
 
258
    probe = GST_PROPERTY_PROBE (elt);
 
259
    pspec = gst_property_probe_get_property (probe, "device");
 
260
    array = gst_property_probe_probe_and_get_values (probe, pspec);
 
261
 
 
262
    if (array != NULL) {
 
263
 
 
264
      for (guint index = 0; index < array->n_values; index++) {
 
265
 
 
266
        GValue* device = NULL;
 
267
        gchar* name = NULL;
 
268
        gchar* descr = NULL;
 
269
 
 
270
        device = g_value_array_get_nth (array, index);
 
271
        g_object_set_property (G_OBJECT (elt), "device", device);
 
272
 
 
273
        g_object_get (G_OBJECT (elt), "device-name", &name, NULL);
 
274
        descr = g_strdup_printf ("v4l2src device=%s"
 
275
                                 " ! videoscale ! ffmpegcolorspace",
 
276
                                 g_value_get_string (device));
 
277
        devices_by_name[std::pair<std::string,std::string>("V4L2",name)] = descr;
 
278
        g_free (descr);
 
279
      }
 
280
 
 
281
      g_value_array_free (array);
 
282
      gst_element_set_state (elt, GST_STATE_NULL);
 
283
    }
 
284
  }
 
285
  if (elt != NULL)
 
286
    gst_object_unref (GST_OBJECT (elt));
 
287
}
 
288
 
 
289
void
 
290
GST::VideoInputManager::detect_dv1394src_devices ()
 
291
{
 
292
  bool problem = false;
 
293
  GstElement* elt = NULL;
 
294
 
 
295
  elt = gst_element_factory_make ("videoscale", "videoscalepresencetest");
 
296
  if (elt == NULL)
 
297
    problem = true;
 
298
  else
 
299
    gst_object_unref (elt);
 
300
 
 
301
  elt = gst_element_factory_make ("decodebin", "decodebinpresencetest");
 
302
  if (elt == NULL)
 
303
    problem = true;
 
304
  else
 
305
    gst_object_unref (elt);
 
306
 
 
307
  elt = gst_element_factory_make ("ffmpegcolorspace",
 
308
                                  "ffmpegcolorspacepresencetest");
 
309
  if (elt == NULL)
 
310
    problem = true;
 
311
  else
 
312
    gst_object_unref (elt);
 
313
 
 
314
  elt = gst_element_factory_make ("dv1394src", "dv1394srcpresencetest");
 
315
 
 
316
  if (elt != NULL && problem == false) {
 
317
 
 
318
    GstPropertyProbe* probe = NULL;
 
319
    const GParamSpec* pspec = NULL;
 
320
    GValueArray* array = NULL;
 
321
 
 
322
    probe = GST_PROPERTY_PROBE (elt);
 
323
    pspec = gst_property_probe_get_property (probe, "guid");
 
324
    array = gst_property_probe_probe_and_get_values (probe, pspec);
 
325
 
 
326
    if (array != NULL) {
 
327
 
 
328
      for (guint index = 0; index < array->n_values; index++) {
 
329
 
 
330
        GValue* guid = NULL;
 
331
        gchar* name = NULL;
 
332
        gchar* descr = NULL;
 
333
        guid = g_value_array_get_nth (array, index);
 
334
        g_object_set_property (G_OBJECT (elt), "guid", guid);
 
335
 
 
336
        g_object_get (G_OBJECT (elt), "device-name", &name, NULL);
 
337
        descr = g_strdup_printf ("dv1394src guid=%Ld"
 
338
                                 " ! decodebin"
 
339
                                 " ! videoscale"
 
340
                                 " ! ffmpegcolorspace",
 
341
                                 g_value_get_uint64 (guid));
 
342
        devices_by_name[std::pair<std::string,std::string>("DV",name)] = descr;
 
343
        g_free (descr);
 
344
      }
 
345
 
 
346
      g_value_array_free (array);
 
347
      gst_element_set_state (elt, GST_STATE_NULL);
 
348
    }
 
349
  }
 
350
  if (elt != NULL)
 
351
    gst_object_unref (GST_OBJECT (elt));
 
352
}
 
353
 
 
354
void
 
355
GST::VideoInputManager::detect_crazy_devices ()
 
356
{
 
357
  GstElement* goom = NULL;
 
358
  GstElement* audiotest = NULL;
 
359
  GstElement* ffmpeg = NULL;
 
360
  GstElement* scale = NULL;
 
361
  GstElement* ximage = NULL;
 
362
 
 
363
  goom = gst_element_factory_make ("goom", "goompresencetest");
 
364
  audiotest = gst_element_factory_make ("audiotestsrc", "audiotestsrcpresencetest");
 
365
  ffmpeg = gst_element_factory_make ("ffmpegcolorspace", "ffmpegcolorspacepresencetest");
 
366
  scale = gst_element_factory_make ("videoscale", "videoscalepresencetest");
 
367
  ximage = gst_element_factory_make ("ximagesrc", "ximagesrcpresencetest");
 
368
 
 
369
  if (goom != NULL && audiotest != NULL && ffmpeg != NULL)
 
370
    devices_by_name[std::pair<std::string,std::string>(_("Crazy"), "Goom")] = "audiotestsrc ! goom ! ffmpegcolorspace";
 
371
 
 
372
  if (ximage != NULL && ffmpeg != NULL) {
 
373
 
 
374
    /* Translators: "Screencast" means the video input device will be your screen -- the other end will see your desktop */
 
375
    devices_by_name[std::pair<std::string,std::string>(_("Crazy"),_("Screencast"))] = "ximagesrc ! videoscale ! ffmpegcolorspace";
 
376
  }
 
377
 
 
378
  if (goom != NULL)
 
379
    gst_object_unref (goom);
 
380
  if (audiotest != NULL)
 
381
    gst_object_unref (audiotest);
 
382
  if (scale != NULL)
 
383
    gst_object_unref (scale);
 
384
  if (ffmpeg != NULL)
 
385
    gst_object_unref (ffmpeg);
 
386
  if (ximage != NULL)
 
387
    gst_object_unref (ximage);
 
388
}