mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 11:45:25 +00:00
rtpbin: more buffering work
When deactivating jitterbuffers when the buffering starts, keep the current percent of the jitterbuffer and also set the jitterbuffer in the buffering state so that we know when it's filled again. Add property to get the buffering percentage of the jitterbuffer.
This commit is contained in:
parent
e6e287cdcc
commit
8bbfd94c25
4 changed files with 119 additions and 36 deletions
|
@ -1771,7 +1771,6 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
|||
gst_structure_set ((GstStructure *) s, "session", G_TYPE_UINT,
|
||||
sess->id, NULL);
|
||||
}
|
||||
GST_RTP_BIN_UNLOCK (rtpbin);
|
||||
}
|
||||
GST_BIN_CLASS (parent_class)->handle_message (bin, message);
|
||||
break;
|
||||
|
@ -1780,7 +1779,7 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
|||
{
|
||||
gint percent;
|
||||
gint min_percent = 100;
|
||||
GSList *sessions, *streams, *elements = NULL;
|
||||
GSList *sessions, *streams;
|
||||
GstRtpBinStream *stream;
|
||||
gboolean change = FALSE, active = FALSE;
|
||||
GstClockTime min_out_time;
|
||||
|
@ -1808,7 +1807,6 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
|||
for (streams = session->streams; streams;
|
||||
streams = g_slist_next (streams)) {
|
||||
GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
|
||||
GstElement *element = stream->buffer;
|
||||
|
||||
GST_DEBUG_OBJECT (bin, "stream %p percent %d", stream,
|
||||
stream->percent);
|
||||
|
@ -1816,8 +1814,6 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
|||
/* find min percent */
|
||||
if (min_percent > stream->percent)
|
||||
min_percent = stream->percent;
|
||||
|
||||
elements = g_slist_prepend (elements, gst_object_ref (element));
|
||||
}
|
||||
GST_RTP_SESSION_UNLOCK (session);
|
||||
}
|
||||
|
@ -1863,6 +1859,8 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
|||
"running time now %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (running_time));
|
||||
|
||||
GST_RTP_BIN_LOCK (rtpbin);
|
||||
|
||||
/* when we reactivate, calculate the offsets so that all streams have
|
||||
* an output time that is at least as big as the running_time */
|
||||
offset = 0;
|
||||
|
@ -1876,28 +1874,38 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
|||
}
|
||||
}
|
||||
|
||||
/* pause all streams */
|
||||
min_out_time = -1;
|
||||
while (G_LIKELY (elements)) {
|
||||
GstElement *element = elements->data;
|
||||
GstClockTime last_out;
|
||||
for (sessions = rtpbin->sessions; sessions;
|
||||
sessions = g_slist_next (sessions)) {
|
||||
GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
|
||||
|
||||
g_signal_emit_by_name (element, "set-active", active, offset,
|
||||
&last_out);
|
||||
GST_RTP_SESSION_LOCK (session);
|
||||
for (streams = session->streams; streams;
|
||||
streams = g_slist_next (streams)) {
|
||||
GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
|
||||
GstElement *element = stream->buffer;
|
||||
guint64 last_out;
|
||||
|
||||
if (!active) {
|
||||
if (last_out == -1)
|
||||
last_out = 0;
|
||||
if (last_out < min_out_time)
|
||||
min_out_time = last_out;
|
||||
g_signal_emit_by_name (element, "set-active", active, offset,
|
||||
&last_out);
|
||||
|
||||
if (!active) {
|
||||
g_object_get (element, "percent", &stream->percent, NULL);
|
||||
|
||||
if (last_out == -1)
|
||||
last_out = 0;
|
||||
if (last_out < min_out_time)
|
||||
min_out_time = last_out;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (bin,
|
||||
"setting %p to %d, offset %" GST_TIME_FORMAT ", last %"
|
||||
GST_TIME_FORMAT ", percent %d", element, active,
|
||||
GST_TIME_ARGS (offset), GST_TIME_ARGS (last_out),
|
||||
stream->percent);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (bin,
|
||||
"setting %p to %d, offset %" GST_TIME_FORMAT ", last %"
|
||||
GST_TIME_FORMAT, element, active, GST_TIME_ARGS (offset),
|
||||
GST_TIME_ARGS (last_out));
|
||||
|
||||
gst_object_unref (element);
|
||||
elements = g_slist_delete_link (elements, elements);
|
||||
GST_RTP_SESSION_UNLOCK (session);
|
||||
}
|
||||
GST_DEBUG_OBJECT (bin,
|
||||
"min out time %" GST_TIME_FORMAT, GST_TIME_ARGS (min_out_time));
|
||||
|
@ -1905,6 +1913,8 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
|||
/* the buffer_start is the min out time of all paused jitterbuffers */
|
||||
if (!active)
|
||||
rtpbin->buffer_start = min_out_time;
|
||||
|
||||
GST_RTP_BIN_UNLOCK (rtpbin);
|
||||
}
|
||||
}
|
||||
GST_BIN_CLASS (parent_class)->handle_message (bin, message);
|
||||
|
|
|
@ -94,6 +94,7 @@ enum
|
|||
#define DEFAULT_TS_OFFSET 0
|
||||
#define DEFAULT_DO_LOST FALSE
|
||||
#define DEFAULT_MODE RTP_JITTER_BUFFER_MODE_SLAVE
|
||||
#define DEFAULT_PERCENT 0
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -103,6 +104,7 @@ enum
|
|||
PROP_TS_OFFSET,
|
||||
PROP_DO_LOST,
|
||||
PROP_MODE,
|
||||
PROP_PERCENT,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -355,6 +357,15 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass)
|
|||
g_param_spec_enum ("mode", "Mode",
|
||||
"Control the buffering algorithm in use", RTP_TYPE_JITTER_BUFFER_MODE,
|
||||
DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* GstRtpJitterBuffer::percent:
|
||||
*
|
||||
* The percent of the jitterbuffer that is filled.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_PERCENT,
|
||||
g_param_spec_int ("percent", "percent",
|
||||
"The buffer filled percent", 0, 100,
|
||||
0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* GstRtpJitterBuffer::request-pt-map:
|
||||
* @buffer: the object which received the signal
|
||||
|
@ -673,6 +684,9 @@ gst_rtp_jitter_buffer_set_active (GstRtpJitterBuffer * jbuf, gboolean active,
|
|||
priv->active = active;
|
||||
JBUF_SIGNAL (priv);
|
||||
}
|
||||
if (!active) {
|
||||
rtp_jitter_buffer_set_buffering (priv->jbuf, TRUE);
|
||||
}
|
||||
if ((head = rtp_jitter_buffer_peek (priv->jbuf))) {
|
||||
/* head buffer timestamp and offset gives our output time */
|
||||
last_out = GST_BUFFER_TIMESTAMP (head) + priv->ts_offset;
|
||||
|
@ -2131,6 +2145,20 @@ gst_rtp_jitter_buffer_get_property (GObject * object,
|
|||
g_value_set_enum (value, rtp_jitter_buffer_get_mode (priv->jbuf));
|
||||
JBUF_UNLOCK (priv);
|
||||
break;
|
||||
case PROP_PERCENT:
|
||||
{
|
||||
gint percent;
|
||||
|
||||
JBUF_LOCK (priv);
|
||||
if (priv->srcresult != GST_FLOW_OK)
|
||||
percent = 100;
|
||||
else
|
||||
percent = rtp_jitter_buffer_get_percent (priv->jbuf);
|
||||
|
||||
g_value_set_int (value, percent);
|
||||
JBUF_UNLOCK (priv);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -162,7 +162,7 @@ rtp_jitter_buffer_set_delay (RTPJitterBuffer * jbuf, GstClockTime delay)
|
|||
jbuf->high_level = (delay * 90) / 100;
|
||||
|
||||
GST_DEBUG ("delay %" GST_TIME_FORMAT ", min %" GST_TIME_FORMAT ", max %"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (jbuf->level),
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (jbuf->delay),
|
||||
GST_TIME_ARGS (jbuf->low_level), GST_TIME_ARGS (jbuf->high_level));
|
||||
}
|
||||
|
||||
|
@ -209,17 +209,17 @@ rtp_jitter_buffer_resync (RTPJitterBuffer * jbuf, GstClockTime time,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_buffer_level (RTPJitterBuffer * jbuf, gint * percent)
|
||||
static guint64
|
||||
get_buffer_level (RTPJitterBuffer * jbuf)
|
||||
{
|
||||
GstBuffer *high_buf, *low_buf;
|
||||
gboolean post = FALSE;
|
||||
guint64 level;
|
||||
|
||||
high_buf = g_queue_peek_head (jbuf->packets);
|
||||
low_buf = g_queue_peek_tail (jbuf->packets);
|
||||
|
||||
if (!high_buf || !low_buf || high_buf == low_buf) {
|
||||
jbuf->level = 0;
|
||||
level = 0;
|
||||
} else {
|
||||
guint64 high_ts, low_ts;
|
||||
|
||||
|
@ -227,20 +227,30 @@ update_buffer_level (RTPJitterBuffer * jbuf, gint * percent)
|
|||
low_ts = GST_BUFFER_TIMESTAMP (low_buf);
|
||||
|
||||
if (high_ts > low_ts)
|
||||
jbuf->level = high_ts - low_ts;
|
||||
level = high_ts - low_ts;
|
||||
else
|
||||
jbuf->level = 0;
|
||||
level = 0;
|
||||
}
|
||||
GST_DEBUG ("buffer level %" GST_TIME_FORMAT, GST_TIME_ARGS (jbuf->level));
|
||||
return level;
|
||||
}
|
||||
|
||||
static void
|
||||
update_buffer_level (RTPJitterBuffer * jbuf, gint * percent)
|
||||
{
|
||||
gboolean post = FALSE;
|
||||
guint64 level;
|
||||
|
||||
level = get_buffer_level (jbuf);
|
||||
GST_DEBUG ("buffer level %" GST_TIME_FORMAT, GST_TIME_ARGS (level));
|
||||
|
||||
if (jbuf->buffering) {
|
||||
post = TRUE;
|
||||
if (jbuf->level > jbuf->high_level) {
|
||||
if (level > jbuf->high_level) {
|
||||
GST_DEBUG ("buffering finished");
|
||||
jbuf->buffering = FALSE;
|
||||
}
|
||||
} else {
|
||||
if (jbuf->level < jbuf->low_level) {
|
||||
if (level < jbuf->low_level) {
|
||||
GST_DEBUG ("buffering started");
|
||||
jbuf->buffering = TRUE;
|
||||
post = TRUE;
|
||||
|
@ -250,7 +260,7 @@ update_buffer_level (RTPJitterBuffer * jbuf, gint * percent)
|
|||
gint perc;
|
||||
|
||||
if (jbuf->buffering) {
|
||||
perc = (jbuf->level * 100 / jbuf->high_level);
|
||||
perc = (level * 100 / jbuf->high_level);
|
||||
perc = MIN (perc, 100);
|
||||
} else {
|
||||
perc = 100;
|
||||
|
@ -323,7 +333,7 @@ update_buffer_level (RTPJitterBuffer * jbuf, gint * percent)
|
|||
*/
|
||||
static GstClockTime
|
||||
calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time,
|
||||
guint32 clock_rate, GstClockTime max_delay)
|
||||
guint32 clock_rate)
|
||||
{
|
||||
guint64 ext_rtptime;
|
||||
guint64 send_diff, recv_diff;
|
||||
|
@ -723,6 +733,40 @@ rtp_jitter_buffer_is_buffering (RTPJitterBuffer * jbuf)
|
|||
return jbuf->buffering;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtp_jitter_buffer_set_buffering:
|
||||
* @jbuf: an #RTPJitterBuffer
|
||||
* @buffering: the new buffering state
|
||||
*
|
||||
* Forces @jbuf to go into the buffering state.
|
||||
*/
|
||||
void
|
||||
rtp_jitter_buffer_set_buffering (RTPJitterBuffer * jbuf, gboolean buffering)
|
||||
{
|
||||
jbuf->buffering = buffering;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtp_jitter_buffer_get_percent:
|
||||
* @jbuf: an #RTPJitterBuffer
|
||||
*
|
||||
* Get the buffering percent of the jitterbuffer.
|
||||
*
|
||||
* Returns: the buffering percent
|
||||
*/
|
||||
gint
|
||||
rtp_jitter_buffer_get_percent (RTPJitterBuffer * jbuf)
|
||||
{
|
||||
gint percent;
|
||||
guint64 level;
|
||||
|
||||
level = get_buffer_level (jbuf);
|
||||
percent = (level * 100 / jbuf->high_level);
|
||||
percent = MIN (percent, 100);
|
||||
|
||||
return percent;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtp_jitter_buffer_num_packets:
|
||||
* @jbuf: an #RTPJitterBuffer
|
||||
|
|
|
@ -75,7 +75,6 @@ struct _RTPJitterBuffer {
|
|||
|
||||
/* for buffering */
|
||||
gboolean buffering;
|
||||
guint64 level;
|
||||
guint64 low_level;
|
||||
guint64 high_level;
|
||||
|
||||
|
@ -123,6 +122,8 @@ GstBuffer * rtp_jitter_buffer_pop (RTPJitterBuffer *jbuf,
|
|||
void rtp_jitter_buffer_flush (RTPJitterBuffer *jbuf);
|
||||
|
||||
gboolean rtp_jitter_buffer_is_buffering (RTPJitterBuffer * jbuf);
|
||||
void rtp_jitter_buffer_set_buffering (RTPJitterBuffer * jbuf, gboolean buffering);
|
||||
gint rtp_jitter_buffer_get_percent (RTPJitterBuffer * jbuf);
|
||||
|
||||
guint rtp_jitter_buffer_num_packets (RTPJitterBuffer *jbuf);
|
||||
guint32 rtp_jitter_buffer_get_ts_diff (RTPJitterBuffer *jbuf);
|
||||
|
|
Loading…
Reference in a new issue