GstFlowReturn ret;
GstPadGetRangeFunction getrangefunc;
GstObject *parent;
+ GstBuffer *res_buf;
GST_PAD_STREAM_LOCK (pad);
if (G_UNLIKELY ((ret = check_sticky (pad))) != GST_FLOW_OK)
goto events_error;
+ res_buf = *buffer;
+
/* when one of the probes returns DROPPED, probe_stopped will be called
- * and we skip calling the getrange function, *buffer should then contain a
+ * and we skip calling the getrange function, res_buf should then contain a
* valid result buffer */
PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
- *buffer, offset, size, probe_stopped);
+ res_buf, offset, size, probe_stopped);
ACQUIRE_PARENT (pad, parent, no_parent);
GST_OBJECT_UNLOCK (pad);
G_GUINT64_FORMAT ", size %u",
GST_DEBUG_FUNCPTR_NAME (getrangefunc), offset, size);
- ret = getrangefunc (pad, parent, offset, size, buffer);
+ ret = getrangefunc (pad, parent, offset, size, &res_buf);
RELEASE_PARENT (parent);
GST_OBJECT_LOCK (pad);
probed_data:
PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER,
- *buffer, offset, size, probe_stopped_unref);
+ res_buf, offset, size, probe_stopped_unref);
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
+ *buffer = res_buf;
+
return ret;
/* ERRORS */
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"probe returned %s", gst_flow_get_name (ret));
if (ret == GST_FLOW_CUSTOM_SUCCESS) {
- if (*buffer) {
+ if (res_buf) {
/* the probe filled the buffer and asks us to not call the getrange
* anymore, we continue with the post probes then. */
GST_DEBUG_OBJECT (pad, "handled buffer");
ret = GST_FLOW_EOS;
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
- gst_buffer_unref (*buffer);
- *buffer = NULL;
+ if (*buffer == NULL)
+ gst_buffer_unref (res_buf);
return ret;
}
get_range_failed:
{
GST_PAD_STREAM_UNLOCK (pad);
- *buffer = NULL;
GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING,
(ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
pad, "getrange failed, flow: %s", gst_flow_get_name (ret));
* installed (see gst_pad_set_getrange_function()) this function returns
* #GST_FLOW_NOT_SUPPORTED.
*
- * @buffer must point to a variable holding NULL or a variable that
- * points to a #GstBuffer that will be filled with the result data.
+ * If @buffer points to a variable holding NULL, a valid new #GstBuffer will be
+ * placed in @buffer when this function returns #GST_FLOW_OK. The new buffer
+ * must be freed with gst_buffer_unref() after usage.
+ *
+ * When @buffer points to a variable that points to a valid #GstBuffer, the
+ * buffer will be filled with the result data when this function returns
+ * #GST_FLOW_OK. If the provided buffer is larger than @size, only
+ * @size bytes will be filled in the result buffer and its size will be updated
+ * accordingly.
+ *
+ * Note that less than @size bytes can be returned in @buffer when, for example,
+ * an EOS condition is near or when @buffer is not large enough to hold @size
+ * bytes. The caller should check the result buffer size to get the result size.
+ *
+ * When this function returns any other result value than #GST_FLOW_OK, @buffer
+ * will be unchanged.
*
* This is a lowlevel function. Usualy gst_pad_pull_range() is used.
*
* @buffer: (out callee-allocates): a pointer to hold the #GstBuffer, returns
* GST_FLOW_ERROR if %NULL.
*
- * Pulls a @buffer from the peer pad.
+ * Pulls a @buffer from the peer pad or fills up a provided buffer.
*
* This function will first trigger the pad block signal if it was
* installed.
* See gst_pad_get_range() for a list of return values and for the
* semantics of the arguments of this function.
*
- * @buffer must point to a variable holding NULL or a variable that
- * points to a #GstBuffer that will be filled with the result data.
+ * If @buffer points to a variable holding NULL, a valid new #GstBuffer will be
+ * placed in @buffer when this function returns #GST_FLOW_OK. The new buffer
+ * must be freed with gst_buffer_unref() after usage. When this function
+ * returns any other result value, @buffer will still point to NULL.
+ *
+ * When @buffer points to a variable that points to a valid #GstBuffer, the
+ * buffer will be filled with the result data when this function returns
+ * #GST_FLOW_OK. When this function returns any other result value,
+ * @buffer will be unchanged. If the provided buffer is larger than @size, only
+ * @size bytes will be filled in the result buffer and its size will be updated
+ * accordingly.
+ *
+ * Note that less than @size bytes can be returned in @buffer when, for example,
+ * an EOS condition is near or when @buffer is not large enough to hold @size
+ * bytes. The caller should check the result buffer size to get the result size.
*
* Returns: a #GstFlowReturn from the peer pad.
- * When this function returns #GST_FLOW_OK, @buffer will contain a valid
- * #GstBuffer that should be freed with gst_buffer_unref() after usage.
- * @buffer may not be used or freed when any other return value than
- * #GST_FLOW_OK is returned.
*
* MT safe.
*/
{
GstPad *peer;
GstFlowReturn ret;
+ GstBuffer *res_buf;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PULL))
goto wrong_mode;
+ res_buf = *buffer;
+
/* when one of the probes returns DROPPED, probe_stopped will be
* called and we skip calling the peer getrange function. *buffer should then
* contain a valid buffer */
PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
- *buffer, offset, size, probe_stopped);
+ res_buf, offset, size, probe_stopped);
if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
goto not_linked;
pad->priv->using++;
GST_OBJECT_UNLOCK (pad);
- ret = gst_pad_get_range_unchecked (peer, offset, size, buffer);
+ ret = gst_pad_get_range_unchecked (peer, offset, size, &res_buf);
gst_object_unref (peer);
probed_data:
PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER,
- *buffer, offset, size, probe_stopped_unref);
+ res_buf, offset, size, probe_stopped_unref);
GST_OBJECT_UNLOCK (pad);
+ *buffer = res_buf;
+
return ret;
/* ERROR recovery here */
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pre probe returned %s",
gst_flow_get_name (ret));
if (ret == GST_FLOW_CUSTOM_SUCCESS) {
- if (*buffer) {
+ if (res_buf) {
/* the probe filled the buffer and asks us to not forward to the peer
* anymore, we continue with the post probes then */
GST_DEBUG_OBJECT (pad, "handled buffer");
}
pull_range_failed:
{
- *buffer = NULL;
GST_OBJECT_UNLOCK (pad);
GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING,
(ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
"post probe returned %s", gst_flow_get_name (ret));
GST_OBJECT_UNLOCK (pad);
/* if we drop here, it signals EOS */
- if (ret == GST_FLOW_CUSTOM_SUCCESS) {
+ if (ret == GST_FLOW_CUSTOM_SUCCESS)
ret = GST_FLOW_EOS;
- gst_buffer_unref (*buffer);
- } else if (ret == GST_FLOW_OK)
- gst_buffer_unref (*buffer);
- *buffer = NULL;
+ if (*buffer == NULL)
+ gst_buffer_unref (res_buf);
return ret;
}
}
{
GstBaseSrcClass *bclass;
GstFlowReturn ret;
+ GstBuffer *res_buf;
bclass = GST_BASE_SRC_GET_CLASS (src);
if (*buffer == NULL) {
/* downstream did not provide us with a buffer to fill, allocate one
* ourselves */
- ret = bclass->alloc (src, offset, size, buffer);
+ ret = bclass->alloc (src, offset, size, &res_buf);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto alloc_failed;
+ } else {
+ res_buf = *buffer;
}
if (G_LIKELY (size > 0)) {
/* only call fill when there is a size */
- ret = bclass->fill (src, offset, size, *buffer);
+ ret = bclass->fill (src, offset, size, res_buf);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto not_ok;
}
+ *buffer = res_buf;
+
return GST_FLOW_OK;
/* ERRORS */
{
GST_DEBUG_OBJECT (src, "fill returned %d (%s)", ret,
gst_flow_get_name (ret));
- gst_buffer_unref (*buffer);
+ if (*buffer == NULL)
+ gst_buffer_unref (res_buf);
return ret;
}
}
GstFlowReturn ret;
GstBaseSrcClass *bclass;
GstClockReturn status;
+ GstBuffer *res_buf;
bclass = GST_BASE_SRC_GET_CLASS (src);
"calling create offset %" G_GUINT64_FORMAT " length %u, time %"
G_GINT64_FORMAT, offset, length, src->segment.time);
- ret = bclass->create (src, offset, length, buf);
+ res_buf = *buf;
+
+ ret = bclass->create (src, offset, length, &res_buf);
/* The create function could be unlocked because we have a pending EOS. It's
* possible that we have a valid buffer from create that we need to
* discard when the create function returned _OK. */
if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos))) {
if (ret == GST_FLOW_OK) {
- gst_buffer_unref (*buf);
- *buf = NULL;
+ if (*buf == NULL)
+ gst_buffer_unref (res_buf);
}
goto eos;
}
/* no timestamp set and we are at offset 0, we can timestamp with 0 */
if (offset == 0 && src->segment.time == 0
- && GST_BUFFER_TIMESTAMP (*buf) == -1 && !src->is_live) {
+ && GST_BUFFER_TIMESTAMP (res_buf) == -1 && !src->is_live) {
GST_DEBUG_OBJECT (src, "setting first timestamp to 0");
- *buf = gst_buffer_make_writable (*buf);
- GST_BUFFER_TIMESTAMP (*buf) = 0;
+ res_buf = gst_buffer_make_writable (res_buf);
+ GST_BUFFER_TIMESTAMP (res_buf) = 0;
}
/* now sync before pushing the buffer */
- status = gst_base_src_do_sync (src, *buf);
+ status = gst_base_src_do_sync (src, res_buf);
/* waiting for the clock could have made us flushing */
if (G_UNLIKELY (src->priv->flushing))
/* this case is triggered when we were waiting for the clock and
* it got unlocked because we did a state change. In any case, get rid of
* the buffer. */
- gst_buffer_unref (*buf);
- *buf = NULL;
+ if (*buf == NULL)
+ gst_buffer_unref (res_buf);
+
if (!src->live_running) {
/* We return WRONG_STATE when we are not running to stop the dataflow also
* get rid of the produced buffer. */
GST_ELEMENT_ERROR (src, CORE, CLOCK,
(_("Internal clock error.")),
("clock returned unexpected return value %d", status));
- gst_buffer_unref (*buf);
- *buf = NULL;
+ if (*buf == NULL)
+ gst_buffer_unref (res_buf);
ret = GST_FLOW_ERROR;
break;
}
+ if (G_LIKELY (ret == GST_FLOW_OK))
+ *buf = res_buf;
+
return ret;
/* ERROR */
flushing:
{
GST_DEBUG_OBJECT (src, "we are flushing");
- gst_buffer_unref (*buf);
- *buf = NULL;
+ if (*buf == NULL)
+ gst_buffer_unref (res_buf);
return GST_FLOW_FLUSHING;
}
eos: