2005-06-02 Wim Taymans <wim@fluendo.com>
+ * gst/base/gstbasesink.c: (gst_basesink_pad_buffer_alloc),
+ (gst_base_sink_buffer_alloc), (gst_basesink_preroll_queue_push),
+ (gst_basesink_activate):
+ * gst/base/gstbasesink.h:
+ * gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
+ (gst_pad_link), (gst_pad_accept_caps), (gst_pad_alloc_buffer),
+ (gst_pad_query), (gst_pad_start_task):
+ * gst/gstpad.h:
+ * gst/gstqueue.c: (gst_queue_bufferalloc),
+ (gst_queue_handle_sink_event), (gst_queue_chain):
+ Bufferalloc: return GstFlowReturn to more accuratly report
+ why allocation failed.
+
+2005-06-02 Wim Taymans <wim@fluendo.com>
+
* gst/gstpipeline.c: (gst_pipeline_send_event):
Take snapshot of state without blocking.
static GstCaps *gst_base_sink_get_caps (GstBaseSink * sink);
static gboolean gst_base_sink_set_caps (GstBaseSink * sink, GstCaps * caps);
-static GstBuffer *gst_base_sink_buffer_alloc (GstBaseSink * sink,
- guint64 offset, guint size, GstCaps * caps);
+static GstFlowReturn gst_base_sink_buffer_alloc (GstBaseSink * sink,
+ guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
static void gst_basesink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
GstClockTime * start, GstClockTime * end);
return res;
}
-static GstBuffer *
+static GstFlowReturn
gst_basesink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size,
- GstCaps * caps)
+ GstCaps * caps, GstBuffer ** buf)
{
GstBaseSinkClass *bclass;
GstBaseSink *bsink;
- GstBuffer *buffer = NULL;
+ GstFlowReturn result = GST_FLOW_OK;
bsink = GST_BASESINK (GST_PAD_PARENT (pad));
bclass = GST_BASESINK_GET_CLASS (bsink);
if (bclass->buffer_alloc)
- buffer = bclass->buffer_alloc (bsink, offset, size, caps);
+ result = bclass->buffer_alloc (bsink, offset, size, caps, buf);
+ else
+ *buf = NULL;
- return buffer;
+ return result;
}
static void
return TRUE;
}
-static GstBuffer *
+static GstFlowReturn
gst_base_sink_buffer_alloc (GstBaseSink * sink, guint64 offset, guint size,
- GstCaps * caps)
+ GstCaps * caps, GstBuffer ** buf)
{
- return NULL;
+ *buf = NULL;
+ return GST_FLOW_OK;
}
/* with PREROLL_LOCK */
gboolean (*set_caps) (GstBaseSink *sink, GstCaps *caps);
/* allocate a new buffer with given caps */
- GstBuffer* (*buffer_alloc) (GstBaseSink *sink, guint64 offset, guint size,
- GstCaps *caps);
+ GstFlowReturn (*buffer_alloc) (GstBaseSink *sink, guint64 offset, guint size,
+ GstCaps *caps, GstBuffer **buf);
/* get the start and end times for syncing on this buffer */
void (*get_times) (GstBaseSink *sink, GstBuffer *buffer,
* @offset: the offset of the new buffer in the stream
* @size: the size of the new buffer
* @caps: the caps of the new buffer
+ * @buf: a newly allocated buffer
*
* Allocates a new, empty buffer optimized to push to pad @pad. This
* function only works if @pad is a source pad and a GST_REAL_PAD and
* You need to check the caps of the buffer after performing this
* function and renegotiate to the format if needed.
*
- * Returns: a new, empty #GstBuffer, or NULL if wrong parameters
- * were provided or the peer pad is not able to provide a buffer
- * that can be handled by the caller.
+ * A new, empty #GstBuffer will be put in the @buf argument.
+ *
+ * Returns: a result code indicating success of the operation. Any
+ * result code other than GST_FLOW_OK is an error and @buf should
+ * not be used.
+ * An error can occur if the pad is not connected or when the downstream
+ * peer elements cannot provide an acceptable buffer.
*
* MT safe.
*/
-GstBuffer *
-gst_pad_alloc_buffer (GstPad * pad, guint64 offset, gint size, GstCaps * caps)
+GstFlowReturn
+gst_pad_alloc_buffer (GstPad * pad, guint64 offset, gint size, GstCaps * caps,
+ GstBuffer ** buf)
{
GstRealPad *peer;
- GstBuffer *result = NULL;
+ GstFlowReturn ret;
GstPadBufferAllocFunction bufferallocfunc;
gboolean caps_changed;
- g_return_val_if_fail (GST_IS_REAL_PAD (pad), NULL);
- g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
+ g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
GST_LOCK (pad);
if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL))
gst_object_ref (GST_OBJECT_CAST (peer));
GST_UNLOCK (pad);
- if (G_LIKELY ((bufferallocfunc = peer->bufferallocfunc) == NULL)) {
+ if (G_LIKELY ((bufferallocfunc = peer->bufferallocfunc) == NULL))
goto fallback;
- }
GST_LOCK (peer);
/* when the peer is flushing we cannot give a buffer */
&bufferallocfunc, GST_DEBUG_PAD_NAME (peer));
GST_UNLOCK (peer);
- result = bufferallocfunc (GST_PAD_CAST (peer), offset, size, caps);
+ ret = bufferallocfunc (GST_PAD_CAST (peer), offset, size, caps, buf);
- gst_object_unref (GST_OBJECT_CAST (peer));
-
- if (G_UNLIKELY (result == NULL)) {
+ if (G_UNLIKELY (ret != GST_FLOW_OK))
+ goto peer_error;
+ if (G_UNLIKELY (*buf == NULL))
goto fallback;
- }
do_caps:
+ gst_object_unref (GST_OBJECT_CAST (peer));
+
/* FIXME, move capnego this into a base class? */
- caps = GST_BUFFER_CAPS (result);
+ caps = GST_BUFFER_CAPS (*buf);
caps_changed = caps && caps != GST_RPAD_CAPS (pad);
/* we got a new datatype on the pad, see if it can handle it */
if (G_UNLIKELY (caps_changed)) {
if (G_UNLIKELY (!gst_pad_configure_src (GST_PAD_CAST (pad), caps)))
goto not_negotiated;
}
-
- return result;
+ return ret;
no_peer:
{
"%s:%s called bufferallocfunc but had no peer, returning NULL",
GST_DEBUG_PAD_NAME (pad));
GST_UNLOCK (pad);
- return NULL;
+ return GST_FLOW_NOT_CONNECTED;
}
flushing:
{
/* peer was flushing */
GST_UNLOCK (peer);
+ gst_object_unref (GST_OBJECT_CAST (peer));
GST_CAT_DEBUG (GST_CAT_PADS,
"%s:%s called bufferallocfunc but peer was flushing, returning NULL",
GST_DEBUG_PAD_NAME (pad));
- return NULL;
+ return GST_FLOW_WRONG_STATE;
}
/* fallback case, allocate a buffer of our own, add pad caps. */
fallback:
{
GST_CAT_DEBUG (GST_CAT_PADS,
"%s:%s fallback buffer alloc", GST_DEBUG_PAD_NAME (pad));
- result = gst_buffer_new_and_alloc (size);
- gst_buffer_set_caps (result, caps);
+ *buf = gst_buffer_new_and_alloc (size);
+ gst_buffer_set_caps (*buf, caps);
+
+ ret = GST_FLOW_OK;
goto do_caps;
}
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"alloc function retured unacceptable buffer");
- return NULL;
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
+peer_error:
+ {
+ gst_object_unref (GST_OBJECT_CAST (peer));
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "alloc function retured error %d", ret);
+ return ret;
}
}
typedef gboolean (*GstPadSetCapsFunction) (GstPad *pad, GstCaps *caps);
typedef gboolean (*GstPadAcceptCapsFunction) (GstPad *pad, GstCaps *caps);
typedef GstCaps* (*GstPadFixateCapsFunction) (GstPad *pad, GstCaps *caps);
-typedef GstBuffer* (*GstPadBufferAllocFunction) (GstPad *pad, guint64 offset, guint size,
- GstCaps *caps);
+typedef GstFlowReturn (*GstPadBufferAllocFunction) (GstPad *pad, guint64 offset, guint size,
+ GstCaps *caps, GstBuffer **buf);
/* misc */
typedef gboolean (*GstPadDispatcherFunction) (GstPad *pad, gpointer data);
GstPadBufferAllocFunction bufferallocfunc;
- GstProbeDispatcher probedisp;
+ GstProbeDispatcher probedisp;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
GstPadTemplate* gst_pad_get_pad_template (GstPad *pad);
void gst_pad_set_bufferalloc_function (GstPad *pad, GstPadBufferAllocFunction bufalloc);
-GstBuffer* gst_pad_alloc_buffer (GstPad *pad, guint64 offset, gint size,
- GstCaps *caps);
+GstFlowReturn gst_pad_alloc_buffer (GstPad *pad, guint64 offset, gint size,
+ GstCaps *caps, GstBuffer **buf);
/* data passing setup functions */
void gst_pad_set_activate_function (GstPad *pad, GstPadActivateFunction activate);
/* misc helper functions */
gboolean gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch,
gpointer data);
-
/* probes */
-#define gst_pad_add_probe(pad, probe) \
- (gst_probe_dispatcher_add_probe (&(GST_PAD_REALIZE (pad)->probedisp), probe))
-#define gst_pad_remove_probe(pad, probe) \
- (gst_probe_dispatcher_remove_probe (&(GST_PAD_REALIZE (pad)->probedisp), probe))
+#define gst_pad_add_probe(pad, probe) \
+ (gst_probe_dispatcher_add_probe (&(GST_PAD_REALIZE (pad)->probedisp), probe))
+#define gst_pad_remove_probe(pad, probe) \
+ (gst_probe_dispatcher_remove_probe (&(GST_PAD_REALIZE (pad)->probedisp), probe))
#ifndef GST_DISABLE_LOADSAVE
void gst_pad_load_and_link (xmlNodePtr self, GstObject *parent);
guint prop_id, GValue * value, GParamSpec * pspec);
static GstFlowReturn gst_queue_chain (GstPad * pad, GstBuffer * buffer);
-static GstBuffer *gst_queue_bufferalloc (GstPad * pad, guint64 offset,
- guint size, GstCaps * caps);
+static GstFlowReturn gst_queue_bufferalloc (GstPad * pad, guint64 offset,
+ guint size, GstCaps * caps, GstBuffer ** buf);
static void gst_queue_loop (GstPad * pad);
static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event);
return result;
}
-static GstBuffer *
-gst_queue_bufferalloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps)
+static GstFlowReturn
+gst_queue_bufferalloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
+ GstBuffer ** buf)
{
GstQueue *queue;
- GstPad *otherpeer;
- GstBuffer *result = NULL;
+ GstFlowReturn result;
queue = GST_QUEUE (GST_PAD_PARENT (pad));
- otherpeer = gst_pad_get_peer (queue->srcpad);
- if (otherpeer == NULL || GST_RPAD_BUFFERALLOCFUNC (otherpeer) == NULL) {
- /* let the default aloc function do the work */
- result = NULL;
- } else {
- result =
- GST_RPAD_BUFFERALLOCFUNC (otherpeer) (otherpeer, offset, size, caps);
- }
- if (otherpeer)
- gst_object_unref (GST_OBJECT (otherpeer));
+ result = gst_pad_alloc_buffer (queue->srcpad, offset, size, caps, buf);
return result;
}
static GstCaps *gst_base_sink_get_caps (GstBaseSink * sink);
static gboolean gst_base_sink_set_caps (GstBaseSink * sink, GstCaps * caps);
-static GstBuffer *gst_base_sink_buffer_alloc (GstBaseSink * sink,
- guint64 offset, guint size, GstCaps * caps);
+static GstFlowReturn gst_base_sink_buffer_alloc (GstBaseSink * sink,
+ guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
static void gst_basesink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
GstClockTime * start, GstClockTime * end);
return res;
}
-static GstBuffer *
+static GstFlowReturn
gst_basesink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size,
- GstCaps * caps)
+ GstCaps * caps, GstBuffer ** buf)
{
GstBaseSinkClass *bclass;
GstBaseSink *bsink;
- GstBuffer *buffer = NULL;
+ GstFlowReturn result = GST_FLOW_OK;
bsink = GST_BASESINK (GST_PAD_PARENT (pad));
bclass = GST_BASESINK_GET_CLASS (bsink);
if (bclass->buffer_alloc)
- buffer = bclass->buffer_alloc (bsink, offset, size, caps);
+ result = bclass->buffer_alloc (bsink, offset, size, caps, buf);
+ else
+ *buf = NULL;
- return buffer;
+ return result;
}
static void
return TRUE;
}
-static GstBuffer *
+static GstFlowReturn
gst_base_sink_buffer_alloc (GstBaseSink * sink, guint64 offset, guint size,
- GstCaps * caps)
+ GstCaps * caps, GstBuffer ** buf)
{
- return NULL;
+ *buf = NULL;
+ return GST_FLOW_OK;
}
/* with PREROLL_LOCK */
gboolean (*set_caps) (GstBaseSink *sink, GstCaps *caps);
/* allocate a new buffer with given caps */
- GstBuffer* (*buffer_alloc) (GstBaseSink *sink, guint64 offset, guint size,
- GstCaps *caps);
+ GstFlowReturn (*buffer_alloc) (GstBaseSink *sink, guint64 offset, guint size,
+ GstCaps *caps, GstBuffer **buf);
/* get the start and end times for syncing on this buffer */
void (*get_times) (GstBaseSink *sink, GstBuffer *buffer,
guint prop_id, GValue * value, GParamSpec * pspec);
static GstFlowReturn gst_queue_chain (GstPad * pad, GstBuffer * buffer);
-static GstBuffer *gst_queue_bufferalloc (GstPad * pad, guint64 offset,
- guint size, GstCaps * caps);
+static GstFlowReturn gst_queue_bufferalloc (GstPad * pad, guint64 offset,
+ guint size, GstCaps * caps, GstBuffer ** buf);
static void gst_queue_loop (GstPad * pad);
static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event);
return result;
}
-static GstBuffer *
-gst_queue_bufferalloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps)
+static GstFlowReturn
+gst_queue_bufferalloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
+ GstBuffer ** buf)
{
GstQueue *queue;
- GstPad *otherpeer;
- GstBuffer *result = NULL;
+ GstFlowReturn result;
queue = GST_QUEUE (GST_PAD_PARENT (pad));
- otherpeer = gst_pad_get_peer (queue->srcpad);
- if (otherpeer == NULL || GST_RPAD_BUFFERALLOCFUNC (otherpeer) == NULL) {
- /* let the default aloc function do the work */
- result = NULL;
- } else {
- result =
- GST_RPAD_BUFFERALLOCFUNC (otherpeer) (otherpeer, offset, size, caps);
- }
- if (otherpeer)
- gst_object_unref (GST_OBJECT (otherpeer));
+ result = gst_pad_alloc_buffer (queue->srcpad, offset, size, caps, buf);
return result;
}