Browse Source

libobs/util: Add `os_nstime_to_timespec`

Ruwen Hahn 1 year ago
parent
commit
26b7b4511c
2 changed files with 61 additions and 0 deletions
  1. 57 0
      libobs/util/platform.c
  2. 4 0
      libobs/util/platform.h

+ 57 - 0
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(&timespec_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;
+}

+ 4 - 0
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