From 26b7b4511c6ceeefc0605ff75f30e922588fd433 Mon Sep 17 00:00:00 2001 From: Ruwen Hahn Date: Mon, 18 Mar 2024 17:32:20 +0100 Subject: [PATCH] libobs/util: Add `os_nstime_to_timespec` --- libobs/util/platform.c | 57 ++++++++++++++++++++++++++++++++++++++++++ libobs/util/platform.h | 4 +++ 2 files changed, 61 insertions(+) diff --git a/libobs/util/platform.c b/libobs/util/platform.c index 068b6d60e..1b9d894aa 100644 --- a/libobs/util/platform.c +++ b/libobs/util/platform.c @@ -27,6 +27,7 @@ #include "utf8.h" #include "dstr.h" #include "obs.h" +#include "threading.h" FILE *os_wfopen(const wchar_t *path, const char *mode) { @@ -807,3 +808,59 @@ char *os_generate_formatted_filename(const char *extension, bool space, return sf.array; } + +static struct { + struct timespec ts; + bool ts_valid; + uint64_t timestamp; +} timespec_offset = {0}; + +static void init_timespec_offset(void) +{ + timespec_offset.ts_valid = + timespec_get(×pec_offset.ts, TIME_UTC) == TIME_UTC; + timespec_offset.timestamp = os_gettime_ns(); +} + +struct timespec *os_nstime_to_timespec(uint64_t timestamp, + struct timespec *storage) +{ + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once(&once, init_timespec_offset); + + if (!storage || !timespec_offset.ts_valid) { + return NULL; + } + + *storage = timespec_offset.ts; + + static const int64_t nsecs_per_sec = 1000000000; + + int64_t nsecs = 0; + int64_t secs = 0; + if (timestamp >= timespec_offset.timestamp) { + uint64_t offset = timestamp - timespec_offset.timestamp; + nsecs = storage->tv_nsec + offset % nsecs_per_sec; + secs = storage->tv_sec + offset / nsecs_per_sec; + } else { + uint64_t offset = timespec_offset.timestamp - timestamp; + int64_t nsec_offset = offset % nsecs_per_sec; + int64_t sec_offset = offset / nsecs_per_sec; + int64_t tv_nsec = storage->tv_nsec; + if (nsec_offset > tv_nsec) { + storage->tv_sec -= 1; + tv_nsec += nsecs_per_sec; + } + nsecs = tv_nsec - nsec_offset; + secs = storage->tv_sec - sec_offset; + } + + if (nsecs > nsecs_per_sec) { + nsecs -= nsecs_per_sec; + secs += 1; + } + storage->tv_nsec = (long)nsecs; + storage->tv_sec = (time_t)secs; + + return storage; +} diff --git a/libobs/util/platform.h b/libobs/util/platform.h index a3a2b74c4..d66394f82 100644 --- a/libobs/util/platform.h +++ b/libobs/util/platform.h @@ -205,6 +205,10 @@ EXPORT uint64_t os_get_proc_virtual_size(void); EXPORT char *os_generate_uuid(void); +EXPORT +struct timespec *os_nstime_to_timespec(uint64_t timestamp, + struct timespec *storage); + /* clang-format off */ #ifdef __APPLE__ # define ARCH_BITS 64