basetransform: move the metadata copy code

Move the metadata copy code to the default prepare_output_buffer implementation.
This commit is contained in:
Wim Taymans 2011-07-21 16:30:07 +02:00
parent 5253a52cb2
commit f8e75ce406

View file

@ -258,14 +258,15 @@ struct _GstBaseTransformPrivate
guint alignment; guint alignment;
}; };
static GstElementClass *parent_class = NULL; static GstElementClass *parent_class = NULL;
static void gst_base_transform_class_init (GstBaseTransformClass * klass); static void gst_base_transform_class_init (GstBaseTransformClass * klass);
static void gst_base_transform_init (GstBaseTransform * trans, static void gst_base_transform_init (GstBaseTransform * trans,
GstBaseTransformClass * klass); GstBaseTransformClass * klass);
static GstFlowReturn gst_base_transform_prepare_output_buffer (GstBaseTransform
* trans, GstBuffer * input, GstBuffer ** buf);
/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init
* method to get to the padtemplates */
GType GType
gst_base_transform_get_type (void) gst_base_transform_get_type (void)
{ {
@ -325,6 +326,9 @@ static gboolean gst_base_transform_setcaps (GstBaseTransform * trans,
static gboolean gst_base_transform_query (GstPad * pad, GstQuery * query); static gboolean gst_base_transform_query (GstPad * pad, GstQuery * query);
static const GstQueryType *gst_base_transform_query_type (GstPad * pad); static const GstQueryType *gst_base_transform_query_type (GstPad * pad);
static GstFlowReturn default_prepare_output_buffer (GstBaseTransform * trans,
GstBuffer * in_buf, GstBuffer ** out_buf);
/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */ /* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
static void static void
@ -369,6 +373,8 @@ gst_base_transform_class_init (GstBaseTransformClass * klass)
klass->src_event = GST_DEBUG_FUNCPTR (gst_base_transform_src_eventfunc); klass->src_event = GST_DEBUG_FUNCPTR (gst_base_transform_src_eventfunc);
klass->accept_caps = klass->accept_caps =
GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps_default); GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps_default);
klass->prepare_output_buffer =
GST_DEBUG_FUNCPTR (default_prepare_output_buffer);
} }
static void static void
@ -1366,10 +1372,18 @@ default_prepare_output_buffer (GstBaseTransform * trans,
priv = trans->priv; priv = trans->priv;
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
/* figure out how to allocate an output buffer */
if (trans->passthrough) { if (trans->passthrough) {
/* passthrough, we will not modify the incomming buffer so we can just
* reuse it */
GST_DEBUG_OBJECT (trans, "passthrough: reusing input buffer"); GST_DEBUG_OBJECT (trans, "passthrough: reusing input buffer");
*out_buf = in_buf; *out_buf = gst_buffer_ref (in_buf);
} else if (priv->pool) { } else {
gboolean copymeta;
guint mask;
/* we can't reuse the input buffer */
if (priv->pool) {
GST_DEBUG_OBJECT (trans, "using pool alloc"); GST_DEBUG_OBJECT (trans, "using pool alloc");
ret = gst_buffer_pool_acquire_buffer (priv->pool, out_buf, NULL); ret = gst_buffer_pool_acquire_buffer (priv->pool, out_buf, NULL);
} else { } else {
@ -1414,6 +1428,46 @@ default_prepare_output_buffer (GstBaseTransform * trans,
*out_buf = *out_buf =
gst_buffer_new_allocate (priv->allocator, outsize, priv->alignment); gst_buffer_new_allocate (priv->allocator, outsize, priv->alignment);
} }
/* now copy the metadata */
mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT |
GST_BUFFER_FLAG_GAP | GST_BUFFER_FLAG_MEDIA1 |
GST_BUFFER_FLAG_MEDIA2 | GST_BUFFER_FLAG_MEDIA3;
/* see if the flags and timestamps match */
copymeta =
(GST_MINI_OBJECT_FLAGS (*out_buf) & mask) !=
(GST_MINI_OBJECT_FLAGS (in_buf) & mask);
copymeta |=
GST_BUFFER_TIMESTAMP (*out_buf) != GST_BUFFER_TIMESTAMP (in_buf) ||
GST_BUFFER_DURATION (*out_buf) != GST_BUFFER_DURATION (in_buf) ||
GST_BUFFER_OFFSET (*out_buf) != GST_BUFFER_OFFSET (in_buf) ||
GST_BUFFER_OFFSET_END (*out_buf) != GST_BUFFER_OFFSET_END (in_buf);
/* we need to modify the metadata when the element is not gap aware,
* passthrough is not used and the gap flag is set */
copymeta |= !priv->gap_aware && !trans->passthrough
&& (GST_MINI_OBJECT_FLAGS (*out_buf) & GST_BUFFER_FLAG_GAP);
if (copymeta) {
GST_DEBUG_OBJECT (trans, "copying metadata");
if (!gst_buffer_is_writable (*out_buf)) {
/* this should not happen, buffers allocated from a pool or with
* new_allocate should always be writable. */
GST_WARNING_OBJECT (trans, "buffer %p not writable", *out_buf);
*out_buf = gst_buffer_make_writable (*out_buf);
}
/* when we get here, the metadata should be writable */
gst_buffer_copy_into (*out_buf, in_buf,
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
/* clear the GAP flag when the subclass does not understand it */
if (!priv->gap_aware)
GST_BUFFER_FLAG_UNSET (*out_buf, GST_BUFFER_FLAG_GAP);
}
}
return ret; return ret;
/* ERRORS */ /* ERRORS */
@ -1440,7 +1494,6 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
GstBaseTransformClass *bclass; GstBaseTransformClass *bclass;
GstBaseTransformPrivate *priv; GstBaseTransformPrivate *priv;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
gboolean copymeta;
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
@ -1462,10 +1515,10 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
* is because we need to make sure that the buffer is writable for the * is because we need to make sure that the buffer is writable for the
* in_place transform. The docs of the vmethod say that you should return * in_place transform. The docs of the vmethod say that you should return
* a reffed inbuf, which is exactly what we don't want :), oh well.. */ * a reffed inbuf, which is exactly what we don't want :), oh well.. */
if (in_buf == *out_buf) if (in_buf == *out_buf) {
GST_DEBUG_OBJECT (trans, "reusing input buffer");
gst_buffer_unref (in_buf); gst_buffer_unref (in_buf);
} else if (trans->passthrough) {
if (trans->passthrough && in_buf != *out_buf) {
/* we are asked to perform a passthrough transform but the input and /* we are asked to perform a passthrough transform but the input and
* output buffers are different. We have to discard the output buffer and * output buffers are different. We have to discard the output buffer and
* reuse the input buffer. This is rather weird, it means that the prepare * reuse the input buffer. This is rather weird, it means that the prepare
@ -1478,49 +1531,6 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
GST_DEBUG_OBJECT (trans, "using allocated buffer in %p, out %p", in_buf, GST_DEBUG_OBJECT (trans, "using allocated buffer in %p, out %p", in_buf,
*out_buf); *out_buf);
/* if we have different buffers, check if the metadata is ok */
copymeta = FALSE;
if (*out_buf != in_buf) {
guint mask;
mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT |
GST_BUFFER_FLAG_GAP | GST_BUFFER_FLAG_MEDIA1 |
GST_BUFFER_FLAG_MEDIA2 | GST_BUFFER_FLAG_MEDIA3;
/* see if the flags and timestamps match */
copymeta =
(GST_MINI_OBJECT_FLAGS (*out_buf) & mask) ==
(GST_MINI_OBJECT_FLAGS (in_buf) & mask);
copymeta |=
GST_BUFFER_TIMESTAMP (*out_buf) != GST_BUFFER_TIMESTAMP (in_buf) ||
GST_BUFFER_DURATION (*out_buf) != GST_BUFFER_DURATION (in_buf) ||
GST_BUFFER_OFFSET (*out_buf) != GST_BUFFER_OFFSET (in_buf) ||
GST_BUFFER_OFFSET_END (*out_buf) != GST_BUFFER_OFFSET_END (in_buf);
}
/* we need to modify the metadata when the element is not gap aware,
* passthrough is not used and the gap flag is set */
copymeta |= !priv->gap_aware && !trans->passthrough
&& (GST_MINI_OBJECT_FLAGS (*out_buf) & GST_BUFFER_FLAG_GAP);
if (copymeta) {
GST_DEBUG_OBJECT (trans, "copymeta %d", copymeta);
if (!gst_buffer_is_writable (*out_buf)) {
GST_DEBUG_OBJECT (trans, "buffer %p not writable", *out_buf);
if (in_buf == *out_buf)
*out_buf = gst_buffer_copy (in_buf);
else
*out_buf = gst_buffer_make_writable (*out_buf);
}
/* when we get here, the metadata should be writable */
if (copymeta)
gst_buffer_copy_into (*out_buf, in_buf,
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
/* clear the GAP flag when the subclass does not understand it */
if (!priv->gap_aware)
GST_BUFFER_FLAG_UNSET (*out_buf, GST_BUFFER_FLAG_GAP);
}
return ret; return ret;
/* ERRORS */ /* ERRORS */