mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 11:45:25 +00:00
rtpjitterbuffer: Add a faststart-min-packets property
When set this property will allow the jitterbuffer to start delivering packets as soon as N most recent packets have consecutive seqnum. A faststart-min-packets of zero disables this feature. This heuristic is also used in rtpsource which implements the probation mechanism and a similar heuristic is used to handle long gaps. https://bugzilla.gnome.org/show_bug.cgi?id=769536
This commit is contained in:
parent
244c7017ee
commit
bbe0053f8a
3 changed files with 107 additions and 1 deletions
|
@ -149,6 +149,7 @@ enum
|
|||
#define DEFAULT_MAX_DROPOUT_TIME 60000
|
||||
#define DEFAULT_MAX_MISORDER_TIME 2000
|
||||
#define DEFAULT_RFC7273_SYNC FALSE
|
||||
#define DEFAULT_FASTSTART_MIN_PACKETS 0
|
||||
|
||||
#define DEFAULT_AUTO_RTX_DELAY (20 * GST_MSECOND)
|
||||
#define DEFAULT_AUTO_RTX_TIMEOUT (40 * GST_MSECOND)
|
||||
|
@ -177,7 +178,8 @@ enum
|
|||
PROP_MAX_RTCP_RTP_TIME_DIFF,
|
||||
PROP_MAX_DROPOUT_TIME,
|
||||
PROP_MAX_MISORDER_TIME,
|
||||
PROP_RFC7273_SYNC
|
||||
PROP_RFC7273_SYNC,
|
||||
PROP_FASTSTART_MIN_PACKETS
|
||||
};
|
||||
|
||||
#define JBUF_LOCK(priv) G_STMT_START { \
|
||||
|
@ -294,6 +296,7 @@ struct _GstRtpJitterBufferPrivate
|
|||
gint max_rtcp_rtp_time_diff;
|
||||
guint32 max_dropout_time;
|
||||
guint32 max_misorder_time;
|
||||
guint faststart_min_packets;
|
||||
|
||||
/* the last seqnum we pushed out */
|
||||
guint32 last_popped_seqnum;
|
||||
|
@ -851,6 +854,23 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass)
|
|||
"(requires clock and offset to be provided)", DEFAULT_RFC7273_SYNC,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstRtpJitterBuffer:faststart-min-packets
|
||||
*
|
||||
* The number of consecutive packets needed to start (set to 0 to
|
||||
* disable faststart. The jitterbuffer will by default start after the
|
||||
* latency has elapsed)
|
||||
*
|
||||
* Since: 1.14
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_FASTSTART_MIN_PACKETS,
|
||||
g_param_spec_uint ("faststart-min-packets", "Faststart minimum packets",
|
||||
"The number of consecutive packets needed to start (set to 0 to "
|
||||
"disable faststart. The jitterbuffer will by default start after "
|
||||
"the latency has elapsed)",
|
||||
0, G_MAXUINT, DEFAULT_FASTSTART_MIN_PACKETS,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstRtpJitterBuffer::request-pt-map:
|
||||
* @buffer: the object which received the signal
|
||||
|
@ -975,6 +995,7 @@ gst_rtp_jitter_buffer_init (GstRtpJitterBuffer * jitterbuffer)
|
|||
priv->max_rtcp_rtp_time_diff = DEFAULT_MAX_RTCP_RTP_TIME_DIFF;
|
||||
priv->max_dropout_time = DEFAULT_MAX_DROPOUT_TIME;
|
||||
priv->max_misorder_time = DEFAULT_MAX_MISORDER_TIME;
|
||||
priv->faststart_min_packets = DEFAULT_FASTSTART_MIN_PACKETS;
|
||||
|
||||
priv->last_dts = -1;
|
||||
priv->last_rtptime = -1;
|
||||
|
@ -2784,6 +2805,37 @@ gst_rtp_jitter_buffer_reset (GstRtpJitterBuffer * jitterbuffer,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rtp_jitter_buffer_fast_start (GstRtpJitterBuffer * jitterbuffer)
|
||||
{
|
||||
GstRtpJitterBufferPrivate *priv;
|
||||
RTPJitterBufferItem *item;
|
||||
TimerData *timer;
|
||||
|
||||
priv = jitterbuffer->priv;
|
||||
|
||||
if (priv->faststart_min_packets == 0)
|
||||
return FALSE;
|
||||
|
||||
item = rtp_jitter_buffer_peek (priv->jbuf);
|
||||
if (!item)
|
||||
return FALSE;
|
||||
|
||||
timer = find_timer (jitterbuffer, item->seqnum);
|
||||
if (!timer || timer->type != TIMER_TYPE_DEADLINE)
|
||||
return FALSE;
|
||||
|
||||
if (rtp_jitter_buffer_can_fast_start (priv->jbuf,
|
||||
priv->faststart_min_packets)) {
|
||||
GST_INFO_OBJECT (jitterbuffer, "We found %i consecutive packet, start now",
|
||||
priv->faststart_min_packets);
|
||||
timer->timeout = -1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
|
||||
GstBuffer * buffer)
|
||||
|
@ -3096,6 +3148,10 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
|
|||
goto duplicate;
|
||||
}
|
||||
|
||||
/* Trigger fast start if needed */
|
||||
if (gst_rtp_jitter_buffer_fast_start (jitterbuffer))
|
||||
head = TRUE;
|
||||
|
||||
/* update timers */
|
||||
update_timers (jitterbuffer, seqnum, dts, pts, do_next_seqnum,
|
||||
GST_BUFFER_IS_RETRANSMISSION (buffer), timer);
|
||||
|
@ -4514,6 +4570,11 @@ gst_rtp_jitter_buffer_set_property (GObject * object,
|
|||
g_value_get_boolean (value));
|
||||
JBUF_UNLOCK (priv);
|
||||
break;
|
||||
case PROP_FASTSTART_MIN_PACKETS:
|
||||
JBUF_LOCK (priv);
|
||||
priv->faststart_min_packets = g_value_get_uint (value);
|
||||
JBUF_UNLOCK (priv);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -4650,6 +4711,11 @@ gst_rtp_jitter_buffer_get_property (GObject * object,
|
|||
rtp_jitter_buffer_get_rfc7273_sync (priv->jbuf));
|
||||
JBUF_UNLOCK (priv);
|
||||
break;
|
||||
case PROP_FASTSTART_MIN_PACKETS:
|
||||
JBUF_LOCK (priv);
|
||||
g_value_set_uint (value, priv->faststart_min_packets);
|
||||
JBUF_UNLOCK (priv);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -1257,3 +1257,41 @@ rtp_jitter_buffer_get_sync (RTPJitterBuffer * jbuf, guint64 * rtptime,
|
|||
if (last_rtptime)
|
||||
*last_rtptime = jbuf->last_rtptime;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtp_jitter_buffer_can_fast_start:
|
||||
* @jbuf: an #RTPJitterBuffer
|
||||
* @num_packets: Number of consecutive packets needed
|
||||
*
|
||||
* Check if in the queue if there is enough packets with consecutive seqnum in
|
||||
* order to start delivering them.
|
||||
*
|
||||
* Returns: %TRUE if the required number of consecutive packets was found.
|
||||
*/
|
||||
gboolean
|
||||
rtp_jitter_buffer_can_fast_start (RTPJitterBuffer * jbuf, gint num_packet)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
RTPJitterBufferItem *last_item = NULL, *item;
|
||||
gint i;
|
||||
|
||||
if (rtp_jitter_buffer_num_packets (jbuf) < num_packet)
|
||||
return FALSE;
|
||||
|
||||
item = rtp_jitter_buffer_peek (jbuf);
|
||||
for (i = 0; i < num_packet; i++) {
|
||||
if (G_LIKELY (last_item)) {
|
||||
guint16 expected_seqnum = last_item->seqnum + 1;
|
||||
|
||||
if (expected_seqnum != item->seqnum) {
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
last_item = item;
|
||||
item = (RTPJitterBufferItem *) last_item->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -192,4 +192,6 @@ void rtp_jitter_buffer_get_sync (RTPJitterBuffer *jbuf,
|
|||
GstClockTime rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts, gboolean estimated_dts,
|
||||
guint32 rtptime, GstClockTime base_time);
|
||||
|
||||
gboolean rtp_jitter_buffer_can_fast_start (RTPJitterBuffer * jbuf, gint num_packet);
|
||||
|
||||
#endif /* __RTP_JITTER_BUFFER_H__ */
|
||||
|
|
Loading…
Reference in a new issue