From: Edward Hervey Date: Fri, 30 Oct 2020 15:58:52 +0000 (+0100) Subject: systemclock: Use clock_nanosleep for higher accuracy X-Git-Tag: 1.19.3~671 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=17feeb1bd6f4fa31d050054a6f3adb04816228d9;p=platform%2Fupstream%2Fgstreamer.git systemclock: Use clock_nanosleep for higher accuracy The various wait implementation have a latency ranging from 50 to 500+ microseconds. While this is not a major issue when dealing with a low number of waits per second (for ex: video), it does introduce a non-negligeable jitter for synchronization of higher packet rate systems. The `clock_nanosleep` syscall does offer a lower-latency waiting system but is unfortunately blocking, so we don't want to use it in all scenarios nor for too long. This patch makes GstSystemClock use clock_nanosleep (if available) as such: * Any wait below 500us uses it * Any wait below 2ms will first use the regular waiting system and then clock_nanosleep # modified: gst/gstsystemclock.c Part-of: --- diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c index 96341fd..61d4d51 100644 --- a/gst/gstsystemclock.c +++ b/gst/gstsystemclock.c @@ -961,11 +961,34 @@ gst_system_clock_id_wait_jitter_unlocked (GstClock * clock, while (TRUE) { gboolean waitret; - /* now wait on the entry, it either times out or the cond is signalled. - * The status of the entry is BUSY only around the wait. */ - waitret = - GST_SYSTEM_CLOCK_ENTRY_WAIT_UNTIL ((GstClockEntryImpl *) entry, - mono_ts * 1000 + diff); +#ifdef HAVE_CLOCK_NANOSLEEP + if (diff <= 500 * GST_USECOND) { + /* In order to provide more accurate wait, we will use BLOCKING + clock_nanosleep for any deadlines at or below 500us */ + struct timespec end; + GST_TIME_TO_TIMESPEC (entryt, end); + GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) entry); + waitret = + clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &end, NULL) == 0; + GST_SYSTEM_CLOCK_ENTRY_LOCK ((GstClockEntryImpl *) entry); + } else { + + if (diff < 2 * GST_MSECOND) { + /* For any deadline within 2ms, we first use the regular non-blocking + wait by reducing the diff accordingly */ + diff -= 500 * GST_USECOND; + } +#endif + + /* now wait on the entry, it either times out or the cond is signalled. + * The status of the entry is BUSY only around the wait. */ + waitret = + GST_SYSTEM_CLOCK_ENTRY_WAIT_UNTIL ((GstClockEntryImpl *) entry, + mono_ts * 1000 + diff); + +#ifdef HAVE_CLOCK_NANOSLEEP + } +#endif /* get the new status, mark as DONE. We do this so that the unschedule * function knows when we left the poll and doesn't need to wakeup the @@ -1004,6 +1027,7 @@ gst_system_clock_id_wait_jitter_unlocked (GstClock * clock, /* reschedule if gst_cond_wait_until returned early or we have to reschedule after * an unlock*/ + mono_ts = g_get_monotonic_time (); now = gst_clock_get_time (clock); diff = GST_CLOCK_DIFF (now, entryt); diff --git a/meson.build b/meson.build index 7edc840..1a860c3 100644 --- a/meson.build +++ b/meson.build @@ -236,6 +236,7 @@ check_functions = [ 'pselect', 'getpagesize', 'clock_gettime', + 'clock_nanosleep', 'strnlen', # These are needed by libcheck 'getline',