rtpdtmfmux: Drop buffers on non-priority sinks when something is incoming on the priority sink

This commit is contained in:
Olivier Crête 2010-05-06 19:51:59 -04:00 committed by Tim-Philipp Müller
parent f6548fe9b6
commit 70097866de
2 changed files with 70 additions and 13 deletions

View file

@ -94,6 +94,8 @@ static void gst_rtp_dtmf_mux_dispose (GObject * object);
static GstPad *gst_rtp_dtmf_mux_request_new_pad (GstElement * element, static GstPad *gst_rtp_dtmf_mux_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * name); GstPadTemplate * templ, const gchar * name);
static void gst_rtp_dtmf_mux_release_pad (GstElement * element, GstPad * pad); static void gst_rtp_dtmf_mux_release_pad (GstElement * element, GstPad * pad);
static GstStateChangeReturn gst_rtp_dtmf_mux_change_state (GstElement * element,
GstStateChange transition);
static gboolean gst_rtp_dtmf_mux_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_rtp_dtmf_mux_sink_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_rtp_dtmf_mux_chain (GstPad * pad, GstBuffer * buffer); static GstFlowReturn gst_rtp_dtmf_mux_chain (GstPad * pad, GstBuffer * buffer);
@ -145,6 +147,8 @@ gst_rtp_dtmf_mux_class_init (GstRTPDTMFMuxClass * klass)
GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_request_new_pad); GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_request_new_pad);
gstelement_class->release_pad = gstelement_class->release_pad =
GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_release_pad); GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_release_pad);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_change_state);
gstrtpmux_class->chain_func = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_chain); gstrtpmux_class->chain_func = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_chain);
gstrtpmux_class->sink_event_func = gstrtpmux_class->sink_event_func =
GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_sink_event); GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_sink_event);
@ -171,28 +175,56 @@ static GstFlowReturn
gst_rtp_dtmf_mux_chain (GstPad * pad, GstBuffer * buffer) gst_rtp_dtmf_mux_chain (GstPad * pad, GstBuffer * buffer)
{ {
GstRTPDTMFMux *mux; GstRTPDTMFMux *mux;
GstFlowReturn ret; GstFlowReturn ret = GST_FLOW_ERROR;
GstRTPMuxPadPrivate *padpriv = NULL;
GstClockTime running_ts;
mux = GST_RTP_DTMF_MUX (gst_pad_get_parent (pad)); mux = GST_RTP_DTMF_MUX (gst_pad_get_parent (pad));
running_ts = GST_BUFFER_TIMESTAMP (buffer);
GST_OBJECT_LOCK (mux); GST_OBJECT_LOCK (mux);
if (mux->special_pad != NULL && mux->special_pad != pad) { if (GST_CLOCK_TIME_IS_VALID (running_ts)) {
/* Drop the buffer */ padpriv = gst_pad_get_element_private (pad);
gst_buffer_unref (buffer); if (padpriv && padpriv->segment.format == GST_FORMAT_TIME)
ret = GST_FLOW_OK; running_ts = gst_segment_to_running_time (&padpriv->segment,
GST_OBJECT_UNLOCK (mux); GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer));
if (padpriv && padpriv->priority) {
if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
if (GST_CLOCK_TIME_IS_VALID (mux->last_priority_end))
mux->last_priority_end =
MAX (running_ts + GST_BUFFER_DURATION (buffer),
mux->last_priority_end);
else
mux->last_priority_end = running_ts + GST_BUFFER_DURATION (buffer);
}
} else { } else {
GST_OBJECT_UNLOCK (mux); if (GST_CLOCK_TIME_IS_VALID (mux->last_priority_end) &&
if (parent_class->chain_func) running_ts < mux->last_priority_end)
ret = parent_class->chain_func (pad, buffer); goto drop_buffer;
else {
gst_buffer_unref (buffer);
ret = GST_FLOW_ERROR;
} }
} }
if (mux->special_pad != NULL && mux->special_pad != pad)
goto drop_buffer;
GST_OBJECT_UNLOCK (mux);
if (parent_class->chain_func)
ret = parent_class->chain_func (pad, buffer);
else
gst_buffer_unref (buffer);
out:
gst_object_unref (mux); gst_object_unref (mux);
return ret; return ret;
drop_buffer:
gst_buffer_unref (buffer);
ret = GST_FLOW_OK;
GST_OBJECT_UNLOCK (mux);
goto out;
} }
static void static void
@ -347,6 +379,29 @@ gst_rtp_dtmf_mux_release_pad (GstElement * element, GstPad * pad)
GST_CALL_PARENT (GST_ELEMENT_CLASS, release_pad, (element, pad)); GST_CALL_PARENT (GST_ELEMENT_CLASS, release_pad, (element, pad));
} }
static GstStateChangeReturn
gst_rtp_dtmf_mux_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret;
GstRTPDTMFMux *mux = GST_RTP_DTMF_MUX (element);
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
{
GST_OBJECT_LOCK (mux);
mux->last_priority_end = GST_CLOCK_TIME_NONE;
GST_OBJECT_UNLOCK (mux);
break;
}
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
return ret;
}
gboolean gboolean
gst_rtp_dtmf_mux_plugin_init (GstPlugin * plugin) gst_rtp_dtmf_mux_plugin_init (GstPlugin * plugin)
{ {

View file

@ -50,6 +50,8 @@ struct _GstRTPDTMFMux
/* Protected by object lock */ /* Protected by object lock */
/* our special pad */ /* our special pad */
GstPad *special_pad; GstPad *special_pad;
GstClockTime last_priority_end;
}; };
struct _GstRTPDTMFMuxClass struct _GstRTPDTMFMuxClass