~ubuntu-branches/debian/wheezy/vlc/wheezy

« back to all changes in this revision

Viewing changes to src/misc/mtime.c

Tags: upstream-0.7.2.final
ImportĀ upstreamĀ versionĀ 0.7.2.final

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
 
 * mtime.c: high rezolution time management functions
 
2
 * mtime.c: high resolution time management functions
3
3
 * Functions are prototyped in mtime.h.
4
4
 *****************************************************************************
5
 
 * Copyright (C) 1998-2001 VideoLAN
6
 
 * $Id: mtime.c,v 1.25 2001/11/28 15:08:06 massiot Exp $
 
5
 * Copyright (C) 1998-2004 VideoLAN
 
6
 * $Id: mtime.c 6961 2004-03-05 17:34:23Z sam $
7
7
 *
8
8
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
9
9
 *
11
11
 * it under the terms of the GNU General Public License as published by
12
12
 * the Free Software Foundation; either version 2 of the License, or
13
13
 * (at your option) any later version.
14
 
 * 
 
14
 *
15
15
 * This program is distributed in the hope that it will be useful,
16
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30
30
/*****************************************************************************
31
31
 * Preamble
32
32
 *****************************************************************************/
33
 
#include "defs.h"
34
 
 
35
33
#include <stdio.h>                                              /* sprintf() */
36
34
 
 
35
#include <vlc/vlc.h>
 
36
 
37
37
#if defined( PTH_INIT_IN_PTH_H )                                  /* GNU Pth */
38
38
#   include <pth.h>
39
39
#endif
46
46
#   include <kernel/OS.h>
47
47
#endif
48
48
 
49
 
#if defined( WIN32 )
 
49
#if defined( WIN32 ) || defined( UNDER_CE )
50
50
#   include <windows.h>
51
51
#else
52
52
#   include <sys/time.h>
53
53
#endif
54
54
 
55
 
#include "config.h"
56
 
#include "common.h"
57
 
#include "mtime.h"
58
 
 
59
 
/*****************************************************************************
60
 
 * mstrtime: return a date in a readable format
61
 
 *****************************************************************************
62
 
 * This functions is provided for any interface function which need to print a
63
 
 * date. psz_buffer should be a buffer long enough to store the formatted
 
55
#if defined(HAVE_NANOSLEEP) && !defined(HAVE_STRUCT_TIMESPEC)
 
56
struct timespec
 
57
{
 
58
    time_t  tv_sec;
 
59
    int32_t tv_nsec;
 
60
};
 
61
#endif
 
62
 
 
63
#if defined(HAVE_NANOSLEEP) && !defined(HAVE_DECL_NANOSLEEP)
 
64
int nanosleep(struct timespec *, struct timespec *);
 
65
#endif
 
66
 
 
67
/**
 
68
 * Return a date in a readable format
 
69
 *
 
70
 * This function converts a mtime date into a string.
 
71
 * psz_buffer should be a buffer long enough to store the formatted
64
72
 * date.
65
 
 *****************************************************************************/
 
73
 * \param date to be converted
 
74
 * \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters
 
75
 * \return psz_buffer is returned so this can be used as printf parameter.
 
76
 */
66
77
char *mstrtime( char *psz_buffer, mtime_t date )
67
78
{
68
 
    sprintf( psz_buffer, "%02d:%02d:%02d-%03d.%03d",
69
 
             (int) (date / (I64C(1000) * I64C(1000) * I64C(60) * I64C(60)) % I64C(24)),
70
 
             (int) (date / (I64C(1000) * I64C(1000) * I64C(60)) % I64C(60)),
71
 
             (int) (date / (I64C(1000) * I64C(1000)) % I64C(60)),
72
 
             (int) (date / I64C(1000) % I64C(1000)),
73
 
             (int) (date % I64C(1000)) );
74
 
    return( psz_buffer );
75
 
}
76
 
 
77
 
/*****************************************************************************
78
 
 * mdate: return high precision date (inline function)
79
 
 *****************************************************************************
 
79
    static mtime_t ll1000 = 1000, ll60 = 60, ll24 = 24;
 
80
 
 
81
    snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%02d:%02d:%02d-%03d.%03d",
 
82
             (int) (date / (ll1000 * ll1000 * ll60 * ll60) % ll24),
 
83
             (int) (date / (ll1000 * ll1000 * ll60) % ll60),
 
84
             (int) (date / (ll1000 * ll1000) % ll60),
 
85
             (int) (date / ll1000 % ll1000),
 
86
             (int) (date % ll1000) );
 
87
    return( psz_buffer );
 
88
}
 
89
 
 
90
/**
 
91
 * Convert seconds to a time in the format h:mm:ss.
 
92
 *
 
93
 * This function is provided for any interface function which need to print a
 
94
 * time string in the format h:mm:ss
 
95
 * date.
 
96
 * \param secs  the date to be converted
 
97
 * \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters
 
98
 * \return psz_buffer is returned so this can be used as printf parameter.
 
99
 */
 
100
char *secstotimestr( char *psz_buffer, int i_seconds )
 
101
{
 
102
    snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%d:%2.2d:%2.2d",
 
103
              (int) (i_seconds / (60 *60)),
 
104
              (int) ((i_seconds / 60) % 60),
 
105
              (int) (i_seconds % 60) );
 
106
    return( psz_buffer );
 
107
}
 
108
 
 
109
/**
 
110
 * Return high precision date
 
111
 *
80
112
 * Uses the gettimeofday() function when possible (1 MHz resolution) or the
81
113
 * ftime() function (1 kHz resolution).
82
 
 *****************************************************************************/
 
114
 */
83
115
mtime_t mdate( void )
84
116
{
85
117
#if defined( HAVE_KERNEL_OS_H )
86
118
    return( real_time_clock_usecs() );
87
119
 
88
 
#elif defined( WIN32 )
89
 
    /* We don't get the real date, just the value of a high precision timer.
90
 
     * this is because the usual time functions have at best only a milisecond
91
 
     * resolution */
92
 
    mtime_t freq, usec_time;
93
 
 
94
 
    if( QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ) )
 
120
#elif defined( WIN32 ) || defined( UNDER_CE )
 
121
    /* We don't need the real date, just the value of a high precision timer */
 
122
    static mtime_t freq = I64C(-1);
 
123
    mtime_t usec_time;
 
124
 
 
125
    if( freq == I64C(-1) )
 
126
    {
 
127
        /* Extract from the Tcl source code:
 
128
         * (http://www.cs.man.ac.uk/fellowsd-bin/TIP/7.html)
 
129
         *
 
130
         * Some hardware abstraction layers use the CPU clock
 
131
         * in place of the real-time clock as a performance counter
 
132
         * reference.  This results in:
 
133
         *    - inconsistent results among the processors on
 
134
         *      multi-processor systems.
 
135
         *    - unpredictable changes in performance counter frequency
 
136
         *      on "gearshift" processors such as Transmeta and
 
137
         *      SpeedStep.
 
138
         * There seems to be no way to test whether the performance
 
139
         * counter is reliable, but a useful heuristic is that
 
140
         * if its frequency is 1.193182 MHz or 3.579545 MHz, it's
 
141
         * derived from a colorburst crystal and is therefore
 
142
         * the RTC rather than the TSC.  If it's anything else, we
 
143
         * presume that the performance counter is unreliable.
 
144
         */
 
145
 
 
146
        freq = ( QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ) &&
 
147
                 (freq == I64C(1193182) || freq == I64C(3579545) ) )
 
148
               ? freq : 0;
 
149
    }
 
150
 
 
151
    if( freq != 0 )
95
152
    {
96
153
        /* Microsecond resolution */
97
154
        QueryPerformanceCounter( (LARGE_INTEGER *)&usec_time );
99
156
    }
100
157
    else
101
158
    {
102
 
        /* Milisecond resolution */
103
 
        return 1000 * GetTickCount();
 
159
        /* Fallback on GetTickCount() which has a milisecond resolution
 
160
         * (actually, best case is about 10 ms resolution)
 
161
         * GetTickCount() only returns a DWORD thus will wrap after
 
162
         * about 49.7 days so we try to detect the wrapping. */
 
163
 
 
164
        static CRITICAL_SECTION date_lock;
 
165
        static mtime_t i_previous_time = I64C(-1);
 
166
        static int i_wrap_counts = -1;
 
167
 
 
168
        if( i_wrap_counts == -1 )
 
169
        {
 
170
            /* Initialization */
 
171
            i_previous_time = I64C(1000) * GetTickCount();
 
172
            InitializeCriticalSection( &date_lock );
 
173
            i_wrap_counts = 0;
 
174
        }
 
175
 
 
176
        EnterCriticalSection( &date_lock );
 
177
        usec_time = I64C(1000) *
 
178
            (i_wrap_counts * I64C(0x100000000) + GetTickCount());
 
179
        if( i_previous_time > usec_time )
 
180
        {
 
181
            /* Counter wrapped */
 
182
            i_wrap_counts++;
 
183
            usec_time += I64C(0x100000000000);
 
184
        }
 
185
        i_previous_time = usec_time;
 
186
        LeaveCriticalSection( &date_lock );
 
187
 
 
188
        return usec_time;
104
189
    }
105
190
 
106
191
#else
115
200
#endif
116
201
}
117
202
 
118
 
/*****************************************************************************
119
 
 * mwait: wait for a date (inline function)
120
 
 *****************************************************************************
 
203
/**
 
204
 * Wait for a date
 
205
 *
121
206
 * This function uses select() and an system date function to wake up at a
122
207
 * precise date. It should be used for process synchronization. If current date
123
208
 * is posterior to wished date, the function returns immediately.
124
 
 *****************************************************************************/
 
