ext/ladspa/gstsignalprocessor.c: (gst_signal_processor_add_pad_from_template)
authorAndy Wingo <wingo@pobox.com>
Sat, 6 Jan 2007 15:56:55 +0000 (15:56 +0000)
committerAndy Wingo <wingo@pobox.com>
Sat, 6 Jan 2007 15:56:55 +0000 (15:56 +0000)
Original commit message from CVS:
2007-01-06  Andy Wingo  <wingo@pobox.com>

* ext/ladspa/gstsignalprocessor.c:
(gst_signal_processor_add_pad_from_template)
(gst_signal_processor_fixate): Add a fixate function, to assist in
pathological ladspa-sine-fcac ! fakesink can-activate-pull=true
cases.
(gst_signal_processor_prepare, gst_signal_processor_process): Add
nframes args so that getrange can tell ladspa how many frames to
process.
(gst_signal_processor_ouija_caps): setcaps needs to be called
before processing, which normally happens when chaining a buffer
to a pad. However in getrange mode with no sinks we need to check
explicitly for this condition, guess some caps to use, and use
those to setcaps(). Hence this mystical function.
(gst_signal_processor_do_pulls): Pull in bytes, not samples.
Divine the caps if necessary.
(gst_signal_processor_getrange): Interpret the length as bytes,
not samples.
(gst_signal_processor_chain): nframes=G_MAXUINT, will be limited
by incoming buffer sizes.

ChangeLog
ext/ladspa/gstsignalprocessor.c

index beb10c539f93f303cbc0fe26527d399edb64f79a..e929a2f0a785bdc8b6a9e8478cd1087d4ee596a3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2007-01-06  Andy Wingo  <wingo@pobox.com>
+
+       * ext/ladspa/gstsignalprocessor.c: 
+       (gst_signal_processor_add_pad_from_template)
+       (gst_signal_processor_fixate): Add a fixate function, to assist in
+       pathological ladspa-sine-fcac ! fakesink can-activate-pull=true
+       cases.
+       (gst_signal_processor_prepare, gst_signal_processor_process): Add
+       nframes args so that getrange can tell ladspa how many frames to
+       process.
+       (gst_signal_processor_ouija_caps): setcaps needs to be called
+       before processing, which normally happens when chaining a buffer
+       to a pad. However in getrange mode with no sinks we need to check
+       explicitly for this condition, guess some caps to use, and use
+       those to setcaps(). Hence this mystical function.
+       (gst_signal_processor_do_pulls): Pull in bytes, not samples.
+       Divine the caps if necessary.
+       (gst_signal_processor_getrange): Interpret the length as bytes,
+       not samples.
+       (gst_signal_processor_chain): nframes=G_MAXUINT, will be limited
+       by incoming buffer sizes.
+
 2007-01-06  Edward Hervey  <edward@fluendo.com>
 
        * gst/real/gstrealaudiodec.c: (gst_real_audio_dec_finalize):
index 99865c0ffb9497f053622f9a45790a90462a7fba..7e0257782797a0b5a471359e0d0309f91667dec6 100644 (file)
@@ -156,6 +156,7 @@ static GstFlowReturn gst_signal_processor_getrange (GstPad * pad,
 static GstFlowReturn gst_signal_processor_chain (GstPad * pad,
     GstBuffer * buffer);
 static gboolean gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps);
+static void gst_signal_processor_fixate (GstPad * pad, GstCaps * caps);
 
 
 static void
@@ -198,6 +199,8 @@ gst_signal_processor_add_pad_from_template (GstSignalProcessor * self,
 
   gst_pad_set_setcaps_function (new,
       GST_DEBUG_FUNCPTR (gst_signal_processor_setcaps));
+  gst_pad_set_fixatecaps_function (new,
+      GST_DEBUG_FUNCPTR (gst_signal_processor_fixate));
 
   if (templ->direction == GST_PAD_SINK) {
     GST_DEBUG ("added new sink pad");
@@ -435,6 +438,14 @@ impossible:
   }
 }
 
+static void
+gst_signal_processor_fixate (GstPad * pad, GstCaps * caps)
+{
+  /* last-ditch attempt at sanity */
+  gst_structure_fixate_field_nearest_int
+      (gst_caps_get_structure (caps, 0), "rate", 44100);
+}
+
 static gboolean
 gst_signal_processor_event (GstPad * pad, GstEvent * event)
 {
@@ -468,12 +479,12 @@ gst_signal_processor_event (GstPad * pad, GstEvent * event)
 }
 
 static guint
