|
|
@@ -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;
|
|
|
+}
|