+2005-09-10 Jan Schmidt <thaytan@mad.scientist.com>
+
+ * check/gst-libs/controller.c:
+ Header include fix.
+ * gst/base/gstbasetransform.c:
+ (gst_base_transform_default_prepare_buf),
+ (gst_base_transform_handle_buffer):
+ * gst/base/gstbasetransform.h:
+ Some more basetransform changes and fixes to enable sub-classes
+ that modify buffer metadata only.
+ * gst/elements/gstcapsfilter.c: (gst_capsfilter_class_init),
+ (gst_capsfilter_init), (gst_capsfilter_transform_ip),
+ (gst_capsfilter_prepare_buf):
+ If the output pad has fixed allowed caps and input buffers
+ don't have any, set the fixed caps on outgoing buffers.
+
2005-09-09 Jan Schmidt <thaytan@mad.scientist.com>
* check/elements/identity.c: (GST_START_TEST):
Make the error a little clearer when the test fails because
#include "config.h"
#include <gst/check/gstcheck.h>
-#include <gst/controller/gst-controller.h>
+#include <gst/controller/gstcontroller.h>
/* LOCAL TEST ELEMENT */
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
/* See if we want to prepare the buffer for in place output */
- if (GST_BUFFER_SIZE (input) == size && bclass->transform_ip) {
- if (gst_buffer_is_writable (input) && (*buf == NULL)) {
+ if (*buf == NULL && GST_BUFFER_SIZE (input) == size && bclass->transform_ip) {
+ if (gst_buffer_is_writable (input)) {
/* Input buffer is already writable, just ref and return it */
*buf = input;
gst_buffer_ref (input);
* buffer flags */
if (*buf != input && GST_MINI_OBJECT_REFCOUNT_VALUE (*buf) == 1) {
+ if (copy_inbuf && gst_buffer_is_writable (*buf))
+ memcpy (GST_BUFFER_DATA (*buf), GST_BUFFER_DATA (input), size);
+
gst_buffer_stamp (*buf, input);
GST_BUFFER_FLAGS (*buf) |= GST_BUFFER_FLAGS (input) &
(GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
GST_BUFFER_FLAG_DELTA_UNIT);
}
- if (copy_inbuf && gst_buffer_is_writable (*buf))
- memcpy (GST_BUFFER_DATA (*buf), GST_BUFFER_DATA (input), size);
-
return ret;
}
GST_LOG_OBJECT (trans, "handling buffer %p of size %d and offset NONE",
inbuf, GST_BUFFER_SIZE (inbuf));
- if (!trans->negotiated && !trans->passthrough)
+ /* Don't allow buffer handling before negotiation, except in passthrough mode
+ * or if the class doesn't implement a set_caps function (in which case it doesn't
+ * care about caps)
+ */
+ if (!trans->negotiated && !trans->passthrough && (bclass->set_caps != NULL))
goto not_negotiated;
if (trans->passthrough) {
}
want_in_place = (bclass->transform_ip != NULL) && trans->always_in_place;
+ *outbuf = NULL;
if (want_in_place) {
/* If want_in_place is TRUE, we may need to prepare a new output buffer
gboolean passthrough;
gboolean always_in_place;
- /* Set if caps on each pad are equal */
- gboolean have_same_caps;
-
GstCaps *cache_caps1;
guint cache_caps1_size;
GstCaps *cache_caps2;
gint64 segment_stop;
gint64 segment_base;
+ /* FIXME: When adjusting the padding, move this to a nice place in the structure */
+ /* Set if caps on each pad are equal */
+ gboolean have_same_caps;
+
/*< private >*/
- gpointer _gst_reserved[GST_PADDING];
+ gpointer _gst_reserved[GST_PADDING - 1];
};
/**
GstPadDirection direction, GstCaps * caps);
static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
GstBuffer * buf);
-
+static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans,
+ GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
static void
gst_capsfilter_base_init (gpointer g_class)
trans_class = (GstBaseTransformClass *) klass;
trans_class->transform_caps = gst_capsfilter_transform_caps;
trans_class->transform_ip = gst_capsfilter_transform_ip;
+ trans_class->prepare_output_buffer = gst_capsfilter_prepare_buf;
}
static void
gst_capsfilter_init (GstCapsFilter * filter, GstCapsFilterClass * g_class)
{
- gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE);
filter->filter_caps = gst_caps_new_any ();
}
static GstFlowReturn
gst_capsfilter_transform_ip (GstBaseTransform * base, GstBuffer * buf)
{
- /* Ensure that outgoing buffers have caps if we can, so that pipelines
- * like:
- * gst-launch filesrc location=rawsamples.raw !
- * audio/x-raw-int,width=16,depth=16,rate=48000,channels=2,
- * endianness=4321,signed='(boolean)'true ! alsasink
- * will work.
- */
- if (GST_BUFFER_CAPS (buf) == NULL) {
+ /* No actual work here. It's all done in the prepare output buffer
+ * func. */
+ return GST_FLOW_OK;
+}
+
+/* Output buffer preparation... if the buffer has no caps, and
+ * our allowed output caps is fixed, then give the caps to the
+ * buffer.
+ * This ensures that outgoing buffers have caps if we can, so
+ * that pipelines like:
+ * gst-launch filesrc location=rawsamples.raw !
+ * audio/x-raw-int,width=16,depth=16,rate=48000,channels=2,
+ * endianness=4321,signed='(boolean)'true ! alsasink
+ * will work.
+ */
+static GstFlowReturn
+gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
+ gint size, GstCaps * caps, GstBuffer ** buf)
+{
+ if (GST_BUFFER_CAPS (input) != NULL) {
+ /* Output buffer already has caps */
+ GST_DEBUG_OBJECT (trans, "Input buffer already has caps");
+ gst_buffer_ref (input);
+ *buf = input;
+ } else {
+ /* Buffer has no caps. See if the output pad only supports fixed caps */
+ GstCaps *out_caps;
+
+ if (GST_PAD_CAPS (trans->srcpad) != NULL) {
+ gst_caps_ref (GST_PAD_CAPS (trans->srcpad));
+ out_caps = GST_PAD_CAPS (trans->srcpad);
+ } else {
+ out_caps = gst_pad_get_allowed_caps (trans->srcpad);
+ g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR);
+ }
+
+ if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) {
+ GST_DEBUG_OBJECT (trans, "Have fixed output caps %"
+ GST_PTR_FORMAT " to apply to buffer with no caps", out_caps);
+ if (gst_buffer_is_writable (input)) {
+ gst_buffer_ref (input);
+ *buf = input;
+ } else {
+ GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps");
+ *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input));
+ }
+ GST_BUFFER_CAPS (input) = out_caps;
+
+ if (GST_PAD_CAPS (trans->srcpad) == NULL)
+ gst_pad_set_caps (trans->srcpad, out_caps);
+ } else {
+ gst_caps_unref (out_caps);
+ }
}
- return GST_FLOW_OK;
+ return GST_BASE_TRANSFORM_CLASS (parent_class)->
+ prepare_output_buffer (trans, input, size, caps, buf);
}
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
/* See if we want to prepare the buffer for in place output */
- if (GST_BUFFER_SIZE (input) == size && bclass->transform_ip) {
- if (gst_buffer_is_writable (input) && (*buf == NULL)) {
+ if (*buf == NULL && GST_BUFFER_SIZE (input) == size && bclass->transform_ip) {
+ if (gst_buffer_is_writable (input)) {
/* Input buffer is already writable, just ref and return it */
*buf = input;
gst_buffer_ref (input);
* buffer flags */
if (*buf != input && GST_MINI_OBJECT_REFCOUNT_VALUE (*buf) == 1) {
+ if (copy_inbuf && gst_buffer_is_writable (*buf))
+ memcpy (GST_BUFFER_DATA (*buf), GST_BUFFER_DATA (input), size);
+
gst_buffer_stamp (*buf, input);
GST_BUFFER_FLAGS (*buf) |= GST_BUFFER_FLAGS (input) &
(GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
GST_BUFFER_FLAG_DELTA_UNIT);
}
- if (copy_inbuf && gst_buffer_is_writable (*buf))
- memcpy (GST_BUFFER_DATA (*buf), GST_BUFFER_DATA (input), size);
-
return ret;
}
GST_LOG_OBJECT (trans, "handling buffer %p of size %d and offset NONE",
inbuf, GST_BUFFER_SIZE (inbuf));
- if (!trans->negotiated && !trans->passthrough)
+ /* Don't allow buffer handling before negotiation, except in passthrough mode
+ * or if the class doesn't implement a set_caps function (in which case it doesn't
+ * care about caps)
+ */
+ if (!trans->negotiated && !trans->passthrough && (bclass->set_caps != NULL))
goto not_negotiated;
if (trans->passthrough) {
}
want_in_place = (bclass->transform_ip != NULL) && trans->always_in_place;
+ *outbuf = NULL;
if (want_in_place) {
/* If want_in_place is TRUE, we may need to prepare a new output buffer
gboolean passthrough;
gboolean always_in_place;
- /* Set if caps on each pad are equal */
- gboolean have_same_caps;
-
GstCaps *cache_caps1;
guint cache_caps1_size;
GstCaps *cache_caps2;
gint64 segment_stop;
gint64 segment_base;
+ /* FIXME: When adjusting the padding, move this to a nice place in the structure */
+ /* Set if caps on each pad are equal */
+ gboolean have_same_caps;
+
/*< private >*/
- gpointer _gst_reserved[GST_PADDING];
+ gpointer _gst_reserved[GST_PADDING - 1];
};
/**
GstPadDirection direction, GstCaps * caps);
static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
GstBuffer * buf);
-
+static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans,
+ GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
static void
gst_capsfilter_base_init (gpointer g_class)
trans_class = (GstBaseTransformClass *) klass;
trans_class->transform_caps = gst_capsfilter_transform_caps;
trans_class->transform_ip = gst_capsfilter_transform_ip;
+ trans_class->prepare_output_buffer = gst_capsfilter_prepare_buf;
}
static void
gst_capsfilter_init (GstCapsFilter * filter, GstCapsFilterClass * g_class)
{
- gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE);
filter->filter_caps = gst_caps_new_any ();
}
static GstFlowReturn
gst_capsfilter_transform_ip (GstBaseTransform * base, GstBuffer * buf)
{
- /* Ensure that outgoing buffers have caps if we can, so that pipelines
- * like:
- * gst-launch filesrc location=rawsamples.raw !
- * audio/x-raw-int,width=16,depth=16,rate=48000,channels=2,
- * endianness=4321,signed='(boolean)'true ! alsasink
- * will work.
- */
- if (GST_BUFFER_CAPS (buf) == NULL) {
+ /* No actual work here. It's all done in the prepare output buffer
+ * func. */
+ return GST_FLOW_OK;
+}
+
+/* Output buffer preparation... if the buffer has no caps, and
+ * our allowed output caps is fixed, then give the caps to the
+ * buffer.
+ * This ensures that outgoing buffers have caps if we can, so
+ * that pipelines like:
+ * gst-launch filesrc location=rawsamples.raw !
+ * audio/x-raw-int,width=16,depth=16,rate=48000,channels=2,
+ * endianness=4321,signed='(boolean)'true ! alsasink
+ * will work.
+ */
+static GstFlowReturn
+gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
+ gint size, GstCaps * caps, GstBuffer ** buf)
+{
+ if (GST_BUFFER_CAPS (input) != NULL) {
+ /* Output buffer already has caps */
+ GST_DEBUG_OBJECT (trans, "Input buffer already has caps");
+ gst_buffer_ref (input);
+ *buf = input;
+ } else {
+ /* Buffer has no caps. See if the output pad only supports fixed caps */
+ GstCaps *out_caps;
+
+ if (GST_PAD_CAPS (trans->srcpad) != NULL) {
+ gst_caps_ref (GST_PAD_CAPS (trans->srcpad));
+ out_caps = GST_PAD_CAPS (trans->srcpad);
+ } else {
+ out_caps = gst_pad_get_allowed_caps (trans->srcpad);
+ g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR);
+ }
+
+ if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) {
+ GST_DEBUG_OBJECT (trans, "Have fixed output caps %"
+ GST_PTR_FORMAT " to apply to buffer with no caps", out_caps);
+ if (gst_buffer_is_writable (input)) {
+ gst_buffer_ref (input);
+ *buf = input;
+ } else {
+ GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps");
+ *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input));
+ }
+ GST_BUFFER_CAPS (input) = out_caps;
+
+ if (GST_PAD_CAPS (trans->srcpad) == NULL)
+ gst_pad_set_caps (trans->srcpad, out_caps);
+ } else {
+ gst_caps_unref (out_caps);
+ }
}
- return GST_FLOW_OK;
+ return GST_BASE_TRANSFORM_CLASS (parent_class)->
+ prepare_output_buffer (trans, input, size, caps, buf);
}
#include "config.h"
#include <gst/check/gstcheck.h>
-#include <gst/controller/gst-controller.h>
+#include <gst/controller/gstcontroller.h>
/* LOCAL TEST ELEMENT */