mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 11:45:25 +00:00
rtpbin: do more accurate buffer offsets
Return the next timestamp in the jitterbuffer. Use the min-timestamp of the jitterbuffers to calculate an offset so that the next timestamp is pushed with a timestamp equal to running_time. Start producing timestamps from 0 in the buffering case too.
This commit is contained in:
parent
3efcc0fbc1
commit
74a3be350d
5 changed files with 61 additions and 38 deletions
|
@ -6,4 +6,4 @@ VOID:UINT,OBJECT
|
||||||
VOID:UINT
|
VOID:UINT
|
||||||
VOID:UINT,UINT
|
VOID:UINT,UINT
|
||||||
VOID:OBJECT,OBJECT
|
VOID:OBJECT,OBJECT
|
||||||
VOID:BOOL,UINT64
|
UINT64:BOOL,UINT64
|
||||||
|
|
|
@ -1783,6 +1783,7 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
||||||
GSList *sessions, *streams, *elements = NULL;
|
GSList *sessions, *streams, *elements = NULL;
|
||||||
GstRtpBinStream *stream;
|
GstRtpBinStream *stream;
|
||||||
gboolean change = FALSE, active = FALSE;
|
gboolean change = FALSE, active = FALSE;
|
||||||
|
GstClockTime min_out_time;
|
||||||
|
|
||||||
gst_message_parse_buffering (message, &percent);
|
gst_message_parse_buffering (message, &percent);
|
||||||
|
|
||||||
|
@ -1847,7 +1848,7 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
||||||
if (G_UNLIKELY (change)) {
|
if (G_UNLIKELY (change)) {
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
guint64 running_time = 0;
|
guint64 running_time = 0;
|
||||||
guint64 elapsed = 0;
|
guint64 offset = 0;
|
||||||
|
|
||||||
/* figure out the running time when we have a clock */
|
/* figure out the running time when we have a clock */
|
||||||
if (G_LIKELY ((clock =
|
if (G_LIKELY ((clock =
|
||||||
|
@ -1858,35 +1859,52 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
||||||
base_time = gst_element_get_base_time (GST_ELEMENT_CAST (bin));
|
base_time = gst_element_get_base_time (GST_ELEMENT_CAST (bin));
|
||||||
running_time = now - base_time;
|
running_time = now - base_time;
|
||||||
}
|
}
|
||||||
|
GST_DEBUG_OBJECT (bin,
|
||||||
|
"running time now %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (running_time));
|
||||||
|
|
||||||
if (!active) {
|
/* when we reactivate, calculate the offsets so that all streams have
|
||||||
/* remember the time when we started buffering */
|
* an output time that is at least as big as the running_time */
|
||||||
rtpbin->buffer_start = running_time;
|
offset = 0;
|
||||||
} else {
|
if (active) {
|
||||||
/* calculate time spent in buffering */
|
if (running_time > rtpbin->buffer_start) {
|
||||||
if (running_time > rtpbin->buffer_start)
|
offset = running_time - rtpbin->buffer_start;
|
||||||
elapsed = running_time - rtpbin->buffer_start;
|
if (offset >= rtpbin->latency_ns)
|
||||||
else
|
offset -= rtpbin->latency_ns;
|
||||||
elapsed = 0;
|
else
|
||||||
/* subtract latency, if we paused for less time than the latency we
|
offset = 0;
|
||||||
* are fine. */
|
}
|
||||||
if (elapsed > rtpbin->latency_ns)
|
|
||||||
elapsed -= rtpbin->latency_ns;
|
|
||||||
else
|
|
||||||
elapsed = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
min_out_time = -1;
|
||||||
while (G_LIKELY (elements)) {
|
while (G_LIKELY (elements)) {
|
||||||
GstElement *element = elements->data;
|
GstElement *element = elements->data;
|
||||||
|
GstClockTime last_out;
|
||||||
|
|
||||||
|
g_signal_emit_by_name (element, "set-active", active, offset,
|
||||||
|
&last_out);
|
||||||
|
|
||||||
|
if (!active) {
|
||||||
|
if (last_out == -1)
|
||||||
|
last_out = 0;
|
||||||
|
if (last_out < min_out_time)
|
||||||
|
min_out_time = last_out;
|
||||||
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (bin,
|
GST_DEBUG_OBJECT (bin,
|
||||||
"setting %p to %d, elapsed %" GST_TIME_FORMAT, element, active,
|
"setting %p to %d, offset %" GST_TIME_FORMAT ", last %"
|
||||||
GST_TIME_ARGS (elapsed));
|
GST_TIME_FORMAT, element, active, GST_TIME_ARGS (offset),
|
||||||
g_signal_emit_by_name (element, "set-active", active, elapsed,
|
GST_TIME_ARGS (last_out));
|
||||||
NULL);
|
|
||||||
gst_object_unref (element);
|
gst_object_unref (element);
|
||||||
elements = g_slist_delete_link (elements, elements);
|
elements = g_slist_delete_link (elements, elements);
|
||||||
}
|
}
|
||||||
|
GST_DEBUG_OBJECT (bin,
|
||||||
|
"min out time %" GST_TIME_FORMAT, GST_TIME_ARGS (min_out_time));
|
||||||
|
|
||||||
|
/* the buffer_start is the min out time of all paused jitterbuffers */
|
||||||
|
if (!active)
|
||||||
|
rtpbin->buffer_start = min_out_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GST_BIN_CLASS (parent_class)->handle_message (bin, message);
|
GST_BIN_CLASS (parent_class)->handle_message (bin, message);
|
||||||
|
|
|
@ -268,7 +268,7 @@ static gboolean gst_rtp_jitter_buffer_query (GstPad * pad, GstQuery * query);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_jitter_buffer_clear_pt_map (GstRtpJitterBuffer * jitterbuffer);
|
gst_rtp_jitter_buffer_clear_pt_map (GstRtpJitterBuffer * jitterbuffer);
|
||||||
static void
|
static GstClockTime
|
||||||
gst_rtp_jitter_buffer_set_active (GstRtpJitterBuffer * jitterbuffer,
|
gst_rtp_jitter_buffer_set_active (GstRtpJitterBuffer * jitterbuffer,
|
||||||
gboolean active, guint64 base_time);
|
gboolean active, guint64 base_time);
|
||||||
|
|
||||||
|
@ -412,12 +412,14 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass)
|
||||||
*
|
*
|
||||||
* Start pushing out packets with the given base time. This signal is only
|
* Start pushing out packets with the given base time. This signal is only
|
||||||
* useful in buffering mode.
|
* useful in buffering mode.
|
||||||
|
*
|
||||||
|
* Returns: the time of the last pushed packet.
|
||||||
*/
|
*/
|
||||||
gst_rtp_jitter_buffer_signals[SIGNAL_SET_ACTIVE] =
|
gst_rtp_jitter_buffer_signals[SIGNAL_SET_ACTIVE] =
|
||||||
g_signal_new ("set-active", G_TYPE_FROM_CLASS (klass),
|
g_signal_new ("set-active", G_TYPE_FROM_CLASS (klass),
|
||||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||||
G_STRUCT_OFFSET (GstRtpJitterBufferClass, set_active), NULL, NULL,
|
G_STRUCT_OFFSET (GstRtpJitterBufferClass, set_active), NULL, NULL,
|
||||||
gst_rtp_bin_marshal_VOID__BOOL_UINT64, G_TYPE_NONE, 2, G_TYPE_BOOLEAN,
|
gst_rtp_bin_marshal_UINT64__BOOL_UINT64, G_TYPE_UINT64, 2, G_TYPE_BOOLEAN,
|
||||||
G_TYPE_UINT64);
|
G_TYPE_UINT64);
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
|
@ -647,29 +649,37 @@ gst_rtp_jitter_buffer_clear_pt_map (GstRtpJitterBuffer * jitterbuffer)
|
||||||
JBUF_UNLOCK (priv);
|
JBUF_UNLOCK (priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GstClockTime
|
||||||
gst_rtp_jitter_buffer_set_active (GstRtpJitterBuffer * jbuf, gboolean active,
|
gst_rtp_jitter_buffer_set_active (GstRtpJitterBuffer * jbuf, gboolean active,
|
||||||
guint64 elapsed)
|
guint64 offset)
|
||||||
{
|
{
|
||||||
GstRtpJitterBufferPrivate *priv;
|
GstRtpJitterBufferPrivate *priv;
|
||||||
|
GstClockTime last_out;
|
||||||
|
GstBuffer *head;
|
||||||
|
|
||||||
priv = jbuf->priv;
|
priv = jbuf->priv;
|
||||||
|
|
||||||
JBUF_LOCK (priv);
|
JBUF_LOCK (priv);
|
||||||
GST_DEBUG_OBJECT (jbuf, "setting active %d with elapsed %" GST_TIME_FORMAT,
|
GST_DEBUG_OBJECT (jbuf, "setting active %d with offset %" GST_TIME_FORMAT,
|
||||||
active, GST_TIME_ARGS (elapsed));
|
active, GST_TIME_ARGS (offset));
|
||||||
|
|
||||||
if (active != priv->active) {
|
if (active != priv->active) {
|
||||||
/* add the amount of time spent in paused to the output offset. All
|
/* add the amount of time spent in paused to the output offset. All
|
||||||
* outgoing buffers will have this offset applied to their timestamps in
|
* outgoing buffers will have this offset applied to their timestamps in
|
||||||
* order to make them arrive in time in the sink. */
|
* order to make them arrive in time in the sink. */
|
||||||
priv->out_offset += elapsed;
|
priv->out_offset = offset;
|
||||||
GST_DEBUG_OBJECT (jbuf, "out offset %" GST_TIME_FORMAT,
|
GST_DEBUG_OBJECT (jbuf, "out offset %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (priv->out_offset));
|
GST_TIME_ARGS (priv->out_offset));
|
||||||
priv->active = active;
|
priv->active = active;
|
||||||
JBUF_SIGNAL (priv);
|
JBUF_SIGNAL (priv);
|
||||||
}
|
}
|
||||||
|
if ((head = rtp_jitter_buffer_peek (priv->jbuf))) {
|
||||||
|
last_out = GST_BUFFER_TIMESTAMP (head);
|
||||||
|
} else
|
||||||
|
last_out = priv->last_out_time;
|
||||||
JBUF_UNLOCK (priv);
|
JBUF_UNLOCK (priv);
|
||||||
|
|
||||||
|
return last_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct _GstRtpJitterBufferClass
|
||||||
/* actions */
|
/* actions */
|
||||||
void (*clear_pt_map) (GstRtpJitterBuffer *buffer);
|
void (*clear_pt_map) (GstRtpJitterBuffer *buffer);
|
||||||
|
|
||||||
void (*set_active) (GstRtpJitterBuffer *buffer, gboolean active, guint64 elapsed);
|
GstClockTime (*set_active) (GstRtpJitterBuffer *buffer, gboolean active, guint64 elapsed);
|
||||||
|
|
||||||
/*< private > */
|
/*< private > */
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
|
|
|
@ -596,21 +596,16 @@ rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, GstBuffer * buf,
|
||||||
rtptime = gst_rtp_buffer_get_timestamp (buf);
|
rtptime = gst_rtp_buffer_get_timestamp (buf);
|
||||||
switch (jbuf->mode) {
|
switch (jbuf->mode) {
|
||||||
case RTP_JITTER_BUFFER_MODE_NONE:
|
case RTP_JITTER_BUFFER_MODE_NONE:
|
||||||
|
case RTP_JITTER_BUFFER_MODE_BUFFER:
|
||||||
/* send 0 as the first timestamp and -1 for the other ones. This will
|
/* send 0 as the first timestamp and -1 for the other ones. This will
|
||||||
* interpollate them from the RTP timestamps with a 0 origin. */
|
* interpollate them from the RTP timestamps with a 0 origin. In buffering
|
||||||
|
* mode we will adjust the outgoing timestamps according to the amount of
|
||||||
|
* time we spent buffering. */
|
||||||
if (jbuf->base_time == -1)
|
if (jbuf->base_time == -1)
|
||||||
time = 0;
|
time = 0;
|
||||||
else
|
else
|
||||||
time = -1;
|
time = -1;
|
||||||
break;
|
break;
|
||||||
case RTP_JITTER_BUFFER_MODE_BUFFER:
|
|
||||||
/* send -1 for all timestamps except the first one. This will make the
|
|
||||||
* timestamps increase according to the RTP timestamps. When in buffering
|
|
||||||
* mode we will adjust the outgoing timestamps relative with how long we
|
|
||||||
* buffered */
|
|
||||||
if (jbuf->base_time != -1)
|
|
||||||
time = -1;
|
|
||||||
break;
|
|
||||||
case RTP_JITTER_BUFFER_MODE_SLAVE:
|
case RTP_JITTER_BUFFER_MODE_SLAVE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue