tee: add buffer-list support

This commit is contained in:
Wim Taymans 2009-06-19 19:35:04 +02:00
parent 570ec39b1c
commit b054530479

View file

@ -116,6 +116,7 @@ static void gst_tee_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer);
static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstBufferList * list);
static GstFlowReturn gst_tee_buffer_alloc (GstPad * pad, guint64 offset,
guint size, GstCaps * caps, GstBuffer ** buf);
static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active);
@ -223,6 +224,8 @@ gst_tee_init (GstTee * tee, GstTeeClass * g_class)
gst_pad_set_activatepush_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push));
gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
gst_pad_set_chain_list_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_tee_chain_list));
gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
tee->last_message = NULL;
@ -524,17 +527,23 @@ gst_tee_buffer_alloc (GstPad * pad, guint64 offset, guint size,
}
static GstFlowReturn
gst_tee_do_push (GstTee * tee, GstPad * pad, GstBuffer * buffer)
gst_tee_do_push (GstTee * tee, GstPad * pad, gpointer data, gboolean is_list)
{
GstFlowReturn res;
if (G_UNLIKELY (!tee->silent)) {
GST_OBJECT_LOCK (tee);
g_free (tee->last_message);
tee->last_message =
g_strdup_printf ("chain ******* (%s:%s)t (%d bytes, %"
G_GUINT64_FORMAT ") %p", GST_DEBUG_PAD_NAME (pad),
GST_BUFFER_SIZE (buffer), GST_BUFFER_TIMESTAMP (buffer), buffer);
if (is_list) {
tee->last_message =
g_strdup_printf ("chain-list ******* (%s:%s)t %p",
GST_DEBUG_PAD_NAME (pad), data);
} else {
tee->last_message =
g_strdup_printf ("chain ******* (%s:%s)t (%d bytes, %"
G_GUINT64_FORMAT ") %p", GST_DEBUG_PAD_NAME (pad),
GST_BUFFER_SIZE (data), GST_BUFFER_TIMESTAMP (data), data);
}
GST_OBJECT_UNLOCK (tee);
g_object_notify (G_OBJECT (tee), "last_message");
}
@ -543,8 +552,12 @@ gst_tee_do_push (GstTee * tee, GstPad * pad, GstBuffer * buffer)
if (pad == tee->pull_pad) {
/* don't push on the pad we're pulling from */
res = GST_FLOW_OK;
} else if (is_list) {
res =
gst_pad_push_list (pad,
gst_buffer_list_ref (GST_BUFFER_LIST_CAST (data)));
} else {
res = gst_pad_push (pad, gst_buffer_ref (buffer));
res = gst_pad_push (pad, gst_buffer_ref (GST_BUFFER_CAST (data)));
}
return res;
}
@ -564,13 +577,15 @@ clear_pads (GstPad * pad, GstTee * tee)
}
static GstFlowReturn
gst_tee_handle_buffer (GstTee * tee, GstBuffer * buffer)
gst_tee_handle_data (GstTee * tee, gpointer data, gboolean is_list)
{
GList *pads;
guint32 cookie;
GstFlowReturn ret, cret;
tee->offset += GST_BUFFER_SIZE (buffer);
if (!is_list) {
tee->offset += GST_BUFFER_SIZE (data);
}
GST_OBJECT_LOCK (tee);
/* mark all pads as 'not pushed on yet' */
@ -583,38 +598,38 @@ restart:
while (pads) {
GstPad *pad;
PushData *data;
PushData *pdata;
pad = GST_PAD_CAST (pads->data);
/* get the private data, something is really wrong with the internal state
* when it is not there */
data = g_object_get_qdata (G_OBJECT (pad), push_data);
pdata = g_object_get_qdata (G_OBJECT (pad), push_data);
g_assert (pdata != NULL);
g_assert (data != NULL);
if (!data->pushed) {
if (!pdata->pushed) {
/* not yet pushed, release lock and start pushing */
gst_object_ref (pad);
GST_OBJECT_UNLOCK (tee);
GST_LOG_OBJECT (tee, "Starting to push buffer %p", buffer);
GST_LOG_OBJECT (tee, "Starting to push %s %p",
is_list ? "list" : "buffer", data);
ret = gst_tee_do_push (tee, pad, buffer);
ret = gst_tee_do_push (tee, pad, data, is_list);
GST_LOG_OBJECT (tee, "Pushing buffer %p yielded result %s", buffer,
GST_LOG_OBJECT (tee, "Pushing item %p yielded result %s", data,
gst_flow_get_name (ret));
GST_OBJECT_LOCK (tee);
/* keep track of which pad we pushed and the result value. We need to do
* this before we release the refcount on the pad, the PushData is
* destroyed when the last ref of the pad goes away. */
data->pushed = TRUE;
data->result = ret;
pdata->pushed = TRUE;
pdata->result = ret;
gst_object_unref (pad);
} else {
/* already pushed, use previous return value */
ret = data->result;
ret = pdata->result;
GST_LOG_OBJECT (tee, "pad already pushed with %s",
gst_flow_get_name (ret));
}
@ -643,7 +658,7 @@ restart:
}
GST_OBJECT_UNLOCK (tee);
gst_buffer_unref (buffer);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
/* no need to unset gvalue */
return cret;
@ -652,7 +667,7 @@ restart:
error:
{
GST_DEBUG_OBJECT (tee, "received error %s", gst_flow_get_name (ret));
gst_buffer_unref (buffer);
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
GST_OBJECT_UNLOCK (tee);
return ret;
}
@ -668,7 +683,7 @@ gst_tee_chain (GstPad * pad, GstBuffer * buffer)
GST_DEBUG_OBJECT (tee, "received buffer %p", buffer);
res = gst_tee_handle_buffer (tee, buffer);
res = gst_tee_handle_data (tee, buffer, FALSE);
GST_DEBUG_OBJECT (tee, "handled buffer %s", gst_flow_get_name (res));
@ -677,6 +692,25 @@ gst_tee_chain (GstPad * pad, GstBuffer * buffer)
return res;
}
static GstFlowReturn
gst_tee_chain_list (GstPad * pad, GstBufferList * list)
{
GstFlowReturn res;
GstTee *tee;
tee = GST_TEE (gst_pad_get_parent (pad));
GST_DEBUG_OBJECT (tee, "received list %p", list);
res = gst_tee_handle_data (tee, list, TRUE);
GST_DEBUG_OBJECT (tee, "handled list %s", gst_flow_get_name (res));
gst_object_unref (tee);
return res;
}
static gboolean
gst_tee_sink_activate_push (GstPad * pad, gboolean active)
{
@ -848,7 +882,7 @@ gst_tee_src_get_range (GstPad * pad, guint64 offset, guint length,
ret = gst_pad_pull_range (tee->sinkpad, offset, length, buf);
if (ret == GST_FLOW_OK)
ret = gst_tee_handle_buffer (tee, gst_buffer_ref (*buf));
ret = gst_tee_handle_data (tee, gst_buffer_ref (*buf), FALSE);
else if (ret == GST_FLOW_UNEXPECTED)
gst_tee_pull_eos (tee);