[ekiga/ds-clutter: 6/8] Clutter GST: Added a new clutter gst videooutput.



commit d7c97cf56fb832be926db651ab779cbf01501f5b
Author: Damien Sandras <dsandras beip be>
Date:   Sun Dec 29 14:35:04 2013 +0100

    Clutter GST: Added a new clutter gst videooutput.
    
    This is using the GStreamer and Clutter APIs to display frames.
    
    The new videooutput designs requires the videooutput to display frames
    onto a surface whatever its size, position and states are. That's
    implemented by the current code which will output frames on a
    ClutterActor. The part of the GUI managing the ClutterActor is
    responsible to size it appropriately following the natural size of the
    video.

 configure.ac                                       |   17 ++-
 lib/Makefile.am                                    |   17 ++-
 .../videooutput-main-clutter-gst.cpp               |   67 +++++
 .../videooutput-main-clutter-gst.h                 |   47 ++++
 .../videooutput-manager-clutter-gst.cpp            |  271 ++++++++++++++++++++
 .../videooutput-manager-clutter-gst.h              |  104 ++++++++
 6 files changed, 521 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d5c7e08..7cd4a00 100644
--- a/configure.ac
+++ b/configure.ac
@@ -170,6 +170,21 @@ AC_SUBST(GLIB_CFLAGS)
 AC_SUBST(GLIB_LIBS)
 
 
+dnl ##########################################
+dnl   Mandatory GST Clutter & Clutter support
+dnl ##########################################
+PKG_CHECK_MODULES([CLUTTER], [clutter-1.0])
+PKG_CHECK_MODULES([CLUTTER_GTK], [clutter-gtk-1.0])
+PKG_CHECK_MODULES([CLUTTER_GST], [clutter-gst-2.0 gstreamer-app-1.0 gstreamer-plugins-base-1.0 
gstreamer-plugins-base-1.0])
+
+AC_SUBST(CLUTTER_CFLAGS)
+AC_SUBST(CLUTTER_LIBS)
+AC_SUBST(CLUTTER_GTK_CFLAGS)
+AC_SUBST(CLUTTER_GTK_LIBS)
+AC_SUBST(CLUTTER_GST_CFLAGS)
+AC_SUBST(CLUTTER_GST_LIBS)
+
+
 dnl ###############################
 dnl   Mandatory BOOST support
 dnl ###############################
@@ -514,7 +529,7 @@ AM_CONDITIONAL(HAVE_AVAHI, test "x$found_avahi" = "xyes")
 
 
 dnl ###############################
-dnl    GStreamer Support
+dnl    GStreamer Plugins Support
 dnl ###############################
 GSTREAMER="disabled"
 
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 295d6d6..8262057 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -154,7 +154,7 @@ libekiga_la_SOURCES += \
 
 if !WIN32
 libekiga_la_SOURCES += \
-       gui/xwindow.cpp         \
+       gui/xwindow.cpp \
        gui/xwindow.h
 endif
 
@@ -666,3 +666,18 @@ libekiga_la_SOURCES += \
 
 libekiga_la_LDFLAGS += $(DX_LIBS)
 endif