-gst_signal_processor_prepare (GstSignalProcessor * self)
+gst_signal_processor_prepare (GstSignalProcessor * self, guint nframes)
 {
   GstElement *elem = (GstElement *) self;
   GstSignalProcessorClass *klass;
   GList *sinks, *srcs;
-  guint samples_avail = G_MAXUINT;
+  guint samples_avail = nframes;
 
   klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
 
@@ -488,13 +499,6 @@ gst_signal_processor_prepare (GstSignalProcessor * self)
     self->audio_in[sinkpad->index] = sinkpad->data;
   }
 
-  if (samples_avail == G_MAXUINT) {
-    /* we don't have any sink pads, just choose a size -- should fix this
-     * function to have a suggested number of samples in the case of
-     * gst_pad_pull_range */
-    samples_avail = 256;
-  }
-
   /* now assign output buffers. we can avoid allocation by reusing input
      buffers, but only if process() can work in place, and if the input buffer
      is the exact size of the number of samples we are processing. */
@@ -580,18 +584,18 @@ gst_signal_processor_update_inputs (GstSignalProcessor * self, guint nprocessed)
 }
 
 static void
-gst_signal_processor_process (GstSignalProcessor * self)
+gst_signal_processor_process (GstSignalProcessor * self, guint nframes)
 {
   GstElement *elem;
   GstSignalProcessorClass *klass;
-  guint nframes;
 
   g_return_if_fail (self->pending_in == 0);
   g_return_if_fail (self->pending_out == 0);
+  g_return_if_fail (GST_SIGNAL_PROCESSOR_IS_RUNNING (self));
 
   elem = GST_ELEMENT (self);
 
-  nframes = gst_signal_processor_prepare (self);
+  nframes = gst_signal_processor_prepare (self, nframes);
   if (G_UNLIKELY (nframes == 0))
     goto flow_error;
 
@@ -668,6 +672,32 @@ gst_signal_processor_flush (GstSignalProcessor * self)
   self->pending_in = klass->num_audio_in;
 }
 
+static void
+gst_signal_processor_ouija_caps (GstSignalProcessor * self)
+{
+  GstElement *element;
+  GstPad *srcpad;
+  GstCaps *srccaps, *peercaps, *caps;
+
+  /* we have no sink pads, no way to know what caps we should be producing.
+     guess! */
+
+  element = GST_ELEMENT (self);
+  g_return_if_fail (element->sinkpads == NULL);
+  g_return_if_fail (element->srcpads != NULL);
+  srcpad = GST_PAD (element->srcpads->data);
+
+  srccaps = gst_pad_get_caps (srcpad);
+  peercaps = gst_pad_peer_get_caps (srcpad);
+  caps = gst_caps_intersect (srccaps, peercaps);
+  gst_caps_unref (srccaps);
+  gst_caps_unref (peercaps);
+  gst_caps_truncate (caps);
+  gst_pad_fixate_caps (srcpad, caps);
+  gst_signal_processor_setcaps (srcpad, caps);
+  gst_caps_unref (caps);
+}
+
 static void
 gst_signal_processor_do_pulls (GstSignalProcessor * self, guint nframes)
 {
@@ -688,7 +718,9 @@ gst_signal_processor_do_pulls (GstSignalProcessor * self, guint nframes)
       continue;
     }
 
-    ret = gst_pad_pull_range (GST_PAD (spad), -1, nframes, &buf);
+    ret =
+        gst_pad_pull_range (GST_PAD (spad), -1, nframes * sizeof (gfloat),
+        &buf);
 
     if (ret != GST_FLOW_OK) {
       gst_signal_processor_flush (self);
@@ -703,11 +735,14 @@ gst_signal_processor_do_pulls (GstSignalProcessor * self, guint nframes)
     }
   }
 
+  if (!self->caps)
+    gst_signal_processor_ouija_caps (self);
+
   if (self->pending_in != 0) {
     g_critical ("Something wierd happened...");
     self->flow_state = GST_FLOW_ERROR;
   } else {
-    gst_signal_processor_process (self);
+    gst_signal_processor_process (self, nframes);
   }
 }
 
@@ -728,7 +763,7 @@ gst_signal_processor_getrange (GstPad * pad, guint64 offset,
     self->pending_out--;
     ret = GST_FLOW_OK;
   } else {
-    gst_signal_processor_do_pulls (self, length);
+    gst_signal_processor_do_pulls (self, length / sizeof (gfloat));
     if (!spad->pen) {
       /* this is an error condition */
       *buffer = NULL;
@@ -800,7 +835,7 @@ gst_signal_processor_chain (GstPad * pad, GstBuffer * buffer)
   gst_signal_processor_pen_buffer (self, pad, buffer);
 
   if (self->pending_in == 0) {
-    gst_signal_processor_process (self);
+    gst_signal_processor_process (self, G_MAXUINT);
 
     gst_signal_processor_do_pushes (self);
   }