Native darwin timer update.

Patch by Dan Christiansen <danchr@daimi.au.dk>


git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@12955 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
wight 2004-08-04 15:48:43 +00:00
parent 37e68033df
commit e68d7f6858
5 changed files with 69 additions and 112 deletions

View File

@ -1127,7 +1127,8 @@ if(!codecs_file || !parse_codec_cfg(codecs_file)){
#endif
if(rtc_fd<0)
#endif
mp_msg(MSGT_CPLAYER, MSGL_INFO, "Using %s timing\n",softsleep?"software":"usleep()");
mp_msg(MSGT_CPLAYER, MSGL_INFO, "Using %s timing\n",
softsleep?"software":timer_name);
#ifdef USE_TERMCAP
if ( !use_gui ) load_termcap(NULL); // load key-codes
@ -2232,9 +2233,9 @@ if(time_frame>0.001 && !(vo_flags&256)){
} else
#endif
{
// -------- USLEEP + SOFTSLEEP -----------
// -------- TIMER + SOFTSLEEP -----------
float min=softsleep?0.021:0.005;
current_module="sleep_usleep";
current_module="sleep_timer";
while(time_frame>min){
if(time_frame<=0.020)
usec_sleep(0); // sleeps 1 clock tick (10ms)!

View File

@ -1,170 +1,116 @@
/*
* Precise timer routines using Mach kernel-space timing.
* Precise timer routines using Mach timing
*
* It reports to be accurate by ~20us, unless the task is preempted.
* Copyright (c) 2003-2004, Dan Villiom Podlaski Christiansen
*
* (C) 2003 Dan Christiansen
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* Released into the public domain.
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <sys/time.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;
const char *timer_name = "Darwin accurate";
/* sleep usec_delay microseconds */
/* the core sleep function, uses floats and is used in MPlayer G2 */
float sleep_accurate(float time_frame)
{
uint64_t deadline = time_frame / timebase_ratio + mach_absolute_time();
mach_wait_until(deadline);
return (mach_absolute_time() - deadline) * timebase_ratio;
}
/* wrapper for MPlayer G1 */
int usec_sleep(int usec_delay)
{
#if 0
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);
#else
usleep(usec_delay);
#endif
return sleep_accurate(usec_delay / 1e6) * 1e6;
}
/* Returns current time in microseconds */
/* current time in microseconds */
unsigned int GetTimer()
{
return (unsigned int)((mach_absolute_time() * timebase_ratio - startup_time)
* 1e6);
}
}
/* Returns current time in milliseconds */
/* current time in milliseconds */
unsigned int GetTimerMS()
{
return (unsigned int)(GetTimer() / 1000);
}
/* Returns time spent between now and last call in seconds */
/* time spent between now and last call in seconds */
float GetRelativeTime()
{
double last_time;
last_time = relative_time;
double last_time = relative_time;
if (!relative_time)
InitTimer();
relative_time = mach_absolute_time() * timebase_ratio;
return (float)(relative_time-last_time);
}
/* Initialize timer, must be called at least once at start */
/* 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;
#include <stdio.h>
int main() {
int i,j, r, c = 200;
long long t = 0;
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 < 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);
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

View File

@ -6,6 +6,13 @@
#include <sys/time.h>
#include "../config.h"
const char *timer_name() =
#ifdef HAVE_NANOSLEEP
"nanosleep()";
#else
"usleep()";
#endif
int usec_sleep(int usec_delay)
{
#ifdef HAVE_NANOSLEEP
@ -18,7 +25,6 @@ int usec_sleep(int usec_delay)
#endif
}
// Returns current time in microseconds
unsigned int GetTimer(){
struct timeval tv;

View File

@ -4,6 +4,8 @@
#include <mmsystem.h>
#include "timer.h"
const char *timer_name = "Windows native";
// Returns current time in microseconds
unsigned int GetTimer(){
return timeGetTime() * 1000;

View File

@ -1,6 +1,8 @@
#ifndef __TIMER_H
#define __TIMER_H
extern const char *timer_name;
void InitTimer();
unsigned int GetTimer();
unsigned int GetTimerMS();