summaryrefslogtreecommitdiffstats
path: root/osdep
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-05-17 19:54:37 +0200
committerwm4 <wm4@nowhere>2013-05-26 16:44:20 +0200
commit81439c5f35e604174408a2aaf4e4dec11b81ac39 (patch)
treeabd67642f487850c7f16666cc5f456d8f7ca347f /osdep
parent25d66f526ebae36a6c044652e5006450dd5a30df (diff)
downloadmpv-81439c5f35e604174408a2aaf4e4dec11b81ac39.tar.bz2
mpv-81439c5f35e604174408a2aaf4e4dec11b81ac39.tar.xz
timer: refactor, add 64 bit timer function
Make OS specific timer code export a mp_raw_time_us() function, and add generic implementations of GetTimer()/GetTimerMS() using this function. New mpv code is supposed to call mp_time_us() in situations where precision is absolutely needed, or mp_time_s() otherwise. Make it so that mp_time_us() will return a value near program start. We don't set it to 0 though to avoid confusion with relative vs. absolute time. Instead, pick an arbitrary offset. Move the test program in timer-darwin.c to timer.c, and modify it to work with the generic timer functions.
Diffstat (limited to 'osdep')
-rw-r--r--osdep/timer-darwin.c66
-rw-r--r--osdep/timer-linux.c32
-rw-r--r--osdep/timer-win2.c30
-rw-r--r--osdep/timer.c82
-rw-r--r--osdep/timer.h24
5 files changed, 138 insertions, 96 deletions
diff --git a/osdep/timer-darwin.c b/osdep/timer-darwin.c
index 1ce9cd584b..e5f751915e 100644
--- a/osdep/timer-darwin.c
+++ b/osdep/timer-darwin.c
@@ -27,72 +27,24 @@
#include "core/mp_msg.h"
#include "timer.h"
-/* global variables */
static double timebase_ratio;
-
-/* the core sleep function, uses floats and is used in MPlayer G2 */
-static float sleep_accurate(float time_frame)
+void mp_sleep_us(int64_t us)
{
- uint64_t deadline = time_frame / timebase_ratio + mach_absolute_time();
-
- mach_wait_until(deadline);
-
- return (mach_absolute_time() - deadline) * timebase_ratio;
-}
+ uint64_t deadline = us / 1e6 / timebase_ratio + mach_absolute_time();
-/* wrapper for MPlayer G1 */
-int usec_sleep(int usec_delay)
-{
- return sleep_accurate(usec_delay / 1e6) * 1e6;
+ mach_wait_until(deadline);
}
-
-/* current time in microseconds */
-unsigned int GetTimer(void)
+uint64_t mp_raw_time_us(void)
{
- return (unsigned int)(uint64_t)(mach_absolute_time() * timebase_ratio * 1e6);
+ return mach_absolute_time() * timebase_ratio * 1e6;
}
-/* current time in milliseconds */
-unsigned int GetTimerMS(void)
+void mp_raw_time_init(void)
{
- return (unsigned int)(uint64_t)(mach_absolute_time() * timebase_ratio * 1e3);
-}
-
-/* initialize timer, must be called at least once at start */
-void InitTimer(void)
-{
- struct mach_timebase_info timebase;
-
- mach_timebase_info(&timebase);
- timebase_ratio = (double)timebase.numer / (double)timebase.denom
- * (double)1e-9;
-}
-
-#if 0
-#include <stdio.h>
-
-int main(void) {
- int i,j, r, c = 200;
- long long t = 0;
-
- InitTimer();
-
- for (i = 0; i < c; i++) {
- const int delay = rand() / (RAND_MAX / 1e5);
- j = GetTimer();
-#if 1
- r = usec_sleep(delay);
-#else
- r = sleep_accurate(delay / 1e6) * 1e6;
-#endif
- j = (GetTimer() - j) - delay;
- printf("sleep time:%8i %5i (%i)\n", delay, j, j - r);
- t += j - r;
- }
- fprintf(stderr, "average error:\t%lli\n", t / c);
+ struct mach_timebase_info timebase;
- return 0;
+ mach_timebase_info(&timebase);
+ timebase_ratio = (double)timebase.numer / (double)timebase.denom * 1e-9;
}
-#endif
diff --git a/osdep/timer-linux.c b/osdep/timer-linux.c
index 63f7ad913f..314aa47b27 100644
--- a/osdep/timer-linux.c
+++ b/osdep/timer-linux.c
@@ -26,35 +26,27 @@
#include "config.h"
#include "timer.h"
-int usec_sleep(int usec_delay)
+void mp_sleep_us(int64_t us)
{
+ if (us < 0)
+ return;
#ifdef HAVE_NANOSLEEP
struct timespec ts;
- ts.tv_sec = usec_delay / 1000000;
- ts.tv_nsec = (usec_delay % 1000000) * 1000;
- return nanosleep(&ts, NULL);
+ ts.tv_sec = us / 1000000;
+ ts.tv_nsec = (us % 1000000) * 1000;
+ nanosleep(&ts, NULL);
#else
- return usleep(usec_delay);
+ usleep(us);
#endif
}
-// Returns current time in microseconds
-unsigned int GetTimer(void)
+uint64_t mp_raw_time_us(void)
{
- struct timeval tv;
- gettimeofday(&tv,NULL);
- return tv.tv_sec * 1000000 + tv.tv_usec;
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return tv.tv_sec * 1000000LL + tv.tv_usec;
}
-// Returns current time in milliseconds
-unsigned int GetTimerMS(void)
-{
- struct timeval tv;
- gettimeofday(&tv,NULL);
- return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-}
-
-// Initialize timer, must be called at least once at start
-void InitTimer(void)
+void mp_raw_time_init(void)
{
}
diff --git a/osdep/timer-win2.c b/osdep/timer-win2.c
index 88a047410d..99980d76bc 100644
--- a/osdep/timer-win2.c
+++ b/osdep/timer-win2.c
@@ -22,27 +22,25 @@
#include <mmsystem.h>
#include "timer.h"
-// Returns current time in microseconds
-unsigned int GetTimer(void)
+void mp_sleep_us(int64_t us)
{
- return timeGetTime() * 1000;
+ if (us < 0)
+ return;
+ // Sleep(0) won't sleep for one clocktick as the unix usleep
+ // instead it will only make the thread ready
+ // it may take some time until it actually starts to run again
+ if (us < 1000)
+ us = 1000;
+ Sleep(us / 1000);
}
-// Returns current time in milliseconds
-unsigned int GetTimerMS(void)
+uint64_t mp_raw_time_us(void)
{
- return timeGetTime() ;
+ return timeGetTime() * 1000;
}
-int usec_sleep(int usec_delay){
- // Sleep(0) won't sleep for one clocktick as the unix usleep
- // instead it will only make the thread ready
- // it may take some time until it actually starts to run again
- if(usec_delay<1000)usec_delay=1000;
- Sleep( usec_delay/1000);
- return 0;
-}
-
-void InitTimer(void)
+void mp_raw_time_init(void)
{
+ // request 1ms timer resolution
+ timeBeginPeriod(1);
}
diff --git a/osdep/timer.c b/osdep/timer.c
new file mode 100644
index 0000000000..2304bb1297
--- /dev/null
+++ b/osdep/timer.c
@@ -0,0 +1,82 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include "timer.h"
+
+static uint64_t raw_time_offset;
+
+void mp_time_init(void)
+{
+ mp_raw_time_init();
+ srand(mp_raw_time_us());
+ raw_time_offset = mp_raw_time_us();
+ // Arbitrary additional offset to avoid confusing relative/absolute times.
+ // Also,we rule that the timer never returns 0 (so default-initialized
+ // time values will be always in the past).
+ raw_time_offset -= 10000000;
+}
+
+int64_t mp_time_us(void)
+{
+ return mp_raw_time_us() - raw_time_offset;
+}
+
+double mp_time_sec(void)
+{
+ return mp_time_us() / (double)(1000 * 1000);
+}
+
+unsigned int GetTimer(void)
+{
+ return mp_time_us();
+}
+
+unsigned int GetTimerMS(void)
+{
+ return (mp_time_us() + 500) / 1000;
+}
+
+int usec_sleep(int usec_delay)
+{
+ mp_sleep_us(usec_delay);
+ return 0;
+}
+
+#if 0
+#include <stdio.h>
+
+int main(void) {
+ int c = 200;
+ int64_t j, r, t = 0;
+
+ mp_time_init();
+
+ for (int i = 0; i < c; i++) {
+ const int delay = rand() / (RAND_MAX / 1e5);
+ r = mp_time_us();
+ mp_sleep_us(delay);
+ j = (mp_time_us() - r) - delay;
+ printf("sleep time: sleep=%8i err=%5i\n", delay, (int)j);
+ t += j;
+ }
+ fprintf(stderr, "average error:\t%i\n", (int)(t / c));
+
+ return 0;
+}
+#endif
diff --git a/osdep/timer.h b/osdep/timer.h
index fe04663781..033b366750 100644
--- a/osdep/timer.h
+++ b/osdep/timer.h
@@ -19,10 +19,28 @@
#ifndef MPLAYER_TIMER_H
#define MPLAYER_TIMER_H
-void InitTimer(void);
-unsigned int GetTimer(void);
-unsigned int GetTimerMS(void);
+#include <inttypes.h>
+// Initialize timer, must be called at least once at start.
+void mp_time_init(void);
+
+// Return time in microseconds. Never wraps. Never returns 0 or negative values.
+int64_t mp_time_us(void);
+
+// Return time in seconds. Can have down to 1 microsecond resolution, but will
+// be much worse when casted to float.
+double mp_time_sec(void);
+
+// Provided by OS specific functions (timer-linux.c)
+void mp_raw_time_init(void);
+uint64_t mp_raw_time_us(void);
+
+// Sleep in microseconds.
+void mp_sleep_us(int64_t us);
+
+// Legacy timer functions. These can wrap.
+unsigned int GetTimer(void); // in us
+unsigned int GetTimerMS(void); // in ms
int usec_sleep(int usec_delay);
#endif /* MPLAYER_TIMER_H */