mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +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,UINT
|
||||
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;
|
||||
GstRtpBinStream *stream;
|
||||
gboolean change = FALSE, active = FALSE;
|
||||
GstClockTime min_out_time;
|
||||
|
||||
gst_message_parse_buffering (message, &percent);
|
||||
|
||||
|
@ -1847,7 +1848,7 @@ gst_rtp_bin_handle_message (GstBin * bin, GstMessage * message)
|
|||
if (G_UNLIKELY (change)) {
|
||||
GstClock *clock;
|
||||
guint64 running_time = 0;
|
||||
guint64 elapsed = 0;
|
||||
guint64 offset = 0;
|
||||
|
||||
/* figure out the running time when we have a 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));
|
||||
running_time = now - base_time;
|
||||
}
|
||||
GST_DEBUG_OBJECT (bin,
|
||||
"running time now %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (running_time));
|
||||
|
||||
if (!active) {
|
||||
/* remember the time when we started buffering */
|
||||
rtpbin->buffer_start = running_time;
|
||||
} else {
|
||||
/* calculate time spent in buffering */
|
||||
if (running_time > rtpbin->buffer_start)
|
||||
elapsed = running_time - rtpbin->buffer_start;
|
||||
else
|
||||
elapsed = 0;
|
||||
/* subtract latency, if we paused for less time than the latency we
|
||||
* are fine. */
|
||||
if (elapsed > rtpbin->latency_ns)
|
||||
elapsed -= rtpbin->latency_ns;
|
||||
else
|
||||
elapsed = 0;
|
||||
/* 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;
|
||||
if (active) {
|
||||
if (running_time > rtpbin->buffer_start) {
|
||||
offset = running_time - rtpbin->buffer_start;
|
||||
if (offset >= rtpbin->latency_ns)
|
||||
offset -= rtpbin->latency_ns;
|
||||
else
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
min_out_time = -1;
|
||||
while (G_LIKELY (elements)) {
|
||||
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,
|
||||
"setting %p to %d, elapsed %" GST_TIME_FORMAT, element, active,
|
||||
GST_TIME_ARGS (elapsed));
|
||||
g_signal_emit_by_name (element, "set-active", active, elapsed,
|
||||
NULL);
|
||||
"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_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);
|
||||
|
|
|
@ -268,7 +268,7 @@ static gboolean gst_rtp_jitter_buffer_query (GstPad * pad, GstQuery * query);
|
|||
|
||||
static void
|
||||
gst_rtp_jitter_buffer_clear_pt_map (GstRtpJitterBuffer * jitterbuffer);
|
||||
static void
|
||||
static GstClockTime
|
||||
gst_rtp_jitter_buffer_set_active (GstRtpJitterBuffer * jitterbuffer,
|
||||
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
|
||||
* useful in buffering mode.
|
||||
*
|
||||
* Returns: the time of the last pushed packet.
|
||||
*/
|
||||
gst_rtp_jitter_buffer_signals[SIGNAL_SET_ACTIVE] =
|
||||
g_signal_new ("set-active", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
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);
|
||||
|
||||
gstelement_class->change_state =
|
||||
|
@ -647,29 +649,37 @@ gst_rtp_jitter_buffer_clear_pt_map (GstRtpJitterBuffer * jitterbuffer)
|
|||
JBUF_UNLOCK (priv);
|
||||
}
|
||||
|
||||
static void
|
||||
static GstClockTime
|
||||
gst_rtp_jitter_buffer_set_active (GstRtpJitterBuffer * jbuf, gboolean active,
|
||||
guint64 elapsed)
|
||||
guint64 offset)
|
||||
{
|
||||
GstRtpJitterBufferPrivate *priv;
|
||||
GstClockTime last_out;
|
||||
GstBuffer *head;
|
||||
|
||||
priv = jbuf->priv;
|
||||
|
||||
JBUF_LOCK (priv);
|
||||
GST_DEBUG_OBJECT (jbuf, "setting active %d with elapsed %" GST_TIME_FORMAT,
|
||||
active, GST_TIME_ARGS (elapsed));
|
||||
GST_DEBUG_OBJECT (jbuf, "setting active %d with offset %" GST_TIME_FORMAT,
|
||||
active, GST_TIME_ARGS (offset));
|
||||
|
||||
if (active != priv->active) {
|
||||
/* add the amount of time spent in paused to the output offset. All
|
||||
* outgoing buffers will have this offset applied to their timestamps in
|
||||
* 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_TIME_ARGS (priv->out_offset));
|
||||
priv->active = active;
|
||||
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);
|
||||
|
||||
return last_out;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
|
|
|
@ -77,7 +77,7 @@ struct _GstRtpJitterBufferClass
|
|||
/* actions */
|
||||
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 > */
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
|
|
|
@ -596,21 +596,16 @@ rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, GstBuffer * buf,
|
|||
rtptime = gst_rtp_buffer_get_timestamp (buf);
|
||||
switch (jbuf->mode) {
|
||||
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
|
||||
* 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)
|
||||
time = 0;
|
||||
else
|
||||
time = -1;
|
||||
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:
|
||||
default:
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue