mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-02 21:48:55 +00:00
rtpjitterbuffer: keep track of duration
Keep track of the estimated duration of missing packets and use it in the lost event. Enable another unit test
This commit is contained in:
parent
ac3bb3acf6
commit
6e4a051d40
3 changed files with 34 additions and 23 deletions
|
@ -241,6 +241,7 @@ typedef struct
|
||||||
guint16 seqnum;
|
guint16 seqnum;
|
||||||
TimerType type;
|
TimerType type;
|
||||||
GstClockTime timeout;
|
GstClockTime timeout;
|
||||||
|
GstClockTime duration;
|
||||||
GstClockTime rtx_base;
|
GstClockTime rtx_base;
|
||||||
GstClockTime rtx_retry;
|
GstClockTime rtx_retry;
|
||||||
} TimerData;
|
} TimerData;
|
||||||
|
@ -1485,7 +1486,7 @@ recalculate_timer (GstRtpJitterBuffer * jitterbuffer, TimerData * timer)
|
||||||
|
|
||||||
static TimerData *
|
static TimerData *
|
||||||
add_timer (GstRtpJitterBuffer * jitterbuffer, TimerType type,
|
add_timer (GstRtpJitterBuffer * jitterbuffer, TimerType type,
|
||||||
guint16 seqnum, GstClockTime timeout)
|
guint16 seqnum, GstClockTime timeout, GstClockTime duration)
|
||||||
{
|
{
|
||||||
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
||||||
TimerData *timer;
|
TimerData *timer;
|
||||||
|
@ -1502,6 +1503,7 @@ add_timer (GstRtpJitterBuffer * jitterbuffer, TimerType type,
|
||||||
timer->type = type;
|
timer->type = type;
|
||||||
timer->seqnum = seqnum;
|
timer->seqnum = seqnum;
|
||||||
timer->timeout = timeout;
|
timer->timeout = timeout;
|
||||||
|
timer->duration = duration;
|
||||||
if (type == TIMER_TYPE_EXPECTED) {
|
if (type == TIMER_TYPE_EXPECTED) {
|
||||||
timer->rtx_base = timeout;
|
timer->rtx_base = timeout;
|
||||||
timer->rtx_retry = 0;
|
timer->rtx_retry = 0;
|
||||||
|
@ -1560,7 +1562,7 @@ set_timer (GstRtpJitterBuffer * jitterbuffer, TimerType type,
|
||||||
/* find the seqnum timer */
|
/* find the seqnum timer */
|
||||||
timer = find_timer (jitterbuffer, type, seqnum);
|
timer = find_timer (jitterbuffer, type, seqnum);
|
||||||
if (timer == NULL) {
|
if (timer == NULL) {
|
||||||
timer = add_timer (jitterbuffer, type, seqnum, timeout);
|
timer = add_timer (jitterbuffer, type, seqnum, timeout, -1);
|
||||||
} else {
|
} else {
|
||||||
reschedule_timer (jitterbuffer, timer, seqnum, timeout);
|
reschedule_timer (jitterbuffer, timer, seqnum, timeout);
|
||||||
}
|
}
|
||||||
|
@ -1643,7 +1645,7 @@ update_timers (GstRtpJitterBuffer * jitterbuffer, guint16 seqnum,
|
||||||
reschedule_timer (jitterbuffer, timer, priv->next_in_seqnum, expected);
|
reschedule_timer (jitterbuffer, timer, priv->next_in_seqnum, expected);
|
||||||
else
|
else
|
||||||
add_timer (jitterbuffer, TIMER_TYPE_EXPECTED, priv->next_in_seqnum,
|
add_timer (jitterbuffer, TIMER_TYPE_EXPECTED, priv->next_in_seqnum,
|
||||||
expected);
|
expected, priv->packet_spacing);
|
||||||
} else if (timer && timer->type != TIMER_TYPE_DEADLINE) {
|
} else if (timer && timer->type != TIMER_TYPE_DEADLINE) {
|
||||||
/* if we had a timer, remove it, we don't know when to expect the next
|
/* if we had a timer, remove it, we don't know when to expect the next
|
||||||
* packet. */
|
* packet. */
|
||||||
|
@ -1786,7 +1788,7 @@ calculate_expected (GstRtpJitterBuffer * jitterbuffer, guint32 expected,
|
||||||
}
|
}
|
||||||
|
|
||||||
while (expected < seqnum) {
|
while (expected < seqnum) {
|
||||||
add_timer (jitterbuffer, type, expected, expected_dts);
|
add_timer (jitterbuffer, type, expected, expected_dts, duration);
|
||||||
expected_dts += duration;
|
expected_dts += duration;
|
||||||
expected++;
|
expected++;
|
||||||
}
|
}
|
||||||
|
@ -2350,7 +2352,9 @@ do_lost_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
||||||
|
|
||||||
seqnum = timer->seqnum;
|
seqnum = timer->seqnum;
|
||||||
timestamp = apply_offset (jitterbuffer, timer->timeout);
|
timestamp = apply_offset (jitterbuffer, timer->timeout);
|
||||||
duration = GST_CLOCK_TIME_NONE;
|
duration = timer->duration;
|
||||||
|
if (duration == GST_CLOCK_TIME_NONE && priv->packet_spacing > 0)
|
||||||
|
duration = priv->packet_spacing;
|
||||||
|
|
||||||
/* remove timer now */
|
/* remove timer now */
|
||||||
remove_timer (jitterbuffer, timer);
|
remove_timer (jitterbuffer, timer);
|
||||||
|
|
|
@ -319,6 +319,9 @@ elements_videocrop_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(CFLA
|
||||||
elements_videofilter_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
|
elements_videofilter_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
|
||||||
elements_videofilter_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) $(LDADD)
|
elements_videofilter_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) $(LDADD)
|
||||||
|
|
||||||
|
elements_rtpjitterbuffer_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
|
||||||
|
elements_rtpjitterbuffer_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-$(GST_API_VERSION) $(LDADD)
|
||||||
|
|
||||||
# FIXME: configure should check for gdk-pixbuf not gtk
|
# FIXME: configure should check for gdk-pixbuf not gtk
|
||||||
# only need video.h header, not the lib
|
# only need video.h header, not the lib
|
||||||
elements_gdkpixbufsink_CFLAGS = \
|
elements_gdkpixbufsink_CFLAGS = \
|
||||||
|
|
|
@ -613,17 +613,17 @@ GST_START_TEST (test_only_one_lost_event_on_large_gaps)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
#if 0
|
|
||||||
GST_START_TEST (test_two_lost_one_arrives_in_time)
|
GST_START_TEST (test_two_lost_one_arrives_in_time)
|
||||||
{
|
{
|
||||||
TestData data;
|
TestData data;
|
||||||
GstTestClockPendingID id;
|
GstClockID id;
|
||||||
guint64 timeout;
|
guint64 timeout;
|
||||||
GstBuffer *in_buf, *out_buf;
|
GstBuffer *in_buf, *out_buf;
|
||||||
GstEvent *out_event;
|
GstEvent *out_event;
|
||||||
gint jb_latency_ms = 10;
|
gint jb_latency_ms = 100;
|
||||||
GstClockTime buffer_time;
|
GstClockTime buffer_time, now;
|
||||||
gint b;
|
gint b;
|
||||||
|
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
||||||
|
|
||||||
setup_testharness (&data);
|
setup_testharness (&data);
|
||||||
timeout = 20 * G_USEC_PER_SEC;
|
timeout = 20 * G_USEC_PER_SEC;
|
||||||
|
@ -634,12 +634,11 @@ GST_START_TEST (test_two_lost_one_arrives_in_time)
|
||||||
in_buf = generate_test_buffer (0 * GST_MSECOND, TRUE, 0, 0);
|
in_buf = generate_test_buffer (0 * GST_MSECOND, TRUE, 0, 0);
|
||||||
gst_test_clock_set_time (GST_TEST_CLOCK (data.clock), 0);
|
gst_test_clock_set_time (GST_TEST_CLOCK (data.clock), 0);
|
||||||
g_assert_cmpint (gst_pad_push (data.test_src_pad, in_buf), ==, GST_FLOW_OK);
|
g_assert_cmpint (gst_pad_push (data.test_src_pad, in_buf), ==, GST_FLOW_OK);
|
||||||
g_assert (gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK
|
gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (data.clock), &id);
|
||||||
(data.clock), &id));
|
now = jb_latency_ms * GST_MSECOND;
|
||||||
gst_test_clock_set_time (GST_TEST_CLOCK (data.clock),
|
gst_test_clock_set_time (GST_TEST_CLOCK (data.clock), now);
|
||||||
jb_latency_ms * GST_MSECOND);
|
|
||||||
g_assert (gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (data.clock))
|
g_assert (gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (data.clock))
|
||||||
== id.clock_id);
|
== id);
|
||||||
out_buf = g_async_queue_timeout_pop (data.buf_queue, timeout);
|
out_buf = g_async_queue_timeout_pop (data.buf_queue, timeout);
|
||||||
g_assert (out_buf != NULL);
|
g_assert (out_buf != NULL);
|
||||||
|
|
||||||
|
@ -647,7 +646,7 @@ GST_START_TEST (test_two_lost_one_arrives_in_time)
|
||||||
for (b = 1; b < 3; b++) {
|
for (b = 1; b < 3; b++) {
|
||||||
buffer_time = b * GST_MSECOND * 20;
|
buffer_time = b * GST_MSECOND * 20;
|
||||||
in_buf = generate_test_buffer (buffer_time, TRUE, b, b * 160);
|
in_buf = generate_test_buffer (buffer_time, TRUE, b, b * 160);
|
||||||
gst_test_clock_set_time (GST_TEST_CLOCK (data.clock), buffer_time);
|
gst_test_clock_set_time (GST_TEST_CLOCK (data.clock), now + buffer_time);
|
||||||
g_assert_cmpint (gst_pad_push (data.test_src_pad, in_buf), ==, GST_FLOW_OK);
|
g_assert_cmpint (gst_pad_push (data.test_src_pad, in_buf), ==, GST_FLOW_OK);
|
||||||
|
|
||||||
// check for the buffer coming out that was pushed in
|
// check for the buffer coming out that was pushed in
|
||||||
|
@ -664,15 +663,15 @@ GST_START_TEST (test_two_lost_one_arrives_in_time)
|
||||||
|
|
||||||
// verify that the jitterbuffer now wait for the latest moment it can push
|
// verify that the jitterbuffer now wait for the latest moment it can push
|
||||||
// the first lost buffer (buffer 3) out on (buffer-timestamp (60) + latency (10) = 70)
|
// the first lost buffer (buffer 3) out on (buffer-timestamp (60) + latency (10) = 70)
|
||||||
g_assert (gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK
|
gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (data.clock), &id);
|
||||||
(data.clock), &id));
|
g_assert_cmpint (gst_clock_id_get_time (id), ==,
|
||||||
g_assert_cmpint (id.time, ==,
|
|
||||||
(3 * GST_MSECOND * 20) + (jb_latency_ms * GST_MSECOND));
|
(3 * GST_MSECOND * 20) + (jb_latency_ms * GST_MSECOND));
|
||||||
|
|
||||||
// let the time expire...
|
// let the time expire...
|
||||||
gst_test_clock_set_time (GST_TEST_CLOCK (data.clock), id.time);
|
gst_test_clock_set_time (GST_TEST_CLOCK (data.clock),
|
||||||
|
gst_clock_id_get_time (id));
|
||||||
g_assert (gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (data.clock))
|
g_assert (gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (data.clock))
|
||||||
== id.clock_id);
|
== id);
|
||||||
|
|
||||||
// we should now receive a packet-lost-event for buffer 3
|
// we should now receive a packet-lost-event for buffer 3
|
||||||
out_event = g_async_queue_timeout_pop (data.event_queue, timeout);
|
out_event = g_async_queue_timeout_pop (data.event_queue, timeout);
|
||||||
|
@ -691,13 +690,17 @@ GST_START_TEST (test_two_lost_one_arrives_in_time)
|
||||||
out_buf = g_async_queue_timeout_pop (data.buf_queue, timeout);
|
out_buf = g_async_queue_timeout_pop (data.buf_queue, timeout);
|
||||||
g_assert (out_buf != NULL);
|
g_assert (out_buf != NULL);
|
||||||
g_assert (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
|
g_assert (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
|
||||||
g_assert_cmpint (gst_rtp_buffer_get_seq (out_buf), ==, 4);
|
gst_rtp_buffer_map (out_buf, GST_MAP_READ, &rtp);
|
||||||
|
g_assert_cmpint (gst_rtp_buffer_get_seq (&rtp), ==, 4);
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
// and see that buffer 5 now arrives in a normal fashion
|
// and see that buffer 5 now arrives in a normal fashion
|
||||||
out_buf = g_async_queue_timeout_pop (data.buf_queue, timeout);
|
out_buf = g_async_queue_timeout_pop (data.buf_queue, timeout);
|
||||||
g_assert (out_buf != NULL);
|
g_assert (out_buf != NULL);
|
||||||
g_assert (!GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
|
g_assert (!GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
|
||||||
g_assert_cmpint (gst_rtp_buffer_get_seq (out_buf), ==, 5);
|
gst_rtp_buffer_map (out_buf, GST_MAP_READ, &rtp);
|
||||||
|
g_assert_cmpint (gst_rtp_buffer_get_seq (&rtp), ==, 5);
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
// should still have only seen 1 packet lost event
|
// should still have only seen 1 packet lost event
|
||||||
g_assert_cmpint (data.lost_event_count, ==, 1);
|
g_assert_cmpint (data.lost_event_count, ==, 1);
|
||||||
|
@ -707,6 +710,7 @@ GST_START_TEST (test_two_lost_one_arrives_in_time)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
#if 0
|
||||||
GST_START_TEST (test_late_packets_still_makes_lost_events)
|
GST_START_TEST (test_late_packets_still_makes_lost_events)
|
||||||
{
|
{
|
||||||
TestData data;
|
TestData data;
|
||||||
|
@ -865,8 +869,8 @@ rtpjitterbuffer_suite (void)
|
||||||
tcase_add_test (tc_chain, test_push_unordered);
|
tcase_add_test (tc_chain, test_push_unordered);
|
||||||
tcase_add_test (tc_chain, test_basetime);
|
tcase_add_test (tc_chain, test_basetime);
|
||||||
tcase_add_test (tc_chain, test_only_one_lost_event_on_large_gaps);
|
tcase_add_test (tc_chain, test_only_one_lost_event_on_large_gaps);
|
||||||
#if 0
|
|
||||||
tcase_add_test (tc_chain, test_two_lost_one_arrives_in_time);
|
tcase_add_test (tc_chain, test_two_lost_one_arrives_in_time);
|
||||||
|
#if 0
|
||||||
tcase_add_test (tc_chain, test_late_packets_still_makes_lost_events);
|
tcase_add_test (tc_chain, test_late_packets_still_makes_lost_events);
|
||||||
tcase_add_test (tc_chain, test_all_packets_are_timestamped_zero);
|
tcase_add_test (tc_chain, test_all_packets_are_timestamped_zero);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue