* mtime.c: high resolution time management functions
* Functions are prototyped in mtime.h.
*****************************************************************************
- * Copyright (C) 1998-2001, 2003 VideoLAN
- * $Id: mtime.c,v 1.39 2003/12/03 21:50:50 sigmunau Exp $
+ * Copyright (C) 1998-2004 VideoLAN
+ * $Id$
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
* 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.
- *
+ *
* This program 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
*
* This function converts a mtime date into a string.
* psz_buffer should be a buffer long enough to store the formatted
- * date.
+ * date.
* \param date to be converted
* \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters
* \return psz_buffer is returned so this can be used as printf parameter.
char *secstotimestr( char *psz_buffer, int i_seconds )
{
snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%d:%2.2d:%2.2d",
- (int) (i_seconds / (60 *60)),
- (int) ((i_seconds / 60) % 60),
+ (int) (i_seconds / (60 *60)),
+ (int) ((i_seconds / 60) % 60),
(int) (i_seconds % 60) );
return( psz_buffer );
}
QueryPerformanceCounter( (LARGE_INTEGER *)&usec_time );
return ( usec_time * 1000000 ) / freq;
}
-
- /* Milisecond resolution (actually, best case is about 10 ms resolution) */
- return 1000 * GetTickCount();
+ else
+ {
+ /* Fallback on GetTickCount() which has a milisecond resolution
+ * (actually, best case is about 10 ms resolution)
+ * GetTickCount() only returns a DWORD thus will wrap after
+ * about 49.7 days so we try to detect the wrapping. */
+
+ static CRITICAL_SECTION date_lock;
+ static mtime_t i_previous_time = I64C(-1);
+ static int i_wrap_counts = -1;
+
+ if( i_wrap_counts == -1 )
+ {
+ /* Initialization */
+ i_previous_time = I64C(1000) * GetTickCount();
+ InitializeCriticalSection( &date_lock );
+ i_wrap_counts = 0;
+ }
+
+ EnterCriticalSection( &date_lock );
+ usec_time = I64C(1000) *
+ (i_wrap_counts * I64C(0x100000000) + GetTickCount());
+ if( i_previous_time > usec_time )
+ {
+ /* Counter wrapped */
+ i_wrap_counts++;
+ usec_time += I64C(0x100000000000);
+ }
+ i_previous_time = usec_time;
+ LeaveCriticalSection( &date_lock );
+
+ return usec_time;
+ }
#else
struct timeval tv_date;
{
#if defined( HAVE_KERNEL_OS_H )
mtime_t delay;
-
+
delay = date - real_time_clock_usecs();
if( delay <= 0 )
{
#endif
}
+/*
+ * Date management (internal and external)
+ */
+
+/**
+ * Initialize a date_t.
+ *
+ * \param date to initialize
+ * \param divider (sample rate) numerator
+ * \param divider (sample rate) denominator
+ */
+
+void date_Init( date_t *p_date, uint32_t i_divider_n, uint32_t i_divider_d )
+{
+ p_date->date = 0;
+ p_date->i_divider_num = i_divider_n;
+ p_date->i_divider_den = i_divider_d;
+ p_date->i_remainder = 0;
+}
+
+/**
+ * Change a date_t.
+ *
+ * \param date to change
+ * \param divider (sample rate) numerator
+ * \param divider (sample rate) denominator
+ */
+
+void date_Change( date_t *p_date, uint32_t i_divider_n, uint32_t i_divider_d )
+{
+ p_date->i_divider_num = i_divider_n;
+ p_date->i_divider_den = i_divider_d;
+}
+
+/**
+ * Set the date value of a date_t.
+ *
+ * \param date to set
+ * \param date value
+ */
+void date_Set( date_t *p_date, mtime_t i_new_date )
+{
+ p_date->date = i_new_date;
+ p_date->i_remainder = 0;
+}
+
+/**
+ * Get the date of a date_t
+ *
+ * \param date to get
+ * \return date value
+ */
+mtime_t date_Get( const date_t *p_date )
+{
+ return p_date->date;
+}
+
+/**
+ * Move forwards or backwards the date of a date_t.
+ *
+ * \param date to move
+ * \param difference value
+ */
+void date_Move( date_t *p_date, mtime_t i_difference )
+{
+ p_date->date += i_difference;
+}
+
+/**
+ * Increment the date and return the result, taking into account
+ * rounding errors.
+ *
+ * \param date to increment
+ * \param incrementation in number of samples
+ * \return date value
+ */
+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;
+ 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;
+ p_date->i_remainder -= p_date->i_divider_num;
+ }
+
+ return p_date->date;
+}