mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
rtp: fix gst_rtp_buffer_ext_timestamp taking into account backwards
If timestamp goes forwards more than allowed, we consider that the timestamp belongs to the previous counting, so the extended timestamp is unwrapped. https://bugzilla.gnome.org/show_bug.cgi?id=783443
This commit is contained in:
parent
c56323e821
commit
bae3636197
3 changed files with 127 additions and 14 deletions
|
@ -1252,18 +1252,21 @@ gst_rtp_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2)
|
|||
* @exttimestamp: a previous extended timestamp
|
||||
* @timestamp: a new timestamp
|
||||
*
|
||||
* Update the @exttimestamp field with @timestamp. For the first call of the
|
||||
* method, @exttimestamp should point to a location with a value of -1.
|
||||
* Update the @exttimestamp field with the extended timestamp of @timestamp
|
||||
* For the first call of the method, @exttimestamp should point to a location
|
||||
* with a value of -1.
|
||||
*
|
||||
* This function makes sure that the returned value is a constantly increasing
|
||||
* value even in the case where there is a timestamp wraparound.
|
||||
* This function is able to handle both forward and backward timestamps taking
|
||||
* into account:
|
||||
* - timestamp wraparound making sure that the returned value is properly increased.
|
||||
* - timestamp unwraparound making sure that the returned value is properly decreased.
|
||||
*
|
||||
* Returns: The extended timestamp of @timestamp.
|
||||
* Returns: The extended timestamp of @timestamp or 0 if the result can't go anywhere backwards.
|
||||
*/
|
||||
guint64
|
||||
gst_rtp_buffer_ext_timestamp (guint64 * exttimestamp, guint32 timestamp)
|
||||
{
|
||||
guint64 result, diff, ext;
|
||||
guint64 result, ext;
|
||||
|
||||
g_return_val_if_fail (exttimestamp != NULL, -1);
|
||||
|
||||
|
@ -1276,17 +1279,33 @@ gst_rtp_buffer_ext_timestamp (guint64 * exttimestamp, guint32 timestamp)
|
|||
result = timestamp + (ext & ~(G_GUINT64_CONSTANT (0xffffffff)));
|
||||
|
||||
/* check for timestamp wraparound */
|
||||
if (result < ext)
|
||||
diff = ext - result;
|
||||
else
|
||||
diff = result - ext;
|
||||
if (result < ext) {
|
||||
guint64 diff = ext - result;
|
||||
|
||||
if (diff > G_MAXINT32) {
|
||||
/* timestamp went backwards more than allowed, we wrap around and get
|
||||
* updated extended timestamp. */
|
||||
result += (G_GUINT64_CONSTANT (1) << 32);
|
||||
if (diff > G_MAXINT32) {
|
||||
/* timestamp went backwards more than allowed, we wrap around and get
|
||||
* updated extended timestamp. */
|
||||
result += (G_GUINT64_CONSTANT (1) << 32);
|
||||
}
|
||||
} else {
|
||||
guint64 diff = result - ext;
|
||||
|
||||
if (diff > G_MAXINT32) {
|
||||
if (result < (G_GUINT64_CONSTANT (1) << 32)) {
|
||||
GST_WARNING
|
||||
("Cannot unwrap, any wrapping took place yet. Returning 0 without updating extended timestamp.");
|
||||
return 0;
|
||||
} else {
|
||||
/* timestamp went forwards more than allowed, we unwrap around and get
|
||||
* updated extended timestamp. */
|
||||
result -= (G_GUINT64_CONSTANT (1) << 32);
|
||||
/* We don't want the extended timestamp storage to go back, ever */
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*exttimestamp = result;
|
||||
|
||||
return result;
|
||||
|
|
|
@ -311,6 +311,10 @@ VALGRIND_TESTS_DISABLE = $(VALGRIND_TO_FIX)
|
|||
|
||||
SUPPRESSIONS = $(top_srcdir)/common/gst.supp $(srcdir)/gst-plugins-base.supp
|
||||
|
||||
generic_rtp_LDADD = \
|
||||
$(top_builddir)/gst-libs/gst/rtp/libgstrtp-@GST_API_VERSION@.la \
|
||||
$(LDADD)
|
||||
|
||||
libs_libsabi_CFLAGS = \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(GST_BASE_CFLAGS) \
|
||||
|
|
|
@ -1353,6 +1353,90 @@ GST_START_TEST (test_rtp_buffer_empty_payload)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_ext_timestamp_basic)
|
||||
{
|
||||
guint64 exttimestamp = -1;
|
||||
guint64 result = 0;
|
||||
|
||||
/* no wraparound when timestamps are increasing */
|
||||
result = gst_rtp_buffer_ext_timestamp (&exttimestamp, 0);
|
||||
fail_unless_equals_uint64 (result, 0);
|
||||
result = gst_rtp_buffer_ext_timestamp (&exttimestamp, 10);
|
||||
fail_unless_equals_uint64 (result, 10);
|
||||
result = gst_rtp_buffer_ext_timestamp (&exttimestamp, 10);
|
||||
fail_unless_equals_uint64 (result, 10);
|
||||
result = gst_rtp_buffer_ext_timestamp (&exttimestamp,
|
||||
G_GUINT64_CONSTANT (1) + G_MAXINT32);
|
||||
fail_unless_equals_uint64 (result, G_GUINT64_CONSTANT (1) + G_MAXINT32);
|
||||
|
||||
/* Even big bumps under G_MAXINT32 don't result in wrap-around */
|
||||
exttimestamp = -1;
|
||||
result = gst_rtp_buffer_ext_timestamp (&exttimestamp, 1087500);
|
||||
fail_unless_equals_uint64 (result, 1087500);
|
||||
result = gst_rtp_buffer_ext_timestamp (&exttimestamp, 24);
|
||||
fail_unless_equals_uint64 (result, 24);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_ext_timestamp_wraparound)
|
||||
{
|
||||
guint64 ext_ts = -1;
|
||||
|
||||
fail_unless_equals_uint64 (gst_rtp_buffer_ext_timestamp (&ext_ts,
|
||||
G_MAXUINT32 - 90000 + G_GUINT64_CONSTANT (1)),
|
||||
(G_MAXUINT32 - 90000 + G_GUINT64_CONSTANT (1)));
|
||||
|
||||
fail_unless_equals_uint64 (gst_rtp_buffer_ext_timestamp (&ext_ts, 0),
|
||||
G_MAXUINT32 + G_GUINT64_CONSTANT (1));
|
||||
|
||||
fail_unless_equals_uint64 (gst_rtp_buffer_ext_timestamp (&ext_ts, 90000),
|
||||
(G_MAXUINT32 + G_GUINT64_CONSTANT (1) + 90000));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_ext_timestamp_wraparound_disordered)
|
||||
{
|
||||
guint64 ext_ts = -1;
|
||||
|
||||
fail_unless (gst_rtp_buffer_ext_timestamp (&ext_ts,
|
||||
G_MAXUINT32 - 90000 + G_GUINT64_CONSTANT (1))
|
||||
== (G_MAXUINT32 - 90000 + G_GUINT64_CONSTANT (1)));
|
||||
|
||||
fail_unless (gst_rtp_buffer_ext_timestamp (&ext_ts, 0)
|
||||
== G_MAXUINT32 + G_GUINT64_CONSTANT (1));
|
||||
|
||||
/* Unwrapping around */
|
||||
fail_unless (gst_rtp_buffer_ext_timestamp (&ext_ts,
|
||||
G_MAXUINT32 - 90000 + G_GUINT64_CONSTANT (1))
|
||||
== (G_MAXUINT32 - 90000 + G_GUINT64_CONSTANT (1)));
|
||||
|
||||
fail_unless (gst_rtp_buffer_ext_timestamp (&ext_ts, 90000)
|
||||
== (G_MAXUINT32 + G_GUINT64_CONSTANT (1) + 90000));
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_ext_timestamp_wraparound_disordered_cannot_unwrap)
|
||||
{
|
||||
guint64 ext_ts = -1;
|
||||
|
||||
fail_unless (gst_rtp_buffer_ext_timestamp (&ext_ts, 90000)
|
||||
== 90000);
|
||||
|
||||
/* Cannot unwrapping around */
|
||||
fail_unless (gst_rtp_buffer_ext_timestamp (&ext_ts,
|
||||
G_MAXUINT32 - 90000 + G_GUINT64_CONSTANT (1)) == 0);
|
||||
|
||||
fail_unless (gst_rtp_buffer_ext_timestamp (&ext_ts, 90000)
|
||||
== 90000);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
rtp_suite (void)
|
||||
{
|
||||
|
@ -1389,6 +1473,12 @@ rtp_suite (void)
|
|||
|
||||
//tcase_add_test (tc_chain, test_rtp_buffer_list);
|
||||
|
||||
tcase_add_test (tc_chain, test_ext_timestamp_basic);
|
||||
tcase_add_test (tc_chain, test_ext_timestamp_wraparound);
|
||||
tcase_add_test (tc_chain, test_ext_timestamp_wraparound_disordered);
|
||||
tcase_add_test (tc_chain,
|
||||
test_ext_timestamp_wraparound_disordered_cannot_unwrap);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue