diff options
| author | Andy Wingo <wingo@pobox.com> | 2006-08-04 09:05:53 +0000 | 
|---|---|---|
| committer | Andy Wingo <wingo@pobox.com> | 2006-08-04 09:05:53 +0000 | 
| commit | 6ea23316fd600e0acce5f8dedd896654afb1955d (patch) | |
| tree | 6a721cf2e5f79ba2bf00350329921c77c8e98911 | |
| parent | 9457674bc0f0d31efcd5f85e99d3214dcff5c32a (diff) | |
ext/ladspa/gstsignalprocessor.c (gst_signal_processor_setcaps) (gst_signal_processor_prepare) (gst_signal_processor_u...
Original commit message from CVS:
2006-08-04  Andy Wingo  <wingo@pobox.com>
* ext/ladspa/gstsignalprocessor.c (gst_signal_processor_setcaps)
(gst_signal_processor_prepare)
(gst_signal_processor_update_inputs)
(gst_signal_processor_process, gst_signal_processor_pen_buffer)
(gst_signal_processor_flush)
(gst_signal_processor_sink_activate_push)
(gst_signal_processor_src_activate_pull)
(gst_signal_processor_change_state): Remove the last of the code
that assumes that we process whole buffers at a time. Fix some
debugging. Seems to work now in some cases.
| -rw-r--r-- | ChangeLog | 13 | ||||
| -rw-r--r-- | ext/ladspa/gstsignalprocessor.c | 201 | 
2 files changed, 140 insertions, 74 deletions
@@ -1,3 +1,16 @@ +2006-08-04  Andy Wingo  <wingo@pobox.com> + +	* ext/ladspa/gstsignalprocessor.c (gst_signal_processor_setcaps) +	(gst_signal_processor_prepare) +	(gst_signal_processor_update_inputs) +	(gst_signal_processor_process, gst_signal_processor_pen_buffer) +	(gst_signal_processor_flush) +	(gst_signal_processor_sink_activate_push) +	(gst_signal_processor_src_activate_pull) +	(gst_signal_processor_change_state): Remove the last of the code +	that assumes that we process whole buffers at a time. Fix some +	debugging. Seems to work now in some cases. +  2006-08-01  Andy Wingo  <wingo@pobox.com>  	* ext/ladspa/gstsignalprocessor.c (gst_signal_processor_process): diff --git a/ext/ladspa/gstsignalprocessor.c b/ext/ladspa/gstsignalprocessor.c index 884bb1e5..880a94c0 100644 --- a/ext/ladspa/gstsignalprocessor.c +++ b/ext/ladspa/gstsignalprocessor.c @@ -110,6 +110,10 @@ struct _GstSignalProcessorPad    GstBuffer *pen;    guint index; + +  /* these are only used for sink pads */ +  guint samples_avail; +  gfloat *data;  };  static GType @@ -281,15 +285,17 @@ gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps)        GST_WARNING ("got no sample-rate");        goto impossible;      } else { -      GST_DEBUG ("Got rate=%d", sample_rate); +      GST_DEBUG_OBJECT (self, "Got rate=%d", sample_rate);      } -    if (!klass->setup (self, sample_rate)) +    if (!klass->setup (self, sample_rate)) {        goto setup_failed; -    else +    } else {        self->sample_rate = sample_rate; +      gst_caps_replace (&self->caps, caps); +    }    } else { -    GST_DEBUG ("skipping, have caps already"); +    GST_DEBUG_OBJECT (self, "skipping, have caps already");    }    /* FIXME: handle was_active, etc */ @@ -334,90 +340,138 @@ gst_signal_processor_event (GstPad * pad, GstEvent * event)    return ret;  } -static void -gst_signal_processor_process (GstSignalProcessor * self) +static guint +gst_signal_processor_prepare (GstSignalProcessor * self)  { -  GstElement *elem; -  GList *l1, *l2; -  GstSignalProcessorClass *klass; -  guint nframes = G_MAXUINT; +  GstElement *elem = (GstElement *) self; +  GList *sinks, *srcs; +  guint samples_avail = G_MAXUINT; + +  /* first, assign audio_in pointers, and determine the number of samples that +   * we can process */ +  for (sinks = elem->sinkpads; sinks; sinks = sinks->next) { +    GstSignalProcessorPad *sinkpad; + +    sinkpad = (GstSignalProcessorPad *) sinks->data; +    g_assert (sinkpad->samples_avail > 0); +    samples_avail = MIN (samples_avail, sinkpad->samples_avail); +    self->audio_in[sinkpad->index] = sinkpad->data; +  } -  g_return_if_fail (self->pending_in == 0); -  g_return_if_fail (self->pending_out == 0); +  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; +  } -  elem = GST_ELEMENT (self); +  /* 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. */ +  sinks = elem->sinkpads; +  srcs = elem->srcpads; +  while (sinks && srcs) { +    GstSignalProcessorPad *sinkpad, *srcpad; -  /* arrange the output buffers */ -  for (l1 = elem->sinkpads, l2 = elem->srcpads; l1 || l2; -      l1 = l1 ? l1->next : NULL, l2 = l2 ? l2->next : NULL) { -    GstSignalProcessorPad *srcpad, *sinkpad; +    sinkpad = (GstSignalProcessorPad *) sinks->data; +    srcpad = (GstSignalProcessorPad *) srcs->data; -    if (l1) { -      GstSignalProcessorPad *tmp = (GstSignalProcessorPad *) l1->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++; -      nframes = MIN (nframes, GST_BUFFER_SIZE (tmp->pen) / sizeof (gfloat)); +      srcs = srcs->next;      } -    if (!l2) { -      /* the output buffers have been covered, yay -- just keep looping to check -         available frames */ -    } else if (!l1) { -      /* need to alloc some output buffers */ -      for (; l2; l2 = l2->next) { -        GstFlowReturn ret; - -        srcpad = (GstSignalProcessorPad *) l2->data; - -        ret = -            gst_pad_alloc_buffer_and_set_caps (GST_PAD (srcpad), -1, -            nframes, GST_PAD_CAPS (srcpad), &srcpad->pen); - -        if (ret != GST_FLOW_OK) { -          self->state = ret; -          goto flow_error; -        } else { -          self->audio_out[srcpad->index] = -              (gfloat *) GST_BUFFER_DATA (srcpad->pen); -          self->pending_out++; -        } -      } - -      /* the for condition should cut out because of this, but I assert to be -         clear */ -      g_assert (l2 == NULL); -    } else { -      /* copy input to output */ -      sinkpad = (GstSignalProcessorPad *) l1->data; -      srcpad = (GstSignalProcessorPad *) l2->data; +    sinks = sinks->next; +  } -      srcpad->pen = sinkpad->pen; -      sinkpad->pen = NULL; +  /* now allocate for any remaining outputs */ +  while (srcs) { +    GstSignalProcessorPad *srcpad; +    GstFlowReturn ret; + +    srcpad = (GstSignalProcessorPad *) srcs->data; + +    ret = +        gst_pad_alloc_buffer_and_set_caps (GST_PAD (srcpad), -1, +        samples_avail, GST_PAD_CAPS (srcpad), &srcpad->pen); + +    if (ret != GST_FLOW_OK) { +      self->state = ret; +      return 0; +    } else {        self->audio_out[srcpad->index] = (gfloat *) GST_BUFFER_DATA (srcpad->pen);        self->pending_out++;      } -  } -  /* will fail in the ladspa src case, need to check that :-/ */ -  g_assert (nframes < G_MAXUINT); - -  klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); +    srcs = srcs->next; +  } -  GST_INFO_OBJECT (self, "process(%u)", nframes); +  return samples_avail; +} -  klass->process (self, nframes); +static void +gst_signal_processor_update_inputs (GstSignalProcessor * self, guint nprocessed) +{ +  GstElement *elem = (GstElement *) self; +  GList *sinks; -  /* reset */ -  self->pending_in = klass->num_audio_in; +  for (sinks = elem->sinkpads; sinks; sinks = sinks->next) { +    GstSignalProcessorPad *sinkpad; -  /* free unneeded input buffers */ -  for (l1 = elem->sinkpads; l1; l1 = l1->next) { -    GstSignalProcessorPad *sinkpad = (GstSignalProcessorPad *) l1->data; +    sinkpad = (GstSignalProcessorPad *) sinks->data; +    g_assert (sinkpad->samples_avail >= nprocessed); -    if (sinkpad->pen) { +    if (sinkpad->pen && sinkpad->samples_avail == nprocessed) { +      /* used up this buffer, unpen */        gst_buffer_unref (sinkpad->pen);        sinkpad->pen = NULL;      } + +    if (!sinkpad->pen) { +      /* this buffer was used up */ +      self->pending_in++; +      sinkpad->data = NULL; +      sinkpad->samples_avail = 0; +    } else { +      /* advance ->data pointers and decrement ->samples_avail, unreffing buffer +         if no samples are left */ +      sinkpad->samples_avail -= nprocessed; +      sinkpad->data += nprocessed;      /* gfloat* arithmetic */ +    }    } +} + +static void +gst_signal_processor_process (GstSignalProcessor * self) +{ +  GstElement *elem; +  GstSignalProcessorClass *klass; +  guint nframes; + +  g_return_if_fail (self->pending_in == 0); +  g_return_if_fail (self->pending_out == 0); + +  elem = GST_ELEMENT (self); + +  nframes = gst_signal_processor_prepare (self); +  if (G_UNLIKELY (nframes == 0)) +    goto flow_error; + +  klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + +  GST_LOG_OBJECT (self, "process(%u)", nframes); + +  klass->process (self, nframes); + +  gst_signal_processor_update_inputs (self, nframes); + +  return;  flow_error:    { @@ -442,15 +496,12 @@ gst_signal_processor_pen_buffer (GstSignalProcessor * self, GstPad * pad,    /* keep the reference */    spad->pen = buffer; -  self->audio_in[spad->index] = (gfloat *) GST_BUFFER_DATA (buffer); +  spad->data = (gfloat *) GST_BUFFER_DATA (buffer); +  spad->samples_avail = GST_BUFFER_SIZE (buffer) / sizeof (float);    g_assert (self->pending_in != 0);    self->pending_in--; - -  if (self->pending_in == 0) { -    gst_signal_processor_process (self); -  }  }  static void @@ -466,6 +517,8 @@ gst_signal_processor_flush (GstSignalProcessor * self)      if (spad->pen) {        gst_buffer_unref (spad->pen);        spad->pen = NULL; +      spad->data = NULL; +      spad->samples_avail = 0;      }    }  } @@ -666,7 +719,7 @@ gst_signal_processor_sink_activate_push (GstPad * pad, gboolean active)      }    } -  GST_DEBUG ("result : %d", TRUE); +  GST_DEBUG_OBJECT (self, "result : %d", result);    gst_object_unref (self); @@ -714,7 +767,7 @@ gst_signal_processor_src_activate_pull (GstPad * pad, gboolean active)      }    } -  GST_DEBUG ("result : %d", TRUE); +  GST_DEBUG_OBJECT ("result : %d", result);    gst_object_unref (self); @@ -766,7 +819,7 @@ gst_signal_processor_change_state (GstElement * element,    /* ERRORS */  failure:    { -    GST_DEBUG ("parent failed state change"); +    GST_DEBUG_OBJECT (element, "parent failed state change");      return result;    }  }  | 
