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:
Wim Taymans 2009-10-08 19:23:53 +02:00
parent 3efcc0fbc1
commit 74a3be350d
5 changed files with 61 additions and 38 deletions

View file

@ -6,4 +6,4 @@ VOID:UINT,OBJECT
VOID:UINT
VOID:UINT,UINT
VOID:OBJECT,OBJECT
VOID:BOOL,UINT64
UINT64:BOOL,UINT64

View file

@ -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);

View file

@ -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 *

View file

@ -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];

View file

@ -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;