mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-21 13:36:39 +00:00
basetransform: move the metadata copy code
Move the metadata copy code to the default prepare_output_buffer implementation.
This commit is contained in:
parent
5253a52cb2
commit
f8e75ce406
1 changed files with 92 additions and 82 deletions
|
@ -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,53 +1372,101 @@ 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) {
|
|
||||||
GST_DEBUG_OBJECT (trans, "using pool alloc");
|
|
||||||
ret = gst_buffer_pool_acquire_buffer (priv->pool, out_buf, NULL);
|
|
||||||
} else {
|
} else {
|
||||||
gsize insize, outsize;
|
gboolean copymeta;
|
||||||
gboolean res;
|
guint mask;
|
||||||
|
|
||||||
/* no pool, we need to figure out the size of the output buffer first */
|
/* we can't reuse the input buffer */
|
||||||
insize = gst_buffer_get_size (in_buf);
|
if (priv->pool) {
|
||||||
|
GST_DEBUG_OBJECT (trans, "using pool alloc");
|
||||||
if (trans->passthrough) {
|
ret = gst_buffer_pool_acquire_buffer (priv->pool, out_buf, NULL);
|
||||||
GST_DEBUG_OBJECT (trans, "doing passthrough alloc");
|
|
||||||
/* passthrough, the output size is the same as the input size. */
|
|
||||||
outsize = insize;
|
|
||||||
} else {
|
} else {
|
||||||
gboolean want_in_place = (bclass->transform_ip != NULL)
|
gsize insize, outsize;
|
||||||
&& trans->always_in_place;
|
gboolean res;
|
||||||
|
|
||||||
if (want_in_place) {
|
/* no pool, we need to figure out the size of the output buffer first */
|
||||||
GST_DEBUG_OBJECT (trans, "doing inplace alloc");
|
insize = gst_buffer_get_size (in_buf);
|
||||||
/* we alloc a buffer of the same size as the input */
|
|
||||||
|
if (trans->passthrough) {
|
||||||
|
GST_DEBUG_OBJECT (trans, "doing passthrough alloc");
|
||||||
|
/* passthrough, the output size is the same as the input size. */
|
||||||
outsize = insize;
|
outsize = insize;
|
||||||
} else {
|
} else {
|
||||||
GstCaps *incaps, *outcaps;
|
gboolean want_in_place = (bclass->transform_ip != NULL)
|
||||||
|
&& trans->always_in_place;
|
||||||
|
|
||||||
/* else use the transform function to get the size */
|
if (want_in_place) {
|
||||||
incaps = gst_pad_get_current_caps (trans->sinkpad);
|
GST_DEBUG_OBJECT (trans, "doing inplace alloc");
|
||||||
outcaps = gst_pad_get_current_caps (trans->srcpad);
|
/* we alloc a buffer of the same size as the input */
|
||||||
|
outsize = insize;
|
||||||
|
} else {
|
||||||
|
GstCaps *incaps, *outcaps;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (trans, "getting output size for alloc");
|
/* else use the transform function to get the size */
|
||||||
/* copy transform, figure out the output size */
|
incaps = gst_pad_get_current_caps (trans->sinkpad);
|
||||||
res = gst_base_transform_transform_size (trans,
|
outcaps = gst_pad_get_current_caps (trans->srcpad);
|
||||||
GST_PAD_SINK, incaps, insize, outcaps, &outsize);
|
|
||||||
|
|
||||||
gst_caps_unref (incaps);
|
GST_DEBUG_OBJECT (trans, "getting output size for alloc");
|
||||||
gst_caps_unref (outcaps);
|
/* copy transform, figure out the output size */
|
||||||
|
res = gst_base_transform_transform_size (trans,
|
||||||
|
GST_PAD_SINK, incaps, insize, outcaps, &outsize);
|
||||||
|
|
||||||
if (!res)
|
gst_caps_unref (incaps);
|
||||||
goto unknown_size;
|
gst_caps_unref (outcaps);
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
goto unknown_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
GST_DEBUG_OBJECT (trans, "doing alloc of size %u", outsize);
|
||||||
|
*out_buf =
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
GST_DEBUG_OBJECT (trans, "doing alloc of size %u", outsize);
|
|
||||||
*out_buf =
|
|
||||||
gst_buffer_new_allocate (priv->allocator, outsize, priv->alignment);
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue