ext/ladspa/gstsignalprocessor.h: Add infrastructure for storing whether a processor can work in place or not, and for...

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.
This commit is contained in:
Andy Wingo 2006-08-04 11:38:54 +00:00
parent 71cad18c5e
commit 9bf2b5e3db
3 changed files with 161 additions and 37 deletions

View 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; klass->descriptor = desc;
} }

View file

@ -236,6 +236,8 @@ gst_signal_processor_init (GstSignalProcessor * self,
templates = templates->next; templates = templates->next;
} }
self->state = GST_SIGNAL_PROCESSOR_STATE_NULL;
self->audio_in = g_new0 (gfloat *, klass->num_audio_in); self->audio_in = g_new0 (gfloat *, klass->num_audio_in);
self->control_in = g_new0 (gfloat, klass->num_control_in); self->control_in = g_new0 (gfloat, klass->num_control_in);
self->audio_out = g_new0 (gfloat *, klass->num_audio_out); 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); 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 static gboolean
gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps) gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps)
{ {
GstSignalProcessor *self; GstSignalProcessor *self;
GstSignalProcessorClass *klass;
self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); 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 /* the whole processor has one caps; if the sample rate changes, let subclass
implementations know */ implementations know */
@ -288,8 +375,10 @@ gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps)
GST_DEBUG_OBJECT (self, "Got rate=%d", sample_rate); GST_DEBUG_OBJECT (self, "Got rate=%d", sample_rate);
} }
if (!klass->setup (self, sample_rate)) { if (!gst_signal_processor_setup (self, sample_rate)) {
goto setup_failed; goto start_failed;
} else if (!gst_signal_processor_start (self)) {
goto start_failed;
} else { } else {
self->sample_rate = sample_rate; self->sample_rate = sample_rate;
gst_caps_replace (&self->caps, caps); gst_caps_replace (&self->caps, caps);
@ -304,9 +393,8 @@ gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps)
return TRUE; return TRUE;
setup_failed: start_failed:
{ {
GST_INFO_OBJECT (self, "setup() failed");
gst_object_unref (self); gst_object_unref (self);
return FALSE; return FALSE;
} }
@ -344,9 +432,12 @@ static guint
gst_signal_processor_prepare (GstSignalProcessor * self) gst_signal_processor_prepare (GstSignalProcessor * self)
{ {
GstElement *elem = (GstElement *) self; GstElement *elem = (GstElement *) self;
GstSignalProcessorClass *klass;
GList *sinks, *srcs; GList *sinks, *srcs;
guint samples_avail = G_MAXUINT; guint samples_avail = G_MAXUINT;
klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
/* first, assign audio_in pointers, and determine the number of samples that /* first, assign audio_in pointers, and determine the number of samples that
* we can process */ * we can process */
for (sinks = elem->sinkpads; sinks; sinks = sinks->next) { 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. */ is the exact size of the number of samples we are processing. */
sinks = elem->sinkpads; sinks = elem->sinkpads;
srcs = elem->srcpads; srcs = elem->srcpads;
while (sinks && srcs) { if (GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE (klass)) {
GstSignalProcessorPad *sinkpad, *srcpad; while (sinks && srcs) {
GstSignalProcessorPad *sinkpad, *srcpad;
sinkpad = (GstSignalProcessorPad *) sinks->data; sinkpad = (GstSignalProcessorPad *) sinks->data;
srcpad = (GstSignalProcessorPad *) srcs->data; srcpad = (GstSignalProcessorPad *) srcs->data;
if (GST_BUFFER_SIZE (sinkpad->pen) == samples_avail * sizeof (gfloat)) { if (GST_BUFFER_SIZE (sinkpad->pen) == samples_avail * sizeof (gfloat)) {
/* reusable, yay */ /* reusable, yay */
g_assert (sinkpad->samples_avail == samples_avail); g_assert (sinkpad->samples_avail == samples_avail);
srcpad->pen = sinkpad->pen; srcpad->pen = sinkpad->pen;
sinkpad->pen = NULL; sinkpad->pen = NULL;
self->audio_out[srcpad->index] = sinkpad->data; self->audio_out[srcpad->index] = sinkpad->data;
self->pending_out++; self->pending_out++;
srcs = srcs->next; srcs = srcs->next;
}
sinks = sinks->next;
} }
sinks = sinks->next;
} }
/* now allocate for any remaining outputs */ /* now allocate for any remaining outputs */
@ -399,10 +492,10 @@ gst_signal_processor_prepare (GstSignalProcessor * self)
ret = ret =
gst_pad_alloc_buffer_and_set_caps (GST_PAD (srcpad), -1, 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) { if (ret != GST_FLOW_OK) {
self->state = ret; self->flow_state = ret;
return 0; return 0;
} else { } else {
self->audio_out[srcpad->index] = (gfloat *) GST_BUFFER_DATA (srcpad->pen); self->audio_out[srcpad->index] = (gfloat *) GST_BUFFER_DATA (srcpad->pen);
@ -476,7 +569,7 @@ gst_signal_processor_process (GstSignalProcessor * self)
flow_error: flow_error:
{ {
GST_WARNING ("gst_pad_alloc_buffer_and_set_caps() returned %d", GST_WARNING ("gst_pad_alloc_buffer_and_set_caps() returned %d",
self->state); self->flow_state);
return; 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); ret = gst_pad_pull_range (GST_PAD (spad), -1, nframes, &buf);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {
self->state = ret; self->flow_state = ret;
gst_signal_processor_flush (self); gst_signal_processor_flush (self);
return; return;
} else if (!buf) { } else if (!buf) {
g_critical ("Pull failed to make a buffer!"); g_critical ("Pull failed to make a buffer!");
self->state = GST_FLOW_ERROR; self->flow_state = GST_FLOW_ERROR;
return; return;
} else { } else {
gst_signal_processor_pen_buffer (self, GST_PAD (spad), buf); 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) { if (self->pending_in != 0) {
g_critical ("Something wierd happened..."); g_critical ("Something wierd happened...");
self->state = GST_FLOW_ERROR; self->flow_state = GST_FLOW_ERROR;
} else { } else {
gst_signal_processor_process (self); gst_signal_processor_process (self);
} }
@ -587,7 +680,7 @@ gst_signal_processor_getrange (GstPad * pad, guint64 offset,
if (!spad->pen) { if (!spad->pen) {
/* this is an error condition */ /* this is an error condition */
*buffer = NULL; *buffer = NULL;
ret = self->state; ret = self->flow_state;
} else { } else {
*buffer = spad->pen; *buffer = spad->pen;
spad->pen = NULL; spad->pen = NULL;
@ -625,7 +718,7 @@ gst_signal_processor_do_pushes (GstSignalProcessor * self)
ret = gst_pad_push (GST_PAD (spad), spad->pen); ret = gst_pad_push (GST_PAD (spad), spad->pen);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {
self->state = ret; self->flow_state = ret;
gst_signal_processor_flush (self); gst_signal_processor_flush (self);
return; return;
} else { } else {
@ -637,7 +730,7 @@ gst_signal_processor_do_pushes (GstSignalProcessor * self)
if (self->pending_out != 0) { if (self->pending_out != 0) {
g_critical ("Something wierd happened..."); 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); gst_object_unref (self);
return self->state; return self->flow_state;
} }
static void static void
@ -778,13 +871,10 @@ static GstStateChangeReturn
gst_signal_processor_change_state (GstElement * element, gst_signal_processor_change_state (GstElement * element,
GstStateChange transition) GstStateChange transition)
{ {
/* GstSignalProcessor *self; GstSignalProcessor *self;
GstSignalProcessorClass *klass; */
GstStateChangeReturn result; GstStateChangeReturn result;
/* self = GST_SIGNAL_PROCESSOR (element); self = GST_SIGNAL_PROCESSOR (element);
klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); */
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY: 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: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
if (GST_SIGNAL_PROCESSOR_IS_RUNNING (self))
gst_signal_processor_stop (self);
break; break;
case GST_STATE_CHANGE_READY_TO_NULL: 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; break;
default: default:
break; break;

View file

@ -29,6 +29,26 @@
G_BEGIN_DECLS 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_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(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)) #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(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_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 _GstSignalProcessor GstSignalProcessor;
typedef struct _GstSignalProcessorClass GstSignalProcessorClass; typedef struct _GstSignalProcessorClass GstSignalProcessorClass;
@ -49,7 +73,9 @@ struct _GstSignalProcessor {
guint sample_rate; guint sample_rate;
GstFlowReturn state; GstSignalProcessorState state;
GstFlowReturn flow_state;
GstActivateMode mode; GstActivateMode mode;
@ -71,6 +97,8 @@ struct _GstSignalProcessorClass {
guint num_control_out; guint num_control_out;
guint num_audio_out; guint num_audio_out;
guint flags;
/* virtual methods for subclasses */ /* virtual methods for subclasses */
gboolean (*setup) (GstSignalProcessor *self, guint sample_rate); gboolean (*setup) (GstSignalProcessor *self, guint sample_rate);