+2005-08-04 Andy Wingo <wingo@pobox.com>
+
+ * gst/elements/gstcapsfilter.c: Reimplement using basetransform,
+ fixes buffer_alloc proxying among other things.
+
+ * gst/base/gstbasetransform.c:
+ * gst/base/gstbasetransform.h:
+ Revert patch to gstbasetransform from 7-28 removing
+ delay_configure.
+
+ * gst/base/gstbasetransform.h (GstBaseTransformClass.get_size):
+ * gst/base/gstbasetransform.c (gst_base_transform_get_size):
+ Semantics changed, should return not the size of the output buffer
+ but the byte size of a buffer with a given caps.
+
+ * gst/base/gstbasetransform.c (gst_base_transform_getcaps): Better
+ debug object.
+ (gst_base_transform_configure_caps): Don't set out_size here: (in,
+ out) are not the pad caps until setcaps finishes.
+ (gst_base_transform_buffer_alloc): Proxy the buffer_alloc for the
+ not-in-place case as well. Deal with changing from in-place to
+ not-in-place within calling pad_alloc_buffer. Still a bit
+ concerned about the overhead here...
+
+2005-08-03 Andy Wingo <wingo@pobox.com>
+
+ * gst/base/gstbasetransform.c (gst_base_transform_setcaps): Not
+ fixating is an error.
+
2005-08-04 Edward Hervey <edward@fluendo.com>
* gst/base/gstadapter.h:
gboolean active);
static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
gboolean active);
-static guint gst_base_transform_get_size (GstBaseTransform * trans);
+static guint gst_base_transform_get_size (GstBaseTransform * trans,
+ GstCaps * caps);
static GstElementStateReturn gst_base_transform_change_state (GstElement *
element);
GstCaps *temp;
const GstCaps *templ;
- GST_DEBUG_OBJECT (trans, "peer caps %" GST_PTR_FORMAT, caps);
+ GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, caps);
/* filtered against our padtemplate */
templ = gst_pad_get_pad_template_caps (otherpad);
- GST_DEBUG_OBJECT (trans, "our template %" GST_PTR_FORMAT, templ);
+ GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ);
temp = gst_caps_intersect (caps, templ);
- GST_DEBUG_OBJECT (trans, "intersected %" GST_PTR_FORMAT, temp);
+ GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
gst_caps_unref (caps);
/* then see what we can tranform this to */
caps = gst_base_transform_transform_caps (trans, otherpad, temp);
- GST_DEBUG_OBJECT (trans, "transformed %" GST_PTR_FORMAT, caps);
+ GST_DEBUG_OBJECT (pad, "transformed %" GST_PTR_FORMAT, caps);
gst_caps_unref (temp);
if (caps == NULL)
goto done;
/* and filter against the template again */
templ = gst_pad_get_pad_template_caps (pad);
- GST_DEBUG_OBJECT (trans, "our template %" GST_PTR_FORMAT, templ);
+ GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ);
temp = gst_caps_intersect (caps, templ);
- GST_DEBUG_OBJECT (trans, "intersected %" GST_PTR_FORMAT, temp);
+ GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
gst_caps_unref (caps);
/* this is what we can do */
caps = temp;
ret = klass->set_caps (trans, in, out);
}
- /* if all goes well, get the size of the output buffer */
- if (ret) {
- trans->out_size = gst_base_transform_get_size (trans);
- GST_DEBUG_OBJECT (trans, "output buffer size %d", trans->out_size);
- }
return ret;
}
GST_DEBUG_OBJECT (trans, "in_place: %d", trans->in_place);
/* see if we have to configure the element now */
- if (pad == trans->sinkpad)
- ret = gst_base_transform_configure_caps (trans, caps, othercaps);
- else
- ret = gst_base_transform_configure_caps (trans, othercaps, caps);
+ if (!trans->delay_configure) {
+ if (pad == trans->sinkpad)
+ ret = gst_base_transform_configure_caps (trans, caps, othercaps);
+ else
+ ret = gst_base_transform_configure_caps (trans, othercaps, caps);
+ }
done:
if (otherpeer)
}
could_not_fixate:
{
- GST_DEBUG_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);
+ GST_ERROR_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);
ret = FALSE;
goto done;
}
}
static guint
-gst_base_transform_get_size (GstBaseTransform * trans)
+gst_base_transform_get_size (GstBaseTransform * trans, GstCaps * caps)
{
guint res = -1;
GstBaseTransformClass *bclass;
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
if (bclass->get_size) {
- res = bclass->get_size (trans);
- GST_DEBUG_OBJECT (trans, "get size function returned %d", res);
+ res = bclass->get_size (trans, caps);
+ GST_DEBUG_OBJECT (trans, "get size(%p) returned %d", caps, res);
}
return res;
{
GstBaseTransform *trans;
GstFlowReturn res;
+ guint got_size;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+ *buf = NULL;
+
if (trans->in_place) {
- /* we can only proxy the bufferpool if we do in_place transforms */
+ /* request a buffer with the same caps */
res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
} else {
- /* else let the default alloc function allocate a buffer */
- *buf = NULL;
+ /* if we are configured, request a buffer with the src caps */
+ GstCaps *srccaps = gst_pad_get_negotiated_caps (trans->srcpad);
+
+ if (!srccaps)
+ goto not_configured;
+
+ got_size = gst_base_transform_get_size (trans, srccaps);
+ if (got_size == -1) {
+ gst_caps_unref (srccaps);
+ goto unknown_size;
+ }
+
+ res = gst_pad_alloc_buffer (trans->srcpad, offset, got_size, srccaps, buf);
+ gst_caps_unref (srccaps);
+ }
+
+ if (res == GST_FLOW_OK && !trans->in_place) {
+ /* note that we might have been in place before, but calling the
+ alloc_buffer caused setcaps to switch us out of in_place -- in any case
+ the alloc_buffer served to transmit caps information but we can't use the
+ buffer. fall through and allocate a buffer corresponding to our sink
+ caps, if any */
+ GstCaps *sinkcaps = gst_pad_get_negotiated_caps (trans->sinkpad);
+
+ if (!sinkcaps)
+ goto not_configured;
+
+ got_size = gst_base_transform_get_size (trans, sinkcaps);
+ if (got_size == -1) {
+ gst_caps_unref (sinkcaps);
+ goto unknown_size;
+ }
+
+ *buf = gst_buffer_new_and_alloc (got_size);
+ gst_buffer_set_caps (*buf, sinkcaps);
+ GST_BUFFER_OFFSET (*buf) = offset;
res = GST_FLOW_OK;
+
+ gst_caps_unref (sinkcaps);
}
gst_object_unref (trans);
-
return res;
+
+not_configured:
+ {
+ /* let the default allocator handle it */
+ *buf = NULL;
+ gst_object_unref (trans);
+ return GST_FLOW_OK;
+ }
+unknown_size:
+ {
+ /* let the default allocator handle it */
+ *buf = NULL;
+ gst_object_unref (trans);
+ return GST_FLOW_OK;
+ }
}
/* figure out the output size */
if (trans->out_size == -1) {
/* ask subclass */
- if ((trans->out_size = gst_base_transform_get_size (trans)) == -1)
- /* else we have an error */
+ trans->out_size = gst_base_transform_get_size (trans,
+ GST_PAD_CAPS (trans->srcpad));
+ if (trans->out_size == -1)
+ /* we have an error */
goto no_size;
}
+ /* we cannot reconfigure the element yet as we are still processing
+ * the old buffer. We will therefore delay the reconfiguration of the
+ * element until we have processed this last buffer. */
+ trans->delay_configure = TRUE;
+
/* no in place transform, get buffer, this might renegotiate. */
ret = gst_pad_alloc_buffer (trans->srcpad,
GST_BUFFER_OFFSET (inbuf), trans->out_size,
GST_PAD_CAPS (trans->srcpad), outbuf);
+ trans->delay_configure = FALSE;
+
if (ret != GST_FLOW_OK)
goto no_buffer;
gboolean in_place;
guint out_size;
+ gboolean delay_configure;
};
struct _GstBaseTransformClass {
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
GstCaps *outcaps);
- /* get the size of the output buffer, -1 on error */
- guint (*get_size) (GstBaseTransform *trans);
+ /* get the byte size of a given caps, -1 on error */
+ guint (*get_size) (GstBaseTransform *trans, GstCaps *caps);
/* start and stop processing, ideal for opening/closing the resource */
gboolean (*start) (GstBaseTransform *trans);
* Boston, MA 02111-1307, USA.
*/
-
-#include <stdlib.h>
-
#ifdef HAVE_CONFIG_H
-# include "config.h"
+#include "config.h"
#endif
#include "../gst-i18n-lib.h"
-#include <gst/gstmarshal.h>
#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+
+
+GstElementDetails gst_capsfilter_details = GST_ELEMENT_DETAILS ("CapsFilter",
+ "Generic",
+ "Pass data without modification, limiting formats",
+ "David Schleef <ds@schleef.org>");
#define GST_TYPE_CAPSFILTER \
struct _GstCapsFilter
{
- GstElement element;
-
- GstPad *srcpad;
- GstPad *sinkpad;
+ GstBaseTransform trans;
GstCaps *filter_caps;
};
struct _GstCapsFilterClass
{
- GstElementClass element_class;
-
+ GstBaseTransformClass trans_class;
};
GType gst_capsfilter_get_type (void);
+enum
+{
+ PROP_0,
+ PROP_FILTER_CAPS
+};
+
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
+
GST_DEBUG_CATEGORY_STATIC (gst_capsfilter_debug);
#define GST_CAT_DEFAULT gst_capsfilter_debug
-GstElementDetails gst_capsfilter_details = GST_ELEMENT_DETAILS ("CapsFilter",
- "Generic",
- "Pass data without modification, limiting formats",
- "David Schleef <ds@schleef.org>");
-
-enum
-{
- PROP_0,
- PROP_FILTER_CAPS
-};
-
-
#define _do_init(bla) \
- GST_DEBUG_CATEGORY_INIT (gst_capsfilter_debug, "capsfilter", 0, "capsfilter element");
+ GST_DEBUG_CATEGORY_INIT (gst_capsfilter_debug, "capsfilter", 0, \
+ "capsfilter element");
+
+GST_BOILERPLATE_FULL (GstCapsFilter, gst_capsfilter, GstBaseTransform,
+ GST_TYPE_BASE_TRANSFORM, _do_init);
-GST_BOILERPLATE_FULL (GstCapsFilter, gst_capsfilter, GstElement,
- GST_TYPE_ELEMENT, _do_init);
-static void gst_capsfilter_finalize (GObject * object);
static void gst_capsfilter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_capsfilter_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
+static void gst_capsfilter_dispose (GObject * object);
+static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base,
+ GstPad * pad, GstCaps * caps);
+static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
+ GstBuffer * buf);
-static GstCaps *gst_capsfilter_getcaps (GstPad * pad);
-static GstFlowReturn gst_capsfilter_chain (GstPad * pad, GstBuffer * buf);
static void
gst_capsfilter_base_init (gpointer g_class)
{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- gst_element_class_add_pad_template (gstelement_class,
+ gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&srctemplate));
- gst_element_class_add_pad_template (gstelement_class,
+ gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sinktemplate));
- gst_element_class_set_details (gstelement_class, &gst_capsfilter_details);
-}
-
-static void
-gst_capsfilter_finalize (GObject * object)
-{
- GstCapsFilter *capsfilter;
-
- capsfilter = GST_CAPSFILTER (object);
-
- gst_caps_unref (capsfilter->filter_caps);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ gst_element_class_set_details (element_class, &gst_capsfilter_details);
}
static void
gst_capsfilter_class_init (GstCapsFilterClass * klass)
{
GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
+ GstBaseTransformClass *trans_class;
- gobject_class = G_OBJECT_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_capsfilter_set_property);
- gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_capsfilter_get_property);
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_capsfilter_finalize);
+ gobject_class = (GObjectClass *) klass;
+ gobject_class->set_property = gst_capsfilter_set_property;
+ gobject_class->get_property = gst_capsfilter_get_property;
+ gobject_class->dispose = gst_capsfilter_dispose;
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILTER_CAPS,
g_param_spec_boxed ("filter_caps", _("Filter caps"),
_("Restrict the possible allowed formats"),
GST_TYPE_CAPS, G_PARAM_READWRITE));
-}
-static void
-gst_capsfilter_init (GstCapsFilter * capsfilter)
-{
- gst_element_create_all_pads (GST_ELEMENT (capsfilter));
-
- capsfilter->srcpad = gst_element_get_pad (GST_ELEMENT (capsfilter), "src");
- capsfilter->sinkpad = gst_element_get_pad (GST_ELEMENT (capsfilter), "sink");
-
- gst_pad_set_getcaps_function (capsfilter->srcpad, gst_capsfilter_getcaps);
-
- gst_pad_set_getcaps_function (capsfilter->sinkpad, gst_capsfilter_getcaps);
- gst_pad_set_chain_function (capsfilter->sinkpad, gst_capsfilter_chain);
-
- capsfilter->filter_caps = gst_caps_new_any ();
+ trans_class = (GstBaseTransformClass *) klass;
+ trans_class->transform_caps = gst_capsfilter_transform_caps;
+ trans_class->transform_ip = gst_capsfilter_transform_ip;
}
-static GstCaps *
-gst_capsfilter_getcaps (GstPad * pad)
-{
- GstPad *otherpad;
- GstCapsFilter *capsfilter = GST_CAPSFILTER (GST_OBJECT_PARENT (pad));
- GstCaps *caps;
- GstCaps *icaps;
-
- otherpad = (pad == capsfilter->srcpad) ? capsfilter->sinkpad :
- capsfilter->srcpad;
-
- caps = gst_pad_peer_get_caps (otherpad);
- if (caps == NULL)
- caps = gst_caps_new_any ();
-
- icaps = gst_caps_intersect (caps, capsfilter->filter_caps);
- gst_caps_unref (caps);
-
- return icaps;
-}
-
-static GstFlowReturn
-gst_capsfilter_chain (GstPad * pad, GstBuffer * buf)
+static void
+gst_capsfilter_init (GstCapsFilter * filter)
{
- GstCapsFilter *capsfilter = GST_CAPSFILTER (GST_PAD_PARENT (pad));
-
- gst_pad_push (capsfilter->srcpad, buf);
-
- return GST_FLOW_OK;
+ gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE);
+ filter->filter_caps = gst_caps_new_any ();
}
static void
gst_capsfilter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
- GstCapsFilter *capsfilter;
-
- capsfilter = GST_CAPSFILTER (object);
+ GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
switch (prop_id) {
case PROP_FILTER_CAPS:{
gst_capsfilter_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
- GstCapsFilter *capsfilter;
-
- capsfilter = GST_CAPSFILTER (object);
+ GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
switch (prop_id) {
case PROP_FILTER_CAPS:
break;
}
}
+
+static void
+gst_capsfilter_dispose (GObject * object)
+{
+ GstCapsFilter *filter = GST_CAPSFILTER (object);
+
+ gst_caps_replace (&filter->filter_caps, NULL);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static GstCaps *
+gst_capsfilter_transform_caps (GstBaseTransform * base, GstPad * pad,
+ GstCaps * caps)
+{
+ GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
+ GstCaps *ret;
+
+ ret = gst_caps_intersect (caps, capsfilter->filter_caps);
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_capsfilter_transform_ip (GstBaseTransform * base, GstBuffer * buf)
+{
+ return GST_FLOW_OK;
+}
gboolean active);
static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
gboolean active);
-static guint gst_base_transform_get_size (GstBaseTransform * trans);
+static guint gst_base_transform_get_size (GstBaseTransform * trans,
+ GstCaps * caps);
static GstElementStateReturn gst_base_transform_change_state (GstElement *
element);
GstCaps *temp;
const GstCaps *templ;
- GST_DEBUG_OBJECT (trans, "peer caps %" GST_PTR_FORMAT, caps);
+ GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, caps);
/* filtered against our padtemplate */
templ = gst_pad_get_pad_template_caps (otherpad);
- GST_DEBUG_OBJECT (trans, "our template %" GST_PTR_FORMAT, templ);
+ GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ);
temp = gst_caps_intersect (caps, templ);
- GST_DEBUG_OBJECT (trans, "intersected %" GST_PTR_FORMAT, temp);
+ GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
gst_caps_unref (caps);
/* then see what we can tranform this to */
caps = gst_base_transform_transform_caps (trans, otherpad, temp);
- GST_DEBUG_OBJECT (trans, "transformed %" GST_PTR_FORMAT, caps);
+ GST_DEBUG_OBJECT (pad, "transformed %" GST_PTR_FORMAT, caps);
gst_caps_unref (temp);
if (caps == NULL)
goto done;
/* and filter against the template again */
templ = gst_pad_get_pad_template_caps (pad);
- GST_DEBUG_OBJECT (trans, "our template %" GST_PTR_FORMAT, templ);
+ GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ);
temp = gst_caps_intersect (caps, templ);
- GST_DEBUG_OBJECT (trans, "intersected %" GST_PTR_FORMAT, temp);
+ GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
gst_caps_unref (caps);
/* this is what we can do */
caps = temp;
ret = klass->set_caps (trans, in, out);
}
- /* if all goes well, get the size of the output buffer */
- if (ret) {
- trans->out_size = gst_base_transform_get_size (trans);
- GST_DEBUG_OBJECT (trans, "output buffer size %d", trans->out_size);
- }
return ret;
}
GST_DEBUG_OBJECT (trans, "in_place: %d", trans->in_place);
/* see if we have to configure the element now */
- if (pad == trans->sinkpad)
- ret = gst_base_transform_configure_caps (trans, caps, othercaps);
- else
- ret = gst_base_transform_configure_caps (trans, othercaps, caps);
+ if (!trans->delay_configure) {
+ if (pad == trans->sinkpad)
+ ret = gst_base_transform_configure_caps (trans, caps, othercaps);
+ else
+ ret = gst_base_transform_configure_caps (trans, othercaps, caps);
+ }
done:
if (otherpeer)
}
could_not_fixate:
{
- GST_DEBUG_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);
+ GST_ERROR_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);
ret = FALSE;
goto done;
}
}
static guint
-gst_base_transform_get_size (GstBaseTransform * trans)
+gst_base_transform_get_size (GstBaseTransform * trans, GstCaps * caps)
{
guint res = -1;
GstBaseTransformClass *bclass;
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
if (bclass->get_size) {
- res = bclass->get_size (trans);
- GST_DEBUG_OBJECT (trans, "get size function returned %d", res);
+ res = bclass->get_size (trans, caps);
+ GST_DEBUG_OBJECT (trans, "get size(%p) returned %d", caps, res);
}
return res;
{
GstBaseTransform *trans;
GstFlowReturn res;
+ guint got_size;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+ *buf = NULL;
+
if (trans->in_place) {
- /* we can only proxy the bufferpool if we do in_place transforms */
+ /* request a buffer with the same caps */
res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
} else {
- /* else let the default alloc function allocate a buffer */
- *buf = NULL;
+ /* if we are configured, request a buffer with the src caps */
+ GstCaps *srccaps = gst_pad_get_negotiated_caps (trans->srcpad);
+
+ if (!srccaps)
+ goto not_configured;
+
+ got_size = gst_base_transform_get_size (trans, srccaps);
+ if (got_size == -1) {
+ gst_caps_unref (srccaps);
+ goto unknown_size;
+ }
+
+ res = gst_pad_alloc_buffer (trans->srcpad, offset, got_size, srccaps, buf);
+ gst_caps_unref (srccaps);
+ }
+
+ if (res == GST_FLOW_OK && !trans->in_place) {
+ /* note that we might have been in place before, but calling the
+ alloc_buffer caused setcaps to switch us out of in_place -- in any case
+ the alloc_buffer served to transmit caps information but we can't use the
+ buffer. fall through and allocate a buffer corresponding to our sink
+ caps, if any */
+ GstCaps *sinkcaps = gst_pad_get_negotiated_caps (trans->sinkpad);
+
+ if (!sinkcaps)
+ goto not_configured;
+
+ got_size = gst_base_transform_get_size (trans, sinkcaps);
+ if (got_size == -1) {
+ gst_caps_unref (sinkcaps);
+ goto unknown_size;
+ }
+
+ *buf = gst_buffer_new_and_alloc (got_size);
+ gst_buffer_set_caps (*buf, sinkcaps);
+ GST_BUFFER_OFFSET (*buf) = offset;
res = GST_FLOW_OK;
+
+ gst_caps_unref (sinkcaps);
}
gst_object_unref (trans);
-
return res;
+
+not_configured:
+ {
+ /* let the default allocator handle it */
+ *buf = NULL;
+ gst_object_unref (trans);
+ return GST_FLOW_OK;
+ }
+unknown_size:
+ {
+ /* let the default allocator handle it */
+ *buf = NULL;
+ gst_object_unref (trans);
+ return GST_FLOW_OK;
+ }
}
/* figure out the output size */
if (trans->out_size == -1) {
/* ask subclass */
- if ((trans->out_size = gst_base_transform_get_size (trans)) == -1)
- /* else we have an error */
+ trans->out_size = gst_base_transform_get_size (trans,
+ GST_PAD_CAPS (trans->srcpad));
+ if (trans->out_size == -1)
+ /* we have an error */
goto no_size;
}
+ /* we cannot reconfigure the element yet as we are still processing
+ * the old buffer. We will therefore delay the reconfiguration of the
+ * element until we have processed this last buffer. */
+ trans->delay_configure = TRUE;
+
/* no in place transform, get buffer, this might renegotiate. */
ret = gst_pad_alloc_buffer (trans->srcpad,
GST_BUFFER_OFFSET (inbuf), trans->out_size,
GST_PAD_CAPS (trans->srcpad), outbuf);
+ trans->delay_configure = FALSE;
+
if (ret != GST_FLOW_OK)
goto no_buffer;
gboolean in_place;
guint out_size;
+ gboolean delay_configure;
};
struct _GstBaseTransformClass {
gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps,
GstCaps *outcaps);
- /* get the size of the output buffer, -1 on error */
- guint (*get_size) (GstBaseTransform *trans);
+ /* get the byte size of a given caps, -1 on error */
+ guint (*get_size) (GstBaseTransform *trans, GstCaps *caps);
/* start and stop processing, ideal for opening/closing the resource */
gboolean (*start) (GstBaseTransform *trans);
* Boston, MA 02111-1307, USA.
*/
-
-#include <stdlib.h>
-
#ifdef HAVE_CONFIG_H
-# include "config.h"
+#include "config.h"
#endif
#include "../gst-i18n-lib.h"
-#include <gst/gstmarshal.h>
#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+
+
+GstElementDetails gst_capsfilter_details = GST_ELEMENT_DETAILS ("CapsFilter",
+ "Generic",
+ "Pass data without modification, limiting formats",
+ "David Schleef <ds@schleef.org>");
#define GST_TYPE_CAPSFILTER \
struct _GstCapsFilter
{
- GstElement element;
-
- GstPad *srcpad;
- GstPad *sinkpad;
+ GstBaseTransform trans;
GstCaps *filter_caps;
};
struct _GstCapsFilterClass
{
- GstElementClass element_class;
-
+ GstBaseTransformClass trans_class;
};
GType gst_capsfilter_get_type (void);
+enum
+{
+ PROP_0,
+ PROP_FILTER_CAPS
+};
+
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
+
GST_DEBUG_CATEGORY_STATIC (gst_capsfilter_debug);
#define GST_CAT_DEFAULT gst_capsfilter_debug
-GstElementDetails gst_capsfilter_details = GST_ELEMENT_DETAILS ("CapsFilter",
- "Generic",
- "Pass data without modification, limiting formats",
- "David Schleef <ds@schleef.org>");
-
-enum
-{
- PROP_0,
- PROP_FILTER_CAPS
-};
-
-
#define _do_init(bla) \
- GST_DEBUG_CATEGORY_INIT (gst_capsfilter_debug, "capsfilter", 0, "capsfilter element");
+ GST_DEBUG_CATEGORY_INIT (gst_capsfilter_debug, "capsfilter", 0, \
+ "capsfilter element");
+
+GST_BOILERPLATE_FULL (GstCapsFilter, gst_capsfilter, GstBaseTransform,
+ GST_TYPE_BASE_TRANSFORM, _do_init);
-GST_BOILERPLATE_FULL (GstCapsFilter, gst_capsfilter, GstElement,
- GST_TYPE_ELEMENT, _do_init);
-static void gst_capsfilter_finalize (GObject * object);
static void gst_capsfilter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_capsfilter_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
+static void gst_capsfilter_dispose (GObject * object);
+static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base,
+ GstPad * pad, GstCaps * caps);
+static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
+ GstBuffer * buf);
-static GstCaps *gst_capsfilter_getcaps (GstPad * pad);
-static GstFlowReturn gst_capsfilter_chain (GstPad * pad, GstBuffer * buf);
static void
gst_capsfilter_base_init (gpointer g_class)
{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- gst_element_class_add_pad_template (gstelement_class,
+ gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&srctemplate));
- gst_element_class_add_pad_template (gstelement_class,
+ gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sinktemplate));
- gst_element_class_set_details (gstelement_class, &gst_capsfilter_details);
-}
-
-static void
-gst_capsfilter_finalize (GObject * object)
-{
- GstCapsFilter *capsfilter;
-
- capsfilter = GST_CAPSFILTER (object);
-
- gst_caps_unref (capsfilter->filter_caps);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ gst_element_class_set_details (element_class, &gst_capsfilter_details);
}
static void
gst_capsfilter_class_init (GstCapsFilterClass * klass)
{
GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
+ GstBaseTransformClass *trans_class;
- gobject_class = G_OBJECT_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_capsfilter_set_property);
- gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_capsfilter_get_property);
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_capsfilter_finalize);
+ gobject_class = (GObjectClass *) klass;
+ gobject_class->set_property = gst_capsfilter_set_property;
+ gobject_class->get_property = gst_capsfilter_get_property;
+ gobject_class->dispose = gst_capsfilter_dispose;
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILTER_CAPS,
g_param_spec_boxed ("filter_caps", _("Filter caps"),
_("Restrict the possible allowed formats"),
GST_TYPE_CAPS, G_PARAM_READWRITE));
-}
-static void
-gst_capsfilter_init (GstCapsFilter * capsfilter)
-{
- gst_element_create_all_pads (GST_ELEMENT (capsfilter));
-
- capsfilter->srcpad = gst_element_get_pad (GST_ELEMENT (capsfilter), "src");
- capsfilter->sinkpad = gst_element_get_pad (GST_ELEMENT (capsfilter), "sink");
-
- gst_pad_set_getcaps_function (capsfilter->srcpad, gst_capsfilter_getcaps);
-
- gst_pad_set_getcaps_function (capsfilter->sinkpad, gst_capsfilter_getcaps);
- gst_pad_set_chain_function (capsfilter->sinkpad, gst_capsfilter_chain);
-
- capsfilter->filter_caps = gst_caps_new_any ();
+ trans_class = (GstBaseTransformClass *) klass;
+ trans_class->transform_caps = gst_capsfilter_transform_caps;
+ trans_class->transform_ip = gst_capsfilter_transform_ip;
}
-static GstCaps *
-gst_capsfilter_getcaps (GstPad * pad)
-{
- GstPad *otherpad;
- GstCapsFilter *capsfilter = GST_CAPSFILTER (GST_OBJECT_PARENT (pad));
- GstCaps *caps;
- GstCaps *icaps;
-
- otherpad = (pad == capsfilter->srcpad) ? capsfilter->sinkpad :
- capsfilter->srcpad;
-
- caps = gst_pad_peer_get_caps (otherpad);
- if (caps == NULL)
- caps = gst_caps_new_any ();
-
- icaps = gst_caps_intersect (caps, capsfilter->filter_caps);
- gst_caps_unref (caps);
-
- return icaps;
-}
-
-static GstFlowReturn
-gst_capsfilter_chain (GstPad * pad, GstBuffer * buf)
+static void
+gst_capsfilter_init (GstCapsFilter * filter)
{
- GstCapsFilter *capsfilter = GST_CAPSFILTER (GST_PAD_PARENT (pad));
-
- gst_pad_push (capsfilter->srcpad, buf);
-
- return GST_FLOW_OK;
+ gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE);
+ filter->filter_caps = gst_caps_new_any ();
}
static void
gst_capsfilter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
- GstCapsFilter *capsfilter;
-
- capsfilter = GST_CAPSFILTER (object);
+ GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
switch (prop_id) {
case PROP_FILTER_CAPS:{
gst_capsfilter_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
- GstCapsFilter *capsfilter;
-
- capsfilter = GST_CAPSFILTER (object);
+ GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
switch (prop_id) {
case PROP_FILTER_CAPS:
break;
}
}
+
+static void
+gst_capsfilter_dispose (GObject * object)
+{
+ GstCapsFilter *filter = GST_CAPSFILTER (object);
+
+ gst_caps_replace (&filter->filter_caps, NULL);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static GstCaps *
+gst_capsfilter_transform_caps (GstBaseTransform * base, GstPad * pad,
+ GstCaps * caps)
+{
+ GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
+ GstCaps *ret;
+
+ ret = gst_caps_intersect (caps, capsfilter->filter_caps);
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_capsfilter_transform_ip (GstBaseTransform * base, GstBuffer * buf)
+{
+ return GST_FLOW_OK;
+}