summaryrefslogtreecommitdiffstats
path: root/osdep
diff options
context:
space:
mode:
authoralex <alex@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-05-21 21:18:29 +0000
committeralex <alex@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-05-21 21:18:29 +0000
commit2ce15e79696fb684ecbe5f0c93b250e2f3d8b196 (patch)
tree7f54ca84a17ca90a66b7b30c665c86fb863afd7d /osdep
parentecf10a4138fcdd90844111892acbd1440f09d40d (diff)
downloadmpv-2ce15e79696fb684ecbe5f0c93b250e2f3d8b196.tar.bz2
mpv-2ce15e79696fb684ecbe5f0c93b250e2f3d8b196.tar.xz
Precise timer for Darwin (it's more accurate than timer-macosx.c)
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@10149 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'osdep')
-rw-r--r--osdep/Makefile4
-rw-r--r--osdep/timer-darwin.c169
2 files changed, 171 insertions, 2 deletions
diff --git a/osdep/Makefile b/osdep/Makefile
index 808f2e3e7b..cc3ea85487 100644
--- a/osdep/Makefile
+++ b/osdep/Makefile
@@ -13,8 +13,8 @@ endif
getch = getch2.c
timer = timer-lx.c
-ifeq ($(MACOSX),yes)
-timer = timer-macosx.c
+ifeq ($(TARGET_OS),Darwin)
+timer = timer-darwin.c
endif
ifeq ($(TARGET_CYGWIN),yes)
timer = timer-win2.c
diff --git a/osdep/timer-darwin.c b/osdep/timer-darwin.c
new file mode 100644
index 0000000000..a5b3516699
--- /dev/null
+++ b/osdep/timer-darwin.c
@@ -0,0 +1,169 @@
+/*
+ * Precise timer routines using Mach kernel-space timing.
+ *
+ * It reports to be accurate by ~20us, unless the task is preempted.
+ *
+ * (C) 2003 Dan Christiansen
+ *
+ * Released into the public domain.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <mach/mach_time.h>
+#include <mach/mach.h>
+#include <mach/clock.h>
+
+#include "../config.h"
+#include "../mp_msg.h"
+#include "timer.h"
+
+/* Utility macros for mach_timespec_t - it uses nsec rather than usec */
+
+/* returns time from t1 to t2, in seconds (as float) */
+#define diff_time(t1, t2) \
+ (((t2).tv_sec - (t1).tv_sec) + \
+ ((t2).tv_nsec - (t1).tv_nsec) / 1e9)
+
+/* returns time from t1 to t2, in microseconds (as integer) */
+#define udiff_time(t1, t2) \
+ (((t2).tv_sec - (t1).tv_sec) * 1000000 + \
+ ((t2).tv_nsec - (t1).tv_nsec) / 1000)
+
+/* returns float value of t, in seconds */
+#define time_to_float(t) \
+ ((t).tv_sec + (t).tv_nsec / 1e9)
+
+/* returns integer value of t, in microseconds */
+#define time_to_usec(t) \
+ ((t).tv_sec * 1000000 + (t).tv_nsec / 1000)
+
+/* sets ts to the value of f, in seconds */
+#define float_to_time(f, ts) \
+ do { \
+ (ts).tv_sec = (unsigned int)(f); \
+ (ts).tv_nsec = (int)(((f) - (ts).sec) / 1000000000.0); \
+ } while (0)
+
+/* sets ts to the value of i, in microseconds */
+#define usec_to_time(i, ts) \
+ do { \
+ (ts).tv_sec = (i) / 1000000; \
+ (ts).tv_nsec = (i) % 1000000 * 1000; \
+ } while (0)
+
+#define time_uadd(i, ts) \
+ do { \
+ (ts).tv_sec += (i) / 1000000; \
+ (ts).tv_nsec += (i) % 1000000 * 1000; \
+ while ((ts).tv_nsec > 1000000000) { \
+ (ts).tv_sec++; \
+ (ts).tv_nsec -= 1000000000; \
+ } \
+ } while (0)
+
+
+/* global variables */
+static double relative_time, startup_time;
+static double timebase_ratio;
+static mach_port_t clock_port;
+
+
+/* sleep usec_delay microseconds */
+int usec_sleep(int usec_delay)
+{
+ mach_timespec_t start_time, end_time;
+
+ clock_get_time(clock_port, &start_time);
+
+ end_time = start_time;
+ time_uadd(usec_delay, end_time);
+
+ clock_sleep(clock_port, TIME_ABSOLUTE, end_time, NULL);
+
+ clock_get_time(clock_port, &end_time);
+
+ return usec_delay - udiff_time(start_time, end_time);
+}
+
+
+/* Returns current time in microseconds */
+unsigned int GetTimer()
+{
+ return (unsigned int)((mach_absolute_time() * timebase_ratio - startup_time)
+ * 1e6);
+}
+
+/* Returns current time in milliseconds */
+unsigned int GetTimerMS()
+{
+ return (unsigned int)(GetTimer() / 1000);
+}
+
+/* Returns time spent between now and last call in seconds */
+float GetRelativeTime()
+{
+ double last_time;
+
+ if (!startup_time)
+ InitTimer();
+
+ last_time = relative_time;
+
+ relative_time = mach_absolute_time() * timebase_ratio;
+
+ return (float)(relative_time-last_time);
+}
+
+/* Initialize timer, must be called at least once at start */
+void InitTimer()
+{
+ struct mach_timebase_info timebase;
+
+ /* get base for mach_absolute_time() */
+ mach_timebase_info(&timebase);
+ timebase_ratio = (double)timebase.numer / (double)timebase.denom
+ * (double)1e-9;
+
+ /* get mach port for the clock */
+ host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &clock_port);
+
+ /* prepare for GetRelativeTime() */
+ relative_time = startup_time =
+ (double)(mach_absolute_time() * timebase_ratio);
+}
+
+
+#if 0
+int main()
+{
+ const long delay = 0.001*1e6;
+ const unsigned short attempts = 100;
+ int i,j[attempts],t[attempts],r[attempts];
+ double sqtotal;
+ double total;
+
+ InitTimer();
+
+ for (i = 0; i < attempts; i++) {
+ t[i] = j[i] = GetTimer();
+ r[i] = usec_sleep(delay);
+ j[i] = delay-(GetTimer() - j[i]);
+ fflush(stdout);
+ }
+
+ for (i = 0; i < attempts; i++) {
+ sqtotal += j[i]*j[i];
+ total += j[i];
+ printf("%2i=%0.06g \tr: %9i\tj: %9i\tr - j:%9i\n",
+ i, t[i] / 1e6, r[i], j[i], r[i] - j[i]);
+ }
+
+ printf("attempts: %i\ttotal=%g\trms=%g\tavg=%g\n", attempts, total,
+ sqrt(sqtotal/attempts),total/attempts);
+
+ return 0;
+}
+#endif