rtpbasedepayload: provide chain_list function on sink pad

Implement a chain_list function, which avoids lots of locking
compared to the default fallback implementation in GstPad.
We may also want to do some more sophisticated timestamp
tracking here at some point, but for now leave it up to the
jitterbuffer and/or subclasses (in case buffers in the
buffer list have no timestamp set on them, there may only
be a timestamp for the whole list on the first buffer).
This provides the exact same behaviour as the default
fallback implementation.
This commit is contained in:
Tim-Philipp Müller 2015-05-21 13:59:55 +01:00
parent dcfb8a83a5
commit bc309a100f
2 changed files with 67 additions and 13 deletions

View file

@ -78,6 +78,8 @@ static void gst_rtp_base_depayload_get_property (GObject * object,
static GstFlowReturn gst_rtp_base_depayload_chain (GstPad * pad,
GstObject * parent, GstBuffer * in);
static GstFlowReturn gst_rtp_base_depayload_chain_list (GstPad * pad,
GstObject * parent, GstBufferList * list);
static gboolean gst_rtp_base_depayload_handle_sink_event (GstPad * pad,
GstObject * parent, GstEvent * event);
@ -227,6 +229,8 @@ gst_rtp_base_depayload_init (GstRTPBaseDepayload * filter,
g_return_if_fail (pad_template != NULL);
filter->sinkpad = gst_pad_new_from_template (pad_template, "sink");
gst_pad_set_chain_function (filter->sinkpad, gst_rtp_base_depayload_chain);
gst_pad_set_chain_list_function (filter->sinkpad,
gst_rtp_base_depayload_chain_list);
gst_pad_set_event_function (filter->sinkpad,
gst_rtp_base_depayload_handle_sink_event);
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
@ -342,11 +346,10 @@ caps_not_changed:
}
static GstFlowReturn
gst_rtp_base_depayload_chain (GstPad * pad, GstObject * parent, GstBuffer * in)
gst_rtp_base_depayload_handle_buffer (GstRTPBaseDepayload * filter,
GstRTPBaseDepayloadClass * bclass, GstBuffer * in)
{
GstRTPBaseDepayload *filter;
GstRTPBaseDepayloadPrivate *priv;
GstRTPBaseDepayloadClass *bclass;
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *out_buf;
GstClockTime pts, dts;
@ -356,7 +359,6 @@ gst_rtp_base_depayload_chain (GstPad * pad, GstObject * parent, GstBuffer * in)
gint gap;
GstRTPBuffer rtp = { NULL };
filter = GST_RTP_BASE_DEPAYLOAD (parent);
priv = filter->priv;
/* we must have a setcaps first */
@ -440,8 +442,6 @@ gst_rtp_base_depayload_chain (GstPad * pad, GstObject * parent, GstBuffer * in)
filter->need_newsegment = FALSE;
}
bclass = GST_RTP_BASE_DEPAYLOAD_GET_CLASS (filter);
if (G_UNLIKELY (bclass->process == NULL))
goto no_process;
@ -450,7 +450,6 @@ gst_rtp_base_depayload_chain (GstPad * pad, GstObject * parent, GstBuffer * in)
if (out_buf) {
ret = gst_rtp_base_depayload_push (filter, out_buf);
}
gst_buffer_unref (in);
return ret;
@ -466,7 +465,6 @@ not_negotiated:
"element before the depayloader and setting the 'caps' property "
"on that. Also see http://cgit.freedesktop.org/gstreamer/"
"gst-plugins-good/tree/gst/rtp/README"));
gst_buffer_unref (in);
return GST_FLOW_NOT_NEGOTIATED;
}
invalid_buffer:
@ -474,13 +472,11 @@ invalid_buffer:
/* this is not fatal but should be filtered earlier */
GST_ELEMENT_WARNING (filter, STREAM, DECODE, (NULL),
("Received invalid RTP payload, dropping"));
gst_buffer_unref (in);
return GST_FLOW_OK;
}
dropping:
{
GST_WARNING_OBJECT (filter, "%d <= 100, dropping old packet", gap);
gst_buffer_unref (in);
return GST_FLOW_OK;
}
no_process:
@ -488,11 +484,68 @@ no_process:
/* this is not fatal but should be filtered earlier */
GST_ELEMENT_ERROR (filter, STREAM, NOT_IMPLEMENTED, (NULL),
("The subclass does not have a process method"));
gst_buffer_unref (in);
return GST_FLOW_ERROR;
}
}
static GstFlowReturn
gst_rtp_base_depayload_chain (GstPad * pad, GstObject * parent, GstBuffer * in)
{
GstRTPBaseDepayloadClass *bclass;
GstRTPBaseDepayload *basedepay;
GstFlowReturn flow_ret;
basedepay = GST_RTP_BASE_DEPAYLOAD_CAST (parent);
bclass = GST_RTP_BASE_DEPAYLOAD_GET_CLASS (basedepay);
flow_ret = gst_rtp_base_depayload_handle_buffer (basedepay, bclass, in);
gst_buffer_unref (in);
return flow_ret;
}
static GstFlowReturn
gst_rtp_base_depayload_chain_list (GstPad * pad, GstObject * parent,
GstBufferList * list)
{
GstRTPBaseDepayloadClass *bclass;
GstRTPBaseDepayload *basedepay;
GstFlowReturn flow_ret;
GstBuffer *buffer;
guint i, len;
basedepay = GST_RTP_BASE_DEPAYLOAD_CAST (parent);
bclass = GST_RTP_BASE_DEPAYLOAD_GET_CLASS (basedepay);
flow_ret = GST_FLOW_OK;
/* chain each buffer in list individually */
len = gst_buffer_list_length (list);
if (len == 0)
goto done;
for (i = 0; i < len; i++) {
buffer = gst_buffer_list_get (list, i);
/* Should we fix up any missing timestamps for list buffers here
* (e.g. set to first or previous timestamp in list) or just assume
* the's a jitterbuffer that will have done that for us? */
flow_ret = gst_rtp_base_depayload_handle_buffer (basedepay, bclass, buffer);
if (flow_ret != GST_FLOW_OK)
break;
}
done:
gst_buffer_list_unref (list);
return flow_ret;
}
static gboolean
gst_rtp_base_depayload_handle_event (GstRTPBaseDepayload * filter,
GstEvent * event)

View file

@ -36,9 +36,10 @@ G_BEGIN_DECLS
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_BASE_DEPAYLOAD))
#define GST_IS_RTP_BASE_DEPAYLOAD_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_BASE_DEPAYLOAD))
#define GST_RTP_BASE_DEPAYLOAD_CAST(obj) ((GstRTPBaseDepayload *)(obj))
#define GST_RTP_BASE_DEPAYLOAD_SINKPAD(depayload) (GST_RTP_BASE_DEPAYLOAD (depayload)->sinkpad)
#define GST_RTP_BASE_DEPAYLOAD_SRCPAD(depayload) (GST_RTP_BASE_DEPAYLOAD (depayload)->srcpad)
#define GST_RTP_BASE_DEPAYLOAD_SINKPAD(depayload) (GST_RTP_BASE_DEPAYLOAD_CAST (depayload)->sinkpad)
#define GST_RTP_BASE_DEPAYLOAD_SRCPAD(depayload) (GST_RTP_BASE_DEPAYLOAD_CAST (depayload)->srcpad)
typedef struct _GstRTPBaseDepayload GstRTPBaseDepayload;
typedef struct _GstRTPBaseDepayloadClass GstRTPBaseDepayloadClass;