[ekiga] Reworked the gstreamer audio output code



commit af01f5c585820c47efcff5c8c393b0061dae5ba8
Author: Julien Puydt <jpuydt newton localdomain>
Date:   Sun Jan 29 01:24:00 2012 +0100

    Reworked the gstreamer audio output code
    
    The code is simpler ; too simple because it doesn't handle errors, but that
    can be added back when it actually works.
    
    Currently, sound events work great, sound in calls doesn't.

 plugins/gstreamer/gst-audiooutput.cpp |  256 ++++++++++++++++-----------------
 plugins/gstreamer/gst-audiooutput.h   |    4 +-
 2 files changed, 126 insertions(+), 134 deletions(-)
---
diff --git a/plugins/gstreamer/gst-audiooutput.cpp b/plugins/gstreamer/gst-audiooutput.cpp
index d81a5cf..ccbaf3a 100644
--- a/plugins/gstreamer/gst-audiooutput.cpp
+++ b/plugins/gstreamer/gst-audiooutput.cpp
@@ -35,34 +35,109 @@
  *
  */
 
-#include <glib/gi18n.h>
+#include <string.h>
 
-#include "gst-audiooutput.h"
+#include <glib/gi18n.h>
 
 #include <gst/interfaces/propertyprobe.h>
 #include <gst/app/gstappsrc.h>
 #include <gst/app/gstappbuffer.h>
 
-#include <string.h>
+#include "runtime.h"
 
-static gboolean
-pipeline_cleaner (GstBus* /*bus*/,
-		  GstMessage* message,
-		  gpointer pipeline)
+#include "gst-audiooutput.h"
+
+struct gstreamer_worker
+{
+  GstElement* pipeline;
+  GstElement* volume;
+  GstElement* src;
+};
+
+static void
+gstreamer_worker_setup (gstreamer_worker* self,
+			const gchar* command)
 {
-  bool result = TRUE;
+  g_message ("%s\t%s\n", __PRETTY_FUNCTION__, command);
+  self->pipeline = gst_parse_launch (command, NULL);
+  (void)gst_element_set_state (self->pipeline, GST_STATE_PLAYING);
+  self->volume = gst_bin_get_by_name (GST_BIN (self->pipeline), "ekiga_volume");
+  self->src = gst_bin_get_by_name (GST_BIN (self->pipeline), "ekiga_src");
+}
 
-  if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS
-      && GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (pipeline)) {
+static void
+gstreamer_worker_destroy (gstreamer_worker* self)
+{
+  g_object_unref (self->src);
+  self->src = NULL;
+  if (self->volume)
+    g_object_unref (self->volume);
+  self->volume = NULL;
+  g_object_unref (self->pipeline);
+  self->pipeline = NULL;
+  g_free (self);
+}
 
-    result = FALSE;
-    gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
-    g_object_unref (pipeline);
-  }
+static void
+gstreamer_worker_close (gstreamer_worker* self)
+{
+  g_message ("%s\n", __PRETTY_FUNCTION__);
+  if (self->src)
+    gst_app_src_end_of_stream (GST_APP_SRC (self->src));
+  Ekiga::Runtime::run_in_main (boost::bind(&gstreamer_worker_destroy, self), 1);
+}
+
+static void
+gstreamer_worker_set_volume (gstreamer_worker* self,
+			     gfloat valf)
+{
+  g_message ("%s\t%f\n", __PRETTY_FUNCTION__, valf);
+  if (self->volume)
+    g_object_set (G_OBJECT (self->volume),
+		  "volume", valf,
+		  NULL);
+}
+
+static gfloat
+gstreamer_worker_get_volume (gstreamer_worker* self)
+{
+  gfloat result = -1;
+  if (self->volume)
+    g_object_get (G_OBJECT (self->volume),
+		  "volume", &result,
+		  NULL);
 
   return result;
 }
 
+static void
+gstreamer_worker_set_buffer_size (gstreamer_worker* self,
+				  unsigned size)
+{
+  g_message ("%s\t%d\n", __PRETTY_FUNCTION__, size);
+  if (self->src)
+    g_object_set (G_OBJECT (self->src),
+		  "blocksize", size,
+		  NULL);
+}
+
+static void
+gstreamer_worker_set_frame_data (gstreamer_worker* self,
+				 const char* data,
+				 unsigned size)
+{
+  gchar* tmp = NULL;
+  GstBuffer* buffer = NULL;
+
+  if (self->src) {
+
+    tmp = (gchar*)g_malloc0 (size);
+    memcpy (tmp, data, size);
+    buffer = gst_app_buffer_new (tmp, size,
+				 (GstAppBufferFinalizeFunc)g_free, tmp);
+    gst_app_src_push_buffer (GST_APP_SRC (self->src), buffer);
+  }
+}
 
 GST::AudioOutputManager::AudioOutputManager ():
   already_detected_devices(false)
