ext/ladspa/gstsignalprocessor.h: Add infrastructure for storing whether a processor...
authorAndy Wingo <wingo@pobox.com>
Fri, 4 Aug 2006 11:38:54 +0000 (11:38 +0000)
committerAndy Wingo <wingo@pobox.com>
Fri, 4 Aug 2006 11:38:54 +0000 (11:38 +0000)
Original commit message from CVS:
2006-08-04  Andy Wingo  <wingo@pobox.com>

* ext/ladspa/gstsignalprocessor.h: Add infrastructure for storing
whether a processor can work in place or not, and for keeping
track of its state. Change the FlowReturn instance variable from
"state" to "flow_state", all callers changed.

* ext/ladspa/gstsignalprocessor.c (gst_signal_processor_setup)
(gst_signal_processor_start, gst_signal_processor_stop)
(gst_signal_processor_cleanup): New functions to manage the
processor's state.
(gst_signal_processor_setcaps): start() as well as setup() here.
(gst_signal_processor_prepare): Respect CAN_PROCESS_IN_PLACE.
(gst_signal_processor_change_state): Stop and cleanup the
processor as we go to NULL.

* ext/ladspa/gstladspa.c (gst_ladspa_base_init): Reuse buffers if
INPLACE_BROKEN is not set.

* ext/ladspa/gstsignalprocessor.c (gst_signal_processor_prepare):
Do the alloc_buffer in bytes, not frames.

ext/ladspa/gstladspa.c
ext/ladspa/gstsignalprocessor.c
ext/ladspa/gstsignalprocessor.h

index c6d0e0b23abcf6529914cda67825ed8e08df8b83..fc2a93433b74fac83b1e8b285cf65374e05cb1a7 100644 (file)
@@ -132,6 +132,9 @@ gst_ladspa_base_init (gpointer g_class)
     }
   }
 
+  if (!LADSPA_IS_INPLACE_BROKEN (desc->Properties))
+    GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE (klass);
+
   klass->descriptor = desc;
 }
 
index 0592fce5ca398c34de80c9a67ccbb1eb098c0778..2d835416ce9bc9d23bc471bc3257c94b96db8409 100644 (file)
@@ -236,6 +236,8 @@ gst_signal_processor_init (GstSignalProcessor * self,
     templates = templates->next;
   }
 
+  self->state = GST_SIGNAL_PROCESSOR_STATE_NULL;
+
   self->audio_in = g_new0 (gfloat *, klass->num_audio_in);
   self->control_in = g_new0 (gfloat, klass->num_control_in);
   self->audio_out = g_new0 (gfloat *, klass->num_audio_out);
@@ -265,14 +267,99 @@ gst_signal_processor_finalize (GObject * object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gboolean
+gst_signal_processor_setup (GstSignalProcessor * self, guint sample_rate)
+{
+  GstSignalProcessorClass *klass;
+  gboolean ret = TRUE;
+
+  klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
+  g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_NULL, FALSE);
+
+  if (klass->setup)
+    ret = klass->setup (self, sample_rate);
+
+  if (!ret)
+    goto setup_failed;
+
+  self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED;
+
+  return ret;
+
+setup_failed:
+  {
+    GST_INFO_OBJECT (self, "setup() failed at %u Hz", sample_rate);
+    return ret;
+  }
+}
+
+static gboolean
+gst_signal_processor_start (GstSignalProcessor * self)
+{
+  GstSignalProcessorClass *klass;
+  gboolean ret = TRUE;
+
+  klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
+  g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED,
+      FALSE);
+
+  if (klass->start)
+    ret = klass->start (self);
+
+  if (!ret)
+    goto start_failed;
+
+  self->state = GST_SIGNAL_PROCESSOR_STATE_RUNNING;
+
+  return ret;
+
+start_failed:
+  {
+    GST_INFO_OBJECT (self, "start() failed");
+    return ret;
+  }
+}
+
+static void
+gst_signal_processor_stop (GstSignalProcessor * self)
+{
+  GstSignalProcessorClass *klass;
+
+  klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
+  g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING);
+
+  if (klass->stop)
+    klass->stop (self);
+
+  /* should also flush our buffers perhaps? */
+
+  self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED;
+}
+
+static void
+gst_signal_processor_cleanup (GstSignalProcessor * self)
+{
+  GstSignalProcessorClass *klass;
+
+  klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
+  g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED);
+
+  if (klass->cleanup)
+    klass->cleanup (self);
+
+  self->state = GST_SIGNAL_PROCESSOR_STATE_NULL;
+}
+
 static gboolean
 gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstSignalProcessor *self;
-  GstSignalProcessorClass *klass;
 
   self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad));
-  klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
 
   /* the whole processor has one caps; if the sample rate changes, let subclass
      implementations know */
@@ -288,8 +375,10 @@ gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps)
       GST_DEBUG_OBJECT (self, "Got rate=%d", sample_rate);
     }
 
-    if (!klass->setup (self, sample_rate)) {
-      goto setup_failed;
+    if (!gst_signal_processor_setup (self, sample_rate)) {
+      goto start_failed;
+    } else if (!gst_signal_processor_start (self)) {
+      goto start_failed;
     } else {
       self->sample_rate = sample_rate;
       gst_caps_replace (&self->caps, caps);
@@ -304,9 +393,8 @@ gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps)
 
   return TRUE;
 
-setup_failed:
+start_failed:
   {
-    GST_INFO_OBJECT (self, "setup() failed");
     gst_object_unref (self);
     return FALSE;
   }
@@ -344,9 +432,12 @@ static guint
 gst_signal_processor_prepare (GstSignalProcessor * self)
 {
   GstElement *elem = (GstElement *) self;
+  GstSignalProcessorClass *klass;
   GList *sinks, *srcs;
   guint samples_avail = G_MAXUINT;
 
+  klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
+
   /* first, assign audio_in pointers, and determine the number of samples that
    * we can process */
   for (sinks = elem->sinkpads; sinks; sinks = sinks->next) {
@@ -370,24 +461,26 @@ gst_signal_processor_prepare (GstSignalProcessor * self)
      is the exact size of the number of samples we are processing. */
   sinks = elem->sinkpads;
   srcs = elem->srcpads;
-  while (sinks && srcs) {
-    GstSignalProcessorPad *sinkpad, *srcpad;
+  if (GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE (klass)) {
+    while (sinks && srcs) {
+      GstSignalProcessorPad *sinkpad, *srcpad;
 
-    sinkpad = (GstSignalProcessorPad *) sinks->data;
-    srcpad = (GstSignalProcessorPad *) srcs->data;
+      sinkpad = (GstSignalProcessorPad *) sinks->data;
+      srcpad = (GstSignalProcessorPad *) srcs->data;
 
-    if (GST_BUFFER_SIZE (sinkpad->pen) == samples_avail * sizeof (gfloat)) {
-      /* reusable, yay */
-      g_assert (sinkpad->samples_avail == samples_avail);
-      srcpad->pen = sinkpad->pen;
-      sinkpad->pen = NULL;
-      self->audio_out[srcpad->index] = sinkpad->data;
-      self->pending_out++;
+      if (GST_BUFFER_SIZE (sinkpad->pen) == samples_avail * sizeof (gfloat)) {
+        /* reusable, yay */
+        g_assert (sinkpad->samples_avail == samples_avail);
+        srcpad->pen = sinkpad->pen;
+        sinkpad->pen = NULL;
+        self->audio_out[srcpad->index] = sinkpad->data;
+        self->pending_out++;
 
-      srcs = srcs->next;
-    }
+        srcs = srcs->next;
+      }
 
-    sinks = sinks->next;
+      sinks = sinks->next;
+    }
   }
 
   /* now allocate for any remaining outputs */
@@ -399,10 +492,10 @@ gst_signal_processor_prepare (GstSignalProcessor * self)
 
     ret =
         gst_pad_alloc_buffer_and_set_caps (GST_PAD (srcpad), -1,
-        samples_avail, GST_PAD_CAPS (srcpad), &srcpad->pen);
+        samples_avail * sizeof (gfloat), GST_PAD_CAPS (srcpad), &srcpad->pen);
 
     if (ret != GST_FLOW_OK) {
-      self->state = ret;
+      self->flow_state = ret;
       return 0;
     } else {
       self->audio_out[srcpad->index] = (gfloat *) GST_BUFFER_DATA (srcpad->pen);
@@ -476,7 +569,7 @@ gst_signal_processor_process (GstSignalProcessor * self)
 flow_error:
   {
     GST_WARNING ("gst_pad_alloc_buffer_and_set_caps() returned %d",
-        self->state);
+        self->flow_state);
     return;
   }
 }
@@ -546,12 +639,12 @@ gst_signal_processor_do_pulls (GstSignalProcessor * self, guint nframes)
     ret = gst_pad_pull_range (GST_PAD (spad), -1, nframes, &buf);
 
     if (ret != GST_FLOW_OK) {
-      self->state = ret;
+      self->flow_state = ret;
       gst_signal_processor_flush (self);
       return;
     } else if (!buf) {
       g_critical ("Pull failed to make a buffer!");
-      self->state = GST_FLOW_ERROR;
+      self->flow_state = GST_FLOW_ERROR;
       return;
     } else {
       gst_signal_processor_pen_buffer (self, GST_PAD (spad), buf);
@@ -560,7 +653,7 @@ gst_signal_processor_do_pulls (GstSignalProcessor * self, guint nframes)
 
   if (self->pending_in != 0) {
     g_critical ("Something wierd happened...");
-    self->state = GST_FLOW_ERROR;
+    self->flow_state = GST_FLOW_ERROR;
   } else {
     gst_signal_processor_process (self);
   }
@@ -587,7 +680,7 @@ gst_signal_processor_getrange (GstPad * pad, guint64 offset,
     if (!spad->pen) {
       /* this is an error condition */
       *buffer = NULL;
-      ret = self->state;
+      ret = self->flow_state;
     } else {
       *buffer = spad->pen;
       spad->pen = NULL;
@@ -625,7 +718,7 @@ gst_signal_processor_do_pushes (GstSignalProcessor * self)
     ret = gst_pad_push (GST_PAD (spad), spad->pen);
 
     if (ret != GST_FLOW_OK) {
-      self->state = ret;
+      self->flow_state = ret;
       gst_signal_processor_flush (self);
       return;
     } else {
@@ -637,7 +730,7 @@ gst_signal_processor_do_pushes (GstSignalProcessor * self)
 
   if (self->pending_out != 0) {
     g_critical ("Something wierd happened...");
-    self->state = GST_FLOW_ERROR;
+    self->flow_state = GST_FLOW_ERROR;
   }
 }
 
@@ -658,7 +751,7 @@ gst_signal_processor_chain (GstPad * pad, GstBuffer * buffer)
 
   gst_object_unref (self);
 
-  return self->state;
+  return self->flow_state;
 }
 
 static void
@@ -778,13 +871,10 @@ static GstStateChangeReturn
 gst_signal_processor_change_state (GstElement * element,
     GstStateChange transition)
 {
-  /* GstSignalProcessor *self;
-     GstSignalProcessorClass *klass; */
+  GstSignalProcessor *self;
   GstStateChangeReturn result;
 
-  /* self = GST_SIGNAL_PROCESSOR (element);
-     klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); */
-
+  self = GST_SIGNAL_PROCESSOR (element);
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
@@ -806,9 +896,12 @@ gst_signal_processor_change_state (GstElement * element,
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+      if (GST_SIGNAL_PROCESSOR_IS_RUNNING (self))
+        gst_signal_processor_stop (self);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
-      /* gst_signal_processor_cleanup (self); */
+      if (GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self))
+        gst_signal_processor_cleanup (self);
       break;
     default:
       break;
index 919280e4109fc7c7fc463a5cd667841cb82750b7..eb9cd40e13201955ff8484ffcd939db25ac739fb 100644 (file)
 G_BEGIN_DECLS
 
 
+typedef enum 
+{
+  GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE = 1<<0
+} GstSignalProcessorClassFlags;
+
+#define GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE(klass)         \
+  (GST_SIGNAL_PROCESSOR_CLASS (klass)->flags &                                 \
+   GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE)
+#define GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE(klass)     \
+  GST_SIGNAL_PROCESSOR_CLASS (klass)->flags |=                         \
+    GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE
+
+typedef enum 
+{
+  GST_SIGNAL_PROCESSOR_STATE_NULL,
+  GST_SIGNAL_PROCESSOR_STATE_INITIALIZED,
+  GST_SIGNAL_PROCESSOR_STATE_RUNNING
+} GstSignalProcessorState;
+
+
 #define GST_TYPE_SIGNAL_PROCESSOR            (gst_signal_processor_get_type())
 #define GST_SIGNAL_PROCESSOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessor))
 #define GST_SIGNAL_PROCESSOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessorClass))
@@ -37,6 +57,10 @@ G_BEGIN_DECLS
 #define GST_IS_SIGNAL_PROCESSOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SIGNAL_PROCESSOR))
 #define GST_IS_SIGNAL_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SIGNAL_PROCESSOR))
 
+#define GST_SIGNAL_PROCESSOR_IS_INITIALIZED(obj) \
+  (GST_SIGNAL_PROCESSOR (obj)->state >= GST_SIGNAL_PROCESSOR_STATE_INITIALIZED)
+#define GST_SIGNAL_PROCESSOR_IS_RUNNING(obj) \
+  (GST_SIGNAL_PROCESSOR (obj)->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING)
 
 typedef struct _GstSignalProcessor GstSignalProcessor;
 typedef struct _GstSignalProcessorClass GstSignalProcessorClass;
@@ -49,7 +73,9 @@ struct _GstSignalProcessor {
 
   guint sample_rate;
 
-  GstFlowReturn state;
+  GstSignalProcessorState state;
+
+  GstFlowReturn flow_state;
 
   GstActivateMode mode;
 
@@ -71,6 +97,8 @@ struct _GstSignalProcessorClass {
   guint num_control_out;
   guint num_audio_out;
 
+  guint flags;
+
   /* virtual methods for subclasses */
 
   gboolean      (*setup)        (GstSignalProcessor *self, guint sample_rate);