2
/* Ekiga -- A VoIP and Video-Conferencing application
3
* Copyright (C) 2000-2009 Damien Sandras <dsandras@seconix.com>
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.
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.
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.
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.
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
38
#include <glib/gi18n.h>
40
#include "gst-videoinput.h"
42
#include <gst/interfaces/propertyprobe.h>
43
#include <gst/app/gstappsink.h>
47
GST::VideoInputManager::VideoInputManager (): pipeline(NULL)
49
detect_devices (); // or we won't recognize the devices we'll be asked to use
52
GST::VideoInputManager::~VideoInputManager ()
55
g_object_unref (pipeline);
60
GST::VideoInputManager::get_devices (std::vector<Ekiga::VideoInputDevice>& devices)
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 ();
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);
78
GST::VideoInputManager::set_device (const Ekiga::VideoInputDevice& device,
80
Ekiga::VideoInputFormat format)
84
if (device.type == "GStreamer"
85
&& devices_by_name.find (std::pair<std::string, std::string>(device.source, device.name)) != devices_by_name.end ()) {
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;
102
GST::VideoInputManager::open (unsigned width,
107
gchar* command = NULL;
108
GError* error = NULL;
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"
117
devices_by_name[std::pair<std::string,std::string>(current_state.device.source, current_state.device.name)].c_str (),
119
g_print ("Pipeline: %s\n", command);
120
pipeline = gst_parse_launch (command, &error);
124
(void)gst_element_set_state (pipeline, GST_STATE_PLAYING);
126
// this will make us wait so we can return the right value...
127
(void)gst_element_get_state (pipeline,
132
if (current != GST_STATE_PLAYING) {
134
gst_element_set_state (pipeline, GST_STATE_NULL);
135
gst_object_unref (GST_OBJECT (pipeline));
140
Ekiga::VideoInputSettings settings;
141
settings.modifyable = false;
142
device_opened.emit (current_state.device, settings);
147
g_error_free (error);
153
current_state.opened = result;
158
GST::VideoInputManager::close ()
160
if (pipeline != NULL) {
162
device_closed.emit (current_state.device);
163
g_object_unref (pipeline);
166
current_state.opened = false;
170
GST::VideoInputManager::get_frame_data (char* data)
173
GstBuffer* buffer = NULL;
174
GstElement* sink = NULL;
176
g_return_val_if_fail (GST_IS_BIN (pipeline), false);
178
sink = gst_bin_get_by_name (GST_BIN (pipeline), "ekiga_sink");
182
buffer = gst_app_sink_pull_buffer (GST_APP_SINK (sink));
184
if (buffer != NULL) {
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);
190
gst_buffer_unref (buffer);
192
g_object_unref (sink);
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)
204
return (devices_by_name.find (std::pair<std::string,std::string> (source, device_name)) != devices_by_name.end ());
208
GST::VideoInputManager::detect_devices ()
210
devices_by_name.clear ();
211
detect_videotestsrc_devices ();
212
detect_v4l2src_devices ();
213
detect_dv1394src_devices ();
214
detect_crazy_devices ();
218
GST::VideoInputManager::detect_videotestsrc_devices ()
220
GstElement* elt = NULL;
222
elt = gst_element_factory_make ("videotestsrc", "videotestsrcpresencetest");
226
devices_by_name[std::pair<std::string,std::string>(_("Video test"),_("Video test"))] = "videotestsrc";
227
gst_object_unref (GST_OBJECT (elt));
232
GST::VideoInputManager::detect_v4l2src_devices ()
234
bool problem = false;
235
GstElement* elt = NULL;
237
elt = gst_element_factory_make ("videoscale", "videoscalepresencetest");
241
gst_object_unref (elt);
243
elt = gst_element_factory_make ("ffmpegcolorspace",
244
"ffmpegcolorspacepresencetest");
248
gst_object_unref (elt);
250
elt = gst_element_factory_make ("v4l2src", "v4l2srcpresencetest");
252
if (elt != NULL && problem == false) {
254
GstPropertyProbe* probe = NULL;
255
const GParamSpec* pspec = NULL;
256
GValueArray* array = NULL;
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);
264
for (guint index = 0; index < array->n_values; index++) {
266
GValue* device = NULL;
270
device = g_value_array_get_nth (array, index);
271
g_object_set_property (G_OBJECT (elt), "device", device);
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;
281
g_value_array_free (array);
282
gst_element_set_state (elt, GST_STATE_NULL);
286
gst_object_unref (GST_OBJECT (elt));
290
GST::VideoInputManager::detect_dv1394src_devices ()
292
bool problem = false;
293
GstElement* elt = NULL;
295
elt = gst_element_factory_make ("videoscale", "videoscalepresencetest");
299
gst_object_unref (elt);
301
elt = gst_element_factory_make ("decodebin", "decodebinpresencetest");
305
gst_object_unref (elt);
307
elt = gst_element_factory_make ("ffmpegcolorspace",
308
"ffmpegcolorspacepresencetest");
312
gst_object_unref (elt);
314
elt = gst_element_factory_make ("dv1394src", "dv1394srcpresencetest");
316
if (elt != NULL && problem == false) {
318
GstPropertyProbe* probe = NULL;
319
const GParamSpec* pspec = NULL;
320
GValueArray* array = NULL;
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);
328
for (guint index = 0; index < array->n_values; index++) {
333
guid = g_value_array_get_nth (array, index);
334
g_object_set_property (G_OBJECT (elt), "guid", guid);
336
g_object_get (G_OBJECT (elt), "device-name", &name, NULL);
337
descr = g_strdup_printf ("dv1394src guid=%Ld"
340
" ! ffmpegcolorspace",
341
g_value_get_uint64 (guid));
342
devices_by_name[std::pair<std::string,std::string>("DV",name)] = descr;
346
g_value_array_free (array);
347
gst_element_set_state (elt, GST_STATE_NULL);
351
gst_object_unref (GST_OBJECT (elt));
355
GST::VideoInputManager::detect_crazy_devices ()
357
GstElement* goom = NULL;
358
GstElement* audiotest = NULL;
359
GstElement* ffmpeg = NULL;
360
GstElement* scale = NULL;
361
GstElement* ximage = NULL;
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");
369
if (goom != NULL && audiotest != NULL && ffmpeg != NULL)
370
devices_by_name[std::pair<std::string,std::string>(_("Crazy"), "Goom")] = "audiotestsrc ! goom ! ffmpegcolorspace";
372
if (ximage != NULL && ffmpeg != NULL) {
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";
379
gst_object_unref (goom);
380
if (audiotest != NULL)
381
gst_object_unref (audiotest);
383
gst_object_unref (scale);
385
gst_object_unref (ffmpeg);
387
gst_object_unref (ximage);