diff --git a/ChangeLog b/ChangeLog index 36285c7085..6bfbf8e7da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2005-11-11 Wim Taymans + + * gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buf), + (gst_base_transform_handle_buffer): + Small cleanups. + If we're processing a buffer and need to allocate an output + buffer, we cannot accept a format change. If we did get a + format change, we have to alloc a buffer ourselves of the + right size. + 2005-11-11 Wim Taymans * gst/gstpad.c: (gst_pad_get_caps), (gst_pad_peer_get_caps): diff --git a/gst/base/gstbasetransform.c b/gst/base/gstbasetransform.c index d097c97b62..4990af31d2 100644 --- a/gst/base/gstbasetransform.c +++ b/gst/base/gstbasetransform.c @@ -785,10 +785,19 @@ failed_configure: } } -/* Allocate a buffer using gst_pad_alloc_buffer */ +/* Allocate a buffer using gst_pad_alloc_buffer. + * + * This function can trigger a renegotiation on the source pad when the + * peer alloc_buffer function sets new caps. Since we currently are + * processing a buffer on the sinkpad when this function is called, we cannot + * reconfigure the transform with sinkcaps different from those of the current + * buffer. FIXME, we currently don't check if the pluging can transform to the + * new srcpad caps using the same sinkcaps, we alloc a proper outbuf buffer + * ourselves instead. + */ static GstFlowReturn gst_base_transform_prepare_output_buf (GstBaseTransform * trans, - GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf) + GstBuffer * in_buf, gint out_size, GstCaps * out_caps, GstBuffer ** out_buf) { GstBaseTransformClass *bclass; GstFlowReturn ret = GST_FLOW_OK; @@ -796,53 +805,72 @@ gst_base_transform_prepare_output_buf (GstBaseTransform * trans, bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + /* 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; + + /* see if the subclass wants to alloc a buffer */ if (bclass->prepare_output_buffer) { - ret = bclass->prepare_output_buffer (trans, input, size, caps, buf); + ret = + bclass->prepare_output_buffer (trans, in_buf, out_size, out_caps, + out_buf); if (ret != GST_FLOW_OK) - return ret; + goto done; } /* See if we want to prepare the buffer for in place output */ - if (*buf == NULL && GST_BUFFER_SIZE (input) == size && bclass->transform_ip) { - if (gst_buffer_is_writable (input)) { + if (*out_buf == NULL && GST_BUFFER_SIZE (in_buf) == out_size + && bclass->transform_ip) { + if (gst_buffer_is_writable (in_buf)) { if (trans->have_same_caps) { /* Input buffer is already writable and caps are the same, just ref and return it */ - *buf = input; - gst_buffer_ref (input); + *out_buf = in_buf; + gst_buffer_ref (in_buf); } else { /* Writable buffer, but need to change caps => subbuffer */ - *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input)); - gst_caps_replace (&GST_BUFFER_CAPS (*buf), caps); + *out_buf = gst_buffer_create_sub (in_buf, 0, GST_BUFFER_SIZE (in_buf)); + gst_caps_replace (&GST_BUFFER_CAPS (*out_buf), out_caps); } - - return GST_FLOW_OK; + goto done; } else { /* Make a writable buffer below and copy the data */ copy_inbuf = TRUE; } } - if (*buf == NULL) { - /* Sub-class didn't already implement a buffer for us. Make one */ - ret = gst_pad_alloc_buffer (trans->srcpad, GST_BUFFER_OFFSET (input), - size, caps, buf); - if (ret != GST_FLOW_OK || *buf == NULL) - return ret; + if (*out_buf == NULL) { + /* Sub-class didn't already provide a buffer for us. Make one */ + ret = gst_pad_alloc_buffer (trans->srcpad, GST_BUFFER_OFFSET (in_buf), + out_size, out_caps, out_buf); + if (ret != GST_FLOW_OK || *out_buf == NULL) + goto done; + + /* allocated buffer could be of different caps than what we requested */ + if (G_UNLIKELY (!gst_caps_is_equal (out_caps, GST_BUFFER_CAPS (*out_buf)))) { + /* FIXME, it is possible we can reconfigure the transform with new caps at this + * point but for now we just create a buffer ourselves */ + *out_buf = gst_buffer_new_and_alloc (out_size); + gst_buffer_set_caps (*out_buf, out_caps); + } } /* If the output buffer metadata is modifiable, copy timestamps and * buffer flags */ - if (*buf != input && GST_MINI_OBJECT_REFCOUNT_VALUE (*buf) == 1) { + if (*out_buf != in_buf && GST_MINI_OBJECT_REFCOUNT_VALUE (*out_buf) == 1) { - if (copy_inbuf && gst_buffer_is_writable (*buf)) - memcpy (GST_BUFFER_DATA (*buf), GST_BUFFER_DATA (input), size); + if (copy_inbuf && gst_buffer_is_writable (*out_buf)) + memcpy (GST_BUFFER_DATA (*out_buf), GST_BUFFER_DATA (in_buf), out_size); - gst_buffer_stamp (*buf, input); - GST_BUFFER_FLAGS (*buf) |= GST_BUFFER_FLAGS (input) & + gst_buffer_stamp (*out_buf, in_buf); + GST_BUFFER_FLAGS (*out_buf) |= GST_BUFFER_FLAGS (in_buf) & (GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS | GST_BUFFER_FLAG_DELTA_UNIT); } +done: + trans->delay_configure = FALSE; + return ret; } @@ -1117,13 +1145,8 @@ gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf, * wish. */ GST_LOG_OBJECT (trans, "doing inplace transform"); - /* 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; ret = gst_base_transform_prepare_output_buf (trans, inbuf, GST_BUFFER_SIZE (inbuf), GST_PAD_CAPS (trans->srcpad), outbuf); - trans->delay_configure = FALSE; if (G_UNLIKELY (ret != GST_FLOW_OK)) goto no_buffer; @@ -1145,15 +1168,9 @@ gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf, } } - /* 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_base_transform_prepare_output_buf (trans, inbuf, out_size, GST_PAD_CAPS (trans->srcpad), outbuf); - trans->delay_configure = FALSE; - if (ret != GST_FLOW_OK) goto no_buffer; diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c index d097c97b62..4990af31d2 100644 --- a/libs/gst/base/gstbasetransform.c +++ b/libs/gst/base/gstbasetransform.c @@ -785,10 +785,19 @@ failed_configure: } } -/* Allocate a buffer using gst_pad_alloc_buffer */ +/* Allocate a buffer using gst_pad_alloc_buffer. + * + * This function can trigger a renegotiation on the source pad when the + * peer alloc_buffer function sets new caps. Since we currently are + * processing a buffer on the sinkpad when this function is called, we cannot + * reconfigure the transform with sinkcaps different from those of the current + * buffer. FIXME, we currently don't check if the pluging can transform to the + * new srcpad caps using the same sinkcaps, we alloc a proper outbuf buffer + * ourselves instead. + */ static GstFlowReturn gst_base_transform_prepare_output_buf (GstBaseTransform * trans, - GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf) + GstBuffer * in_buf, gint out_size, GstCaps * out_caps, GstBuffer ** out_buf) { GstBaseTransformClass *bclass; GstFlowReturn ret = GST_FLOW_OK; @@ -796,53 +805,72 @@ gst_base_transform_prepare_output_buf (GstBaseTransform * trans, bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + /* 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; + + /* see if the subclass wants to alloc a buffer */ if (bclass->prepare_output_buffer) { - ret = bclass->prepare_output_buffer (trans, input, size, caps, buf); + ret = + bclass->prepare_output_buffer (trans, in_buf, out_size, out_caps, + out_buf); if (ret != GST_FLOW_OK) - return ret; + goto done; } /* See if we want to prepare the buffer for in place output */ - if (*buf == NULL && GST_BUFFER_SIZE (input) == size && bclass->transform_ip) { - if (gst_buffer_is_writable (input)) { + if (*out_buf == NULL && GST_BUFFER_SIZE (in_buf) == out_size + && bclass->transform_ip) { + if (gst_buffer_is_writable (in_buf)) { if (trans->have_same_caps) { /* Input buffer is already writable and caps are the same, just ref and return it */ - *buf = input; - gst_buffer_ref (input); + *out_buf = in_buf; + gst_buffer_ref (in_buf); } else { /* Writable buffer, but need to change caps => subbuffer */ - *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input)); - gst_caps_replace (&GST_BUFFER_CAPS (*buf), caps); + *out_buf = gst_buffer_create_sub (in_buf, 0, GST_BUFFER_SIZE (in_buf)); + gst_caps_replace (&GST_BUFFER_CAPS (*out_buf), out_caps); } - - return GST_FLOW_OK; + goto done; } else { /* Make a writable buffer below and copy the data */ copy_inbuf = TRUE; } } - if (*buf == NULL) { - /* Sub-class didn't already implement a buffer for us. Make one */ - ret = gst_pad_alloc_buffer (trans->srcpad, GST_BUFFER_OFFSET (input), - size, caps, buf); - if (ret != GST_FLOW_OK || *buf == NULL) - return ret; + if (*out_buf == NULL) { + /* Sub-class didn't already provide a buffer for us. Make one */ + ret = gst_pad_alloc_buffer (trans->srcpad, GST_BUFFER_OFFSET (in_buf), + out_size, out_caps, out_buf); + if (ret != GST_FLOW_OK || *out_buf == NULL) + goto done; + + /* allocated buffer could be of different caps than what we requested */ + if (G_UNLIKELY (!gst_caps_is_equal (out_caps, GST_BUFFER_CAPS (*out_buf)))) { + /* FIXME, it is possible we can reconfigure the transform with new caps at this + * point but for now we just create a buffer ourselves */ + *out_buf = gst_buffer_new_and_alloc (out_size); + gst_buffer_set_caps (*out_buf, out_caps); + } } /* If the output buffer metadata is modifiable, copy timestamps and * buffer flags */ - if (*buf != input && GST_MINI_OBJECT_REFCOUNT_VALUE (*buf) == 1) { + if (*out_buf != in_buf && GST_MINI_OBJECT_REFCOUNT_VALUE (*out_buf) == 1) { - if (copy_inbuf && gst_buffer_is_writable (*buf)) - memcpy (GST_BUFFER_DATA (*buf), GST_BUFFER_DATA (input), size); + if (copy_inbuf && gst_buffer_is_writable (*out_buf)) + memcpy (GST_BUFFER_DATA (*out_buf), GST_BUFFER_DATA (in_buf), out_size); - gst_buffer_stamp (*buf, input); - GST_BUFFER_FLAGS (*buf) |= GST_BUFFER_FLAGS (input) & + gst_buffer_stamp (*out_buf, in_buf); + GST_BUFFER_FLAGS (*out_buf) |= GST_BUFFER_FLAGS (in_buf) & (GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS | GST_BUFFER_FLAG_DELTA_UNIT); } +done: + trans->delay_configure = FALSE; + return ret; } @@ -1117,13 +1145,8 @@ gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf, * wish. */ GST_LOG_OBJECT (trans, "doing inplace transform"); - /* 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; ret = gst_base_transform_prepare_output_buf (trans, inbuf, GST_BUFFER_SIZE (inbuf), GST_PAD_CAPS (trans->srcpad), outbuf); - trans->delay_configure = FALSE; if (G_UNLIKELY (ret != GST_FLOW_OK)) goto no_buffer; @@ -1145,15 +1168,9 @@ gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf, } } - /* 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_base_transform_prepare_output_buf (trans, inbuf, out_size, GST_PAD_CAPS (trans->srcpad), outbuf); - trans->delay_configure = FALSE; - if (ret != GST_FLOW_OK) goto no_buffer;