+
+##
+# Sources of the Clutter video output component
+##
+
+AM_CPPFLAGS += $(CLUTTER_CFLAGS) $(CLUTTER_GTK_CFLAGS) $(CLUTTER_GST_CFLAGS) \
+       -I$(top_srcdir)/lib/engine/components/clutter-gst-videooutput
+
+libekiga_la_SOURCES += \
+       engine/components/clutter-gst-videooutput/videooutput-manager-clutter-gst.cpp   \
+       engine/components/clutter-gst-videooutput/videooutput-manager-clutter-gst.h     \
+       engine/components/clutter-gst-videooutput/videooutput-main-clutter-gst.cpp      \
+       engine/components/clutter-gst-videooutput/videooutput-main-clutter-gst.h
+
+libekiga_la_LDFLAGS += $(CLUTTER_LIBS) $(CLUTTER_GTK_LIBS) $(CLUTTER_GST_LIBS)
diff --git a/lib/engine/components/clutter-gst-videooutput/videooutput-main-clutter-gst.cpp 
b/lib/engine/components/clutter-gst-videooutput/videooutput-main-clutter-gst.cpp
new file mode 100644
index 0000000..72bc5b2
--- /dev/null
+++ b/lib/engine/components/clutter-gst-videooutput/videooutput-main-clutter-gst.cpp
@@ -0,0 +1,67 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2014 Damien Sandras <dsandras seconix com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                         videooutput-main-clutter.cpp  -  description
+ *                         --------------------------------------------
+ *   begin                : Sun 15 December 2013
+ *   copyright            : (c) 2013 by Damien Sandras
+ *   description          : code to hook the Clutter display manager into the main program
+ *
+ */
+
+#include <clutter/clutter.h>
+#include <gst/gst.h>
+#include <clutter-gtk/clutter-gtk.h>
+
+#include "videooutput-core.h"
+
+#include "videooutput-main-clutter-gst.h"
+#include "videooutput-manager-clutter-gst.h"
+
+bool
+videooutput_clutter_gst_init (Ekiga::ServiceCore &core,
+                              G_GNUC_UNUSED int *argc,
+                              G_GNUC_UNUSED char **argv[])
+{
+  bool result = false;
+  boost::shared_ptr<Ekiga::VideoOutputCore> videooutput_core =
+    core.get<Ekiga::VideoOutputCore> ("videooutput-core");
+
+  if (videooutput_core) {
+
+    gst_init (argc, argv);
+    gtk_clutter_init (argc, argv);
+    GMVideoOutputManager_clutter_gst *videooutput_manager = new GMVideoOutputManager_clutter_gst (core);
+
+    videooutput_core->add_manager (*videooutput_manager);
+    result = true;
+  }
+
+  return result;
+}
diff --git a/lib/engine/components/clutter-gst-videooutput/videooutput-main-clutter-gst.h 
b/lib/engine/components/clutter-gst-videooutput/videooutput-main-clutter-gst.h
new file mode 100644
index 0000000..17af9ea
--- /dev/null
+++ b/lib/engine/components/clutter-gst-videooutput/videooutput-main-clutter-gst.h
@@ -0,0 +1,47 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2014 Damien Sandras <dsandras seconix com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                         videooutput-main-clutter-gst.h  -  description
+ *                         -----------------------------------------------
+ *   begin                : Sun 15 December 2013
+ *   copyright            : (c) 2013 by Damien Sandras
+ *   description          : code to hook the Clutter display manager into the main program
+ *
+ */
+
+#ifndef __VIDEOOUTPUT_MAIN_CLUTTER_GST_H__
+#define __VIDEOOUTPUT_MAIN_CLUTTER_GST_H__
+
+#include "services.h"
+
+bool videooutput_clutter_gst_init (Ekiga::ServiceCore &core,
+                                   int *argc,
+                                   char **argv[]);
+
+#endif
diff --git a/lib/engine/components/clutter-gst-videooutput/videooutput-manager-clutter-gst.cpp 
b/lib/engine/components/clutter-gst-videooutput/videooutput-manager-clutter-gst.cpp
new file mode 100644
index 0000000..ca0ab69
--- /dev/null
+++ b/lib/engine/components/clutter-gst-videooutput/videooutput-manager-clutter-gst.cpp
@@ -0,0 +1,271 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2014 Damien Sandras <dsandras seconix com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                         videooutput-manager-clutter-gst.cpp  -  description
+ *                         ---------------------------------------------------
+ *   begin                : Sun 15 December 2013
+ *   copyright            : (c) 2013 by Damien Sandras
+ *   description          : Clutter VideoOutput Manager code.
+ *
+ */
+
+
+#include <ptlib.h>
+
+#include <gtk/gtk.h>
+#include <gst/gst.h>
+#include <gst/app/gstappsrc.h>
+#include <clutter-gtk/clutter-gtk.h>
+
+#include "videooutput-manager-clutter-gst.h"
+#include "videooutput-info.h"
+#include "videoinput-info.h"
+
+#include "runtime.h"
+
+
+GMVideoOutputManager_clutter_gst::GMVideoOutputManager_clutter_gst (G_GNUC_UNUSED Ekiga::ServiceCore & _core)
+{
+  devices_nbr = 0;
+
+  for (int i = 0 ; i < 3 ; i++) {
+    texture[i] = NULL;
+    pipeline[i] = NULL;
+  }
+}
+
+
+GMVideoOutputManager_clutter_gst::~GMVideoOutputManager_clutter_gst ()
+{
+}
+
+
+void
+GMVideoOutputManager_clutter_gst::quit ()
+{
+}
+
+
+void
+GMVideoOutputManager_clutter_gst::open ()
+{
+  GstElement *appsrc = NULL;
+  GstElement *videosink = NULL;
+  GstElement *conv = NULL;
+  GstCaps *caps = NULL;
+  PWaitAndSignal m(device_mutex);
+
+  for (int i = 0 ; i < 3 ; ++i) {
+
+    std::ostringstream name;
+    name << std::string ("appsrc") << i;
+    pipeline[i] = gst_pipeline_new (NULL);
+    videosink = gst_element_factory_make ("autocluttersink", "videosink");
+    if (videosink == NULL)
+      videosink = gst_element_factory_make ("cluttersink", "videosink");
+    g_object_set (videosink, "texture", texture[i], NULL);
+
+    appsrc = gst_element_factory_make ("appsrc", name.str ().c_str ());
+    conv = gst_element_factory_make ("videoconvert", NULL);
+
+    /* set the caps on the source */
+    current_width[i] = 0;
+    current_height[i]= 0;
+    caps = gst_caps_new_simple ("video/x-raw",
+                                "format", G_TYPE_STRING, "I420",
+                                "framerate", GST_TYPE_FRACTION, 0, 1,
+                                "pixel-aspect-ratio" ,GST_TYPE_FRACTION, 1, 1,
+                                "width", G_TYPE_INT, 704,
+                                "height", G_TYPE_INT, 576,
+                                "red_mask",   G_TYPE_INT, 0x00ff0000,
+                                "green_mask", G_TYPE_INT, 0x0000ff00,
+                                "blue_mask",  G_TYPE_INT, 0x000000ff,
+                                "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
+                                NULL);
+
+    if (!videosink || !appsrc || !conv || !pipeline[i]) {
+
+      Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_clutter_gst::device_error_in_main,
+                                                this,
+                                                Ekiga::VO_ERROR));
+      break;
+    }
+
+    gst_app_src_set_caps (GST_APP_SRC (appsrc), caps);
+    g_object_set (G_OBJECT (appsrc),
+                  "block", TRUE,
+                  "max-bytes", MAX_VIDEO_SIZE*3/2,
+                  "stream-type", GST_APP_STREAM_TYPE_STREAM,
+                  NULL);
+    gst_bin_add_many (GST_BIN (pipeline[i]), appsrc, conv, videosink, NULL);
+    gst_element_link_many (appsrc, conv, videosink, NULL);
+    gst_caps_unref (caps);
+  }
+}
+
+
+void
+GMVideoOutputManager_clutter_gst::close ()
+{
+  PWaitAndSignal m(device_mutex);
+  for (int i = 0 ; i < 2 ; i++) {
+    if (!pipeline[i])
+      continue;
+
+    std::ostringstream name;
+    name << std::string ("appsrc") << i;
+    GstElement *appsrc = gst_bin_get_by_name (GST_BIN (pipeline[i]), name.str ().c_str ());
+    gst_app_src_end_of_stream (GST_APP_SRC (appsrc));
+    gst_element_set_state (pipeline[i], GST_STATE_NULL);
+    gst_object_unref (pipeline[i]);
+    pipeline[i] = NULL;
+  }
+  devices_nbr = 0;
+
+  Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_clutter_gst::device_closed_in_main,
+                                            this));
+}
+
+
+void
+GMVideoOutputManager_clutter_gst::set_frame_data (const char *data,
+                                                  unsigned width,
+                                                  unsigned height,
+                                                  unsigned i,
+                                                  int _devices_nbr)
+{
+  GstBuffer *buffer = NULL;
+  GstMapInfo info;
+  int buffer_size = width*height*3/2;
+  std::ostringstream name;
+
+  info.memory = NULL;
+  info.flags = GST_MAP_WRITE;
+  info.data = NULL;
+  info.size = 0;
+  info.maxsize = buffer_size;
+
+  PWaitAndSignal m(device_mutex);
+
+  if (!pipeline[i]) {
+    PTRACE (1, "GMVideoOutputManager_clutter_gst\tTrying to upload frame to closed pipeline " << i);
+    return;
+  }
+
+  if (_devices_nbr != devices_nbr) {
+    Ekiga::Runtime::run_in_main
+      (boost::bind (&GMVideoOutputManager_clutter_gst::device_opened_in_main,
+                    this,
+                    (_devices_nbr > 1),
+                    (_devices_nbr > 2)));
+    devices_nbr = (unsigned) _devices_nbr;
+  }
+
+  if (devices_nbr == 1) { // Only one video stream (either local or remote)
+    // Force whatever stream is received to be displayed as the remote
+    // video (the big one).
+    i = 1;
+  }
+  name << std::string ("appsrc") << i;
+  GstElement *appsrc = gst_bin_get_by_name (GST_BIN (pipeline[i]), name.str ().c_str ());
+
+  if (current_width[i] != width || current_height[i] != height) {
+
+    GstCaps *caps = gst_app_src_get_caps (GST_APP_SRC (appsrc));
+    GstCaps *new_caps = gst_caps_copy (caps);
+    gst_caps_set_simple (new_caps,
+                         "width", G_TYPE_INT, width,
+                         "height", G_TYPE_INT, height, NULL);
+    gst_app_src_set_caps (GST_APP_SRC (appsrc), new_caps);
+    gst_caps_unref (caps);
+    gst_caps_unref (new_caps);
+
+    current_height[i] = height;
+    current_width[i] = width;
+
+    Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_clutter_gst::size_changed_in_main,
+                                              this,
+                                              width,
+                                              height,
+                                              i));
+  }
+
+  buffer = gst_buffer_new_and_alloc (buffer_size);
+  gst_buffer_map (buffer, &info, GST_MAP_WRITE);
+  memcpy ((void *) info.data, (const void *) data, buffer_size);
+  info.size = buffer_size;
+  gst_buffer_unmap (buffer, &info);
+  gst_app_src_push_buffer (GST_APP_SRC (appsrc), buffer);
+
+  gst_element_set_state (pipeline[i], GST_STATE_PLAYING);
+}
+
+
+void
+GMVideoOutputManager_clutter_gst::set_display_info (const gpointer _local_video,
+                                                    const gpointer _remote_video)
+{
+  texture[0] = CLUTTER_ACTOR (_local_video);
+  texture[1] = CLUTTER_ACTOR (_remote_video);
+}
+
+
+void
+GMVideoOutputManager_clutter_gst::set_ext_display_info (const gpointer _ext_video)
+{
+  texture[2] = CLUTTER_ACTOR (_ext_video);
+}
+
+
+void
+GMVideoOutputManager_clutter_gst::size_changed_in_main (unsigned width,
+                                                        unsigned height,
+                                                        unsigned type)
+{
+  size_changed (width, height, type);
+}
+
+void
+GMVideoOutputManager_clutter_gst::device_opened_in_main (bool both,
+                                                         bool ext)
+{
+  device_opened (both, ext);
+}
+
+void
+GMVideoOutputManager_clutter_gst::device_closed_in_main ()
+{
+  device_closed ();
+}
+
+void
+GMVideoOutputManager_clutter_gst::device_error_in_main (Ekiga::VideoOutputErrorCodes code)
+{
+  device_error (code);
+}
diff --git a/lib/engine/components/clutter-gst-videooutput/videooutput-manager-clutter-gst.h 
b/lib/engine/components/clutter-gst-videooutput/videooutput-manager-clutter-gst.h
new file mode 100644
index 0000000..7aae0f4
--- /dev/null
+++ b/lib/engine/components/clutter-gst-videooutput/videooutput-manager-clutter-gst.h
@@ -0,0 +1,104 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2014 Damien Sandras <dsandras seconix com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                         videooutput-manager-clutter-gst.h  -  description
+ *                         -------------------------------------------------
+ *   begin                : Sun 15 December 2013
+ *   copyright            : (c) 2013 by Damien Sandras
+ *   description          : Clutter VideoOutput Manager code.
+ *
+ */
+
+#ifndef _VIDEOOUTPUT_MANAGER_CLUTTER_GST_H_
+#define _VIDEOOUTPUT_MANAGER_CLUTTER_GST_H_
+
+#include "services.h"
+#include "videooutput-manager.h"
+#include "videooutput-info.h"
+
+#include <glib.h>
+
+/**
+ * @addtogroup videooutput
+ * @{
+ */
+
+class GMVideoOutputManager_clutter_gst : public Ekiga::VideoOutputManager
+{
+public:
+  GMVideoOutputManager_clutter_gst (Ekiga::ServiceCore & _core);
+
+  ~GMVideoOutputManager_clutter_gst ();
+
+  void quit ();
+
+  void open ();
+
+  void close ();
+
+  void set_frame_data (const char *data,
+                       unsigned width,
+                       unsigned height,
+                       unsigned type,
+                       int devices_nbr);
+
+  void set_display_info (const gpointer local_video,
+                         const gpointer remote_video);
+
+  void set_ext_display_info (const gpointer ext_video);
+
+private:
+  void size_changed_in_main (unsigned width,
+                            unsigned height,
+                            unsigned type);
+
+  void device_opened_in_main (bool both,
+                             bool ext);
+
+  void device_closed_in_main ();
+
+  void device_error_in_main (Ekiga::VideoOutputErrorCodes code);
+
+  // Variables
+  PMutex device_mutex;
+
+  // 0 = local, 1 = remote, 2 = extended
+  unsigned current_width[3];
+  unsigned current_height[3];
+  GstElement *pipeline[3];
+  ClutterActor *texture[3];
+
+  int devices_nbr;
+};
+
+/**
+ * @}
+ */
+
+#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]