@@ -117,11 +192,11 @@ GST::AudioOutputManager::open (Ekiga::AudioOutputPS ps,
 			       unsigned samplerate,
 			       unsigned bits_per_sample)
 {
-  bool result = false;
+  g_message ("%s\n", __PRETTY_FUNCTION__);
   unsigned ii = (ps == Ekiga::primary)?0:1;
   gchar* command = NULL;
-  GError* error = NULL;
-  GstState current;
+
+  worker[ii] = g_new0 (gstreamer_worker, 1);
 
   if ( !already_detected_devices)
     detect_devices ();
@@ -133,96 +208,42 @@ GST::AudioOutputManager::open (Ekiga::AudioOutputPS ps,
 			     ",width=%d"
 			     ",depth=%d"
 			     ",signed=true,endianness=1234"
-			     " ! %s",
+			     " ! audiorate ! %s",
 			     samplerate, channels, bits_per_sample, bits_per_sample,
 			     devices_by_name[std::pair<std::string,std::string>(current_state[ii].device.source, current_state[ii].device.name)].c_str ());
-  //g_print ("Pipeline: %s\n", command);
-  pipeline[ii] = gst_parse_launch (command, &error);
-
-  if (error == NULL) {
-
-    (void)gst_element_set_state (pipeline[ii], GST_STATE_PLAYING);
-
-    // this will make us wait so we can return the right value...
-    (void)gst_element_get_state (pipeline[ii],
-				 &current,
-				 NULL,
-				 GST_SECOND);
-
-    if ( !(current == GST_STATE_PLAYING
-	   || current == GST_STATE_PAUSED)) {
-
-      gst_element_set_state (pipeline[ii], GST_STATE_NULL);
-      gst_object_unref (GST_OBJECT (pipeline[ii]));
-      pipeline[ii] = NULL;
-      result = false;
-    } else {
-
-      Ekiga::AudioOutputSettings settings;
-      GstElement* volume = NULL;
-      gfloat val;
-
-      volume = gst_bin_get_by_name (GST_BIN (pipeline[ii]), "ekiga_volume");
-      if (volume != NULL) {
+  gstreamer_worker_setup (worker[ii], command);
+  g_free (command);
 
-	g_object_get (G_OBJECT (volume),
-		      "volume", &val,
-		      NULL);
-	settings.volume = (unsigned)(255*val);
-	settings.modifyable = true;
-	g_object_unref (volume);
-      } else {
-
-	settings.modifyable = false;
-      }
-      current_state[ii].channels = channels;
-      current_state[ii].samplerate = samplerate;
-      current_state[ii].bits_per_sample = bits_per_sample;
-      device_opened (ps, current_state[ii].device, settings);
-      result = true;
-    }
+  Ekiga::AudioOutputSettings settings;
+  gfloat vol = gstreamer_worker_get_volume (worker[ii]);
+  if (vol >= 0) {
 
+    settings.volume = (unsigned)(255*vol);
+    settings.modifyable = true;
   } else {
 
-    g_error_free (error);
-    result = false;
+    settings.modifyable = false;
   }
+  current_state[ii].channels = channels;
+  current_state[ii].samplerate = samplerate;
+  current_state[ii].bits_per_sample = bits_per_sample;
+  current_state[ii].opened = true;
+  device_opened (ps, current_state[ii].device, settings);
 
-  g_free (command);
-
-  current_state[ii].opened = result;
-
-//   std::cout << __PRETTY_FUNCTION__
-// 	    << " result=";
-//   if (result)
-//     std::cout << "TRUE";
-//   else
-//     std::cout << "FALSE";
-//   std::cout << std::endl;
-
-  return result;
+  return true;
 }
 
 void
 GST::AudioOutputManager::close (Ekiga::AudioOutputPS ps)
 {
+  g_message ("%s\n", __PRETTY_FUNCTION__);
   unsigned ii = (ps == Ekiga::primary)?0:1;
-  if (pipeline[ii] != NULL) {
-
-    GstElement* src = gst_bin_get_by_name (GST_BIN (pipeline[ii]), "ekiga_src");
-
-    if (src != NULL) {
 
-      gst_app_src_end_of_stream (GST_APP_SRC (src));
-      GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline[ii]));
-      gst_bus_add_watch (bus, pipeline_cleaner, pipeline[ii]);
-      gst_object_unref (bus);
-      gst_element_set_state (pipeline[ii], GST_STATE_NULL);
-      pipeline[ii] = NULL;
-      device_closed (ps, current_state[ii].device);
-    }
-  }
+  if (worker[ii])
+      gstreamer_worker_close (worker[ii]);
+  device_closed (ps, current_state[ii].device);
   current_state[ii].opened = false;