209
 * \param date The date to wake up at
 
210
 */
125
211
void mwait( mtime_t date )
126
212
{
127
213
#if defined( HAVE_KERNEL_OS_H )
128
214
    mtime_t delay;
129
 
    
 
215
 
130
216
    delay = date - real_time_clock_usecs();
131
217
    if( delay <= 0 )
132
218
    {
134
220
    }
135
221
    snooze( delay );
136
222
 
137
 
#elif defined( WIN32 )
 
223
#elif defined( WIN32 ) || defined( UNDER_CE )
138
224
    mtime_t usec_time, delay;
139
225
 
140
226
    usec_time = mdate();
147
233
 
148
234
#else
149
235
 
150
 
#   ifdef HAVE_USLEEP
151
236
    struct timeval tv_date;
152
 
#   else
153
 
    struct timeval tv_date, tv_delay;
154
 
#   endif
155
237
    mtime_t        delay;          /* delay in msec, signed to detect errors */
156
238
 
157
239
    /* see mdate() about gettimeofday() possible errors */
172
254
#   if defined( PTH_INIT_IN_PTH_H )
173
255
    pth_usleep( delay );
174
256
 
175
 
#   elif defined( HAVE_USLEEP )
176
 
    usleep( delay );
 
257
#   elif defined( ST_INIT_IN_ST_H )
 
258
    st_usleep( delay );
177
259
 
178
260
#   else
179
 
    tv_delay.tv_sec = delay / 1000000;
180
 
    tv_delay.tv_usec = delay % 1000000;
 
261
 
 
262
#       if defined( HAVE_NANOSLEEP )
 
263
    {
 
264
        struct timespec ts_delay;
 
265
        ts_delay.tv_sec = delay / 1000000;
 
266
        ts_delay.tv_nsec = (delay % 1000000) * 1000;
 
267
 
 
268
        nanosleep( &ts_delay, NULL );
 
269
    }
 
270
 
 
271
#       else
 
272
    tv_date.tv_sec = delay / 1000000;
 
273
    tv_date.tv_usec = delay % 1000000;
181
274
    /* see msleep() about select() errors */
182
 
    select( 0, NULL, NULL, NULL, &tv_delay );
 
275
    select( 0, NULL, NULL, NULL, &tv_date );
 
276
#       endif
183
277
 
184
278
#   endif
185
279
 
186
280
#endif
187
281
}
188
282
 
189
 
/*****************************************************************************
190
 
 * msleep: more precise sleep() (inline function)                        (ok ?)
191
 
 *****************************************************************************
 
283
/**
 
284
 * More precise sleep()
 
285
 *
192
286
 * Portable usleep() function.
193
 
 *****************************************************************************/
 
287
 * \param delay the amount of time to sleep
 
288
 */
194
289
void msleep( mtime_t delay )
195
290
{
196
291
#if defined( HAVE_KERNEL_OS_H )
197
292
    snooze( delay );
198
293
 
199
294
#elif defined( PTH_INIT_IN_PTH_H )
200
 
    struct timeval tv_delay;
201
 
    tv_delay.tv_sec = delay / 1000000;
202
 
    tv_delay.tv_usec = delay % 1000000;
203
 
    pth_select( 0, NULL, NULL, NULL, &tv_delay );
204
 
 
205
 
#elif defined( HAVE_USLEEP )
206
 
    usleep( delay );
207
 
 
208
 
#elif defined( WIN32 )
 
295
    pth_usleep( delay );
 
296
 
 
297
#elif defined( ST_INIT_IN_ST_H )
 
298
    st_usleep( delay );
 
299
 
 
300
#elif defined( WIN32 ) || defined( UNDER_CE )
209
301
    Sleep( (int) (delay / 1000) );
210
302
 
 
303
#elif defined( HAVE_NANOSLEEP )
 
304
    struct timespec ts_delay;
 
305
 
 
306
    ts_delay.tv_sec = delay / 1000000;
 
307
    ts_delay.tv_nsec = (delay % 1000000) * 1000;
 
308
 
 
309
    nanosleep( &ts_delay, NULL );
 
310
 
211
311
#else
212
312
    struct timeval tv_delay;
213
313
 
214
314
    tv_delay.tv_sec = delay / 1000000;
215
315
    tv_delay.tv_usec = delay % 1000000;
 
316
 
216
317
    /* select() return value should be tested, since several possible errors
217
318
     * can occur. However, they should only happen in very particular occasions
218
319
     * (i.e. when a signal is sent to the thread, or when memory is full), and
219
 
     * can be ingnored. */
 
320
     * can be ignored. */
220
321
    select( 0, NULL, NULL, NULL, &tv_delay );
221
322
 
222
323
#endif