# include "config.h"
#endif
-#include <vlc/vlc.h>
+#include <vlc_common.h>
#include <time.h> /* clock_gettime(), clock_nanosleep() */
#include <assert.h>
*/
char *mstrtime( char *psz_buffer, mtime_t date )
{
- static mtime_t ll1000 = 1000, ll60 = 60, ll24 = 24;
+ static const mtime_t ll1000 = 1000, ll60 = 60, ll24 = 24;
snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%02d:%02d:%02d-%03d.%03d",
(int) (date / (ll1000 * ll1000 * ll60 * ll60) % ll24),
#endif
}
-static volatile mtime_t cached_time = 0;
-
/**
* Return high precision date
*
}
else
{
- /* Fallback on timeGetTime() which has a milisecond resolution
+ /* Fallback on timeGetTime() which has a millisecond resolution
* (actually, best case is about 5 ms resolution)
* timeGetTime() only returns a DWORD thus will wrap after
* about 49.7 days so we try to detect the wrapping. */
res = (mtime_t) tv_date.tv_sec * 1000000 + (mtime_t) tv_date.tv_usec;
#endif
- return cached_time = res;
+ return res;
}
+#undef mwait
/**
* Wait for a date
*
void mwait( mtime_t date )
{
/* If the deadline is already elapsed, or within the clock precision,
- * do not even bother the clock. */
- if( ( date - cached_time ) < (mtime_t)mprec() ) // OK: mtime_t is signed
- return;
+ * do not even bother the system timer. */
+ date -= mprec();
-#if 0 && defined (HAVE_CLOCK_NANOSLEEP)
+#if defined (HAVE_CLOCK_NANOSLEEP)
lldiv_t d = lldiv( date, 1000000 );
struct timespec ts = { d.quot, d.rem * 1000 };
ts.tv_sec = d.quot; ts.tv_nsec = d.rem * 1000;
while( clock_nanosleep( CLOCK_REALTIME, 0, &ts, NULL ) == EINTR );
}
-#else
+#elif defined (WIN32)
+ mtime_t i_total;
+
+ while( (i_total = (date - mdate())) > 0 )
+ {
+ const mtime_t i_sleep = i_total / 1000;
+ DWORD i_delay = (i_sleep > 0x7fffffff) ? 0x7fffffff : i_sleep;
+ vlc_testcancel();
+ SleepEx( i_delay, TRUE );
+ }
+ vlc_testcancel();
+
+#else
mtime_t delay = date - mdate();
if( delay > 0 )
msleep( delay );
#endif
}
+
+#include "libvlc.h" /* vlc_backtrace() */
+#undef msleep
+
/**
- * More precise sleep()
+ * Portable usleep(). Cancellation point.
*
- * Portable usleep() function.
* \param delay the amount of time to sleep
*/
void msleep( mtime_t delay )
{
- mtime_t earlier = cached_time;
+#ifndef NDEBUG
+# if defined (__linux__)
+ /* We assume that proper use of msleep() will not use a constant period...
+ * Media synchronization is likely to use mwait() with at least slight
+ * sleep length variation at microsecond precision. Network protocols
+ * normally have exponential backoffs, or long delays. */
+ static __thread unsigned tick_period = 0;
+ static __thread unsigned tick_frequency = 0;
+ if (tick_period != delay)
+ tick_frequency = 0;
+ tick_frequency++;
+ tick_period = delay;
+ if (delay < (29 * CLOCK_FREQ) && tick_frequency == 20)
+ {
+ fprintf (stderr, "Likely bogus delay(%"PRIu64"µs) ", delay);
+ vlc_backtrace ();
+ }
+ //fprintf (stderr, "%u, %u\n", tick_period, tick_frequency);
+# endif
+#endif
#if defined( HAVE_CLOCK_NANOSLEEP )
lldiv_t d = lldiv( delay, 1000000 );
snooze( delay );
#elif defined( WIN32 ) || defined( UNDER_CE )
- Sleep( (DWORD) (delay / 1000) );
+ mwait (mdate () + delay);
#elif defined( HAVE_NANOSLEEP )
struct timespec ts_delay;
* or clock_nanosleep() if this is an issue. */
select( 0, NULL, NULL, NULL, &tv_delay );
#endif
-
- earlier += delay;
- if( cached_time < earlier )
- cached_time = earlier;
}
/*
void date_Change( date_t *p_date, uint32_t i_divider_n, uint32_t i_divider_d )
{
+ /* change time scale of remainder */
+ p_date->i_remainder = p_date->i_remainder * i_divider_n / p_date->i_divider_num;
p_date->i_divider_num = i_divider_n;
p_date->i_divider_den = i_divider_d;
}
*/
mtime_t date_Increment( date_t *p_date, uint32_t i_nb_samples )
{
- mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000;
- p_date->date += i_dividend / p_date->i_divider_num * p_date->i_divider_den;
+ mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000 * p_date->i_divider_den;
+ p_date->date += i_dividend / p_date->i_divider_num;
p_date->i_remainder += (int)(i_dividend % p_date->i_divider_num);
if( p_date->i_remainder >= p_date->i_divider_num )
{
/* This is Bresenham algorithm. */
- p_date->date += p_date->i_divider_den;
+ assert( p_date->i_remainder < 2*p_date->i_divider_num);
+ p_date->date += 1;
p_date->i_remainder -= p_date->i_divider_num;
}