+  worker[ii] = NULL;
 }
 
 void
@@ -231,17 +252,7 @@ GST::AudioOutputManager::set_buffer_size (Ekiga::AudioOutputPS ps,
 					  unsigned /*num_buffers*/)
 {
   unsigned ii = (ps == Ekiga::primary)?0:1;
-  GstElement* src = NULL;
-
-  src = gst_bin_get_by_name (GST_BIN (pipeline[ii]), "ekiga_src");
-
-  if (src != NULL) {
-
-    g_object_set (G_OBJECT (src),
-		  "blocksize", buffer_size,
-		  NULL);
-    g_object_unref (src);
-  }
+  gstreamer_worker_set_buffer_size (worker[ii], buffer_size);
 }
 
 bool
@@ -250,30 +261,20 @@ GST::AudioOutputManager::set_frame_data (Ekiga::AudioOutputPS ps,
 					 unsigned size,
 					 unsigned& written)
 {
-  bool result = false;
+  bool result;
   unsigned ii = (ps == Ekiga::primary)?0:1;
-  gchar* tmp = NULL;
-  GstBuffer* buffer = NULL;
-  GstElement* src = NULL;
-
-  written = 0;
 
-  g_return_val_if_fail (GST_IS_BIN (pipeline[ii]), false);
+  if (worker[ii]) {
 
-  src = gst_bin_get_by_name (GST_BIN (pipeline[ii]), "ekiga_src");
-
-  if (src != NULL) {
-
-    tmp = (gchar*)g_malloc0 (size);
-    memcpy (tmp, data, size);
-    buffer = gst_app_buffer_new (tmp, size,
-				 (GstAppBufferFinalizeFunc)g_free, tmp);
-    gst_app_src_push_buffer (GST_APP_SRC (src), buffer);
+    gstreamer_worker_set_frame_data (worker[ii], data, size);
     written = size;
     result = true;
-    g_object_unref (src);
-  }
+  } else {
 
+    // we're closed already!
+    written = 0;
+    result = false;
+  }
   return result;
 }
 
@@ -282,19 +283,8 @@ GST::AudioOutputManager::set_volume (Ekiga::AudioOutputPS ps,
 				     unsigned valu)
 {
   unsigned ii = (ps == Ekiga::primary)?0:1;
-  GstElement* volume = NULL;
-  gfloat valf;
 
-  valf = valu / 255.0;
-
-  volume = gst_bin_get_by_name (GST_BIN (pipeline[ii]), "ekiga_volume");
-  if (volume != NULL) {
-
-    g_object_set (G_OBJECT (volume),
-		  "volume", valf,
-		  NULL);
-    g_object_unref (volume);
-  }
+  gstreamer_worker_set_volume (worker[ii], valu / 255.0);
 }
 
 bool
diff --git a/plugins/gstreamer/gst-audiooutput.h b/plugins/gstreamer/gst-audiooutput.h
index 16cd2af..ff4a2e5 100644
--- a/plugins/gstreamer/gst-audiooutput.h
+++ b/plugins/gstreamer/gst-audiooutput.h
@@ -43,6 +43,8 @@
 
 #include <map>
 
+struct gstreamer_worker;
+
 namespace GST
 {
   class AudioOutputManager: public Ekiga::AudioOutputManager
@@ -93,7 +95,7 @@ namespace GST
      * the actual device */
     std::map<std::pair<std::string, std::string>, std::string> devices_by_name;
 
-    GstElement* pipeline[2];
+    gstreamer_worker* worker[2];
   };
 };
 



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