JRTPLIB  3.11.2 (development version)
rtptimeutilities.h
Go to the documentation of this file.
1 /*
2 
3  This file is a part of JRTPLIB
4  Copyright (c) 1999-2017 Jori Liesenborgs
5 
6  Contact: jori.liesenborgs@gmail.com
7 
8  This library was developed at the Expertise Centre for Digital Media
9  (http://www.edm.uhasselt.be), a research center of the Hasselt University
10  (http://www.uhasselt.be). The library is based upon work done for
11  my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
12 
13  Permission is hereby granted, free of charge, to any person obtaining a
14  copy of this software and associated documentation files (the "Software"),
15  to deal in the Software without restriction, including without limitation
16  the rights to use, copy, modify, merge, publish, distribute, sublicense,
17  and/or sell copies of the Software, and to permit persons to whom the
18  Software is furnished to do so, subject to the following conditions:
19 
20  The above copyright notice and this permission notice shall be included
21  in all copies or substantial portions of the Software.
22 
23  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29  IN THE SOFTWARE.
30 
31 */
32 
37 #ifndef RTPTIMEUTILITIES_H
38 
39 #define RTPTIMEUTILITIES_H
40 
41 #include "rtpconfig.h"
42 #include "rtptypes.h"
43 #ifndef RTP_HAVE_QUERYPERFORMANCECOUNTER
44  #include <sys/time.h>
45  #include <time.h>
46  #include <errno.h>
47 #endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
48 
49 #define RTP_NTPTIMEOFFSET 2208988800UL
50 
51 #ifdef RTP_HAVE_VSUINT64SUFFIX
52 #define C1000000 1000000ui64
53 #define CEPOCH 11644473600000000ui64
54 #else
55 #define C1000000 1000000ULL
56 #define CEPOCH 11644473600000000ULL
57 #endif // RTP_HAVE_VSUINT64SUFFIX
58 
59 namespace jrtplib
60 {
61 
66 class JRTPLIB_IMPORTEXPORT RTPNTPTime
67 {
68 public:
70  RTPNTPTime(uint32_t m,uint32_t l) { msw = m ; lsw = l; }
71 
73  uint32_t GetMSW() const { return msw; }
74 
76  uint32_t GetLSW() const { return lsw; }
77 private:
78  uint32_t msw,lsw;
79 };
80 
85 class JRTPLIB_IMPORTEXPORT RTPTime
86 {
87 public:
92  static RTPTime CurrentTime();
93 
95  static void Wait(const RTPTime &delay);
96 
98  RTPTime(double t);
99 
105  RTPTime(RTPNTPTime ntptime);
106 
108  RTPTime(int64_t seconds, uint32_t microseconds);
109 
111  int64_t GetSeconds() const;
112 
114  uint32_t GetMicroSeconds() const;
115 
117  double GetDouble() const { return m_t; }
118 
120  RTPNTPTime GetNTPTime() const;
121 
122  RTPTime &operator-=(const RTPTime &t);
123  RTPTime &operator+=(const RTPTime &t);
124  bool operator<(const RTPTime &t) const;
125  bool operator>(const RTPTime &t) const;
126  bool operator<=(const RTPTime &t) const;
127  bool operator>=(const RTPTime &t) const;
128 
129  bool IsZero() const { return m_t == 0; }
130 private:
131 #ifdef RTP_HAVE_QUERYPERFORMANCECOUNTER
132  static inline uint64_t CalculateMicroseconds(uint64_t performancecount,uint64_t performancefrequency);
133 #endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
134 
135  double m_t;
136 };
137 
138 inline RTPTime::RTPTime(double t)
139 {
140  m_t = t;
141 }
142 
143 inline RTPTime::RTPTime(int64_t seconds, uint32_t microseconds)
144 {
145  if (seconds >= 0)
146  {
147  m_t = (double)seconds + 1e-6*(double)microseconds;
148  }
149  else
150  {
151  int64_t possec = -seconds;
152 
153  m_t = (double)possec + 1e-6*(double)microseconds;
154  m_t = -m_t;
155  }
156 }
157 
159 {
160  if (ntptime.GetMSW() < RTP_NTPTIMEOFFSET)
161  {
162  m_t = 0;
163  }
164  else
165  {
166  uint32_t sec = ntptime.GetMSW() - RTP_NTPTIMEOFFSET;
167 
168  double x = (double)ntptime.GetLSW();
169  x /= (65536.0*65536.0);
170  x *= 1000000.0;
171  uint32_t microsec = (uint32_t)x;
172 
173  m_t = (double)sec + 1e-6*(double)microsec;
174  }
175 }
176 
177 inline int64_t RTPTime::GetSeconds() const
178 {
179  return (int64_t)m_t;
180 }
181 
182 inline uint32_t RTPTime::GetMicroSeconds() const
183 {
184  uint32_t microsec;
185 
186  if (m_t >= 0)
187  {
188  int64_t sec = (int64_t)m_t;
189  microsec = (uint32_t)(1e6*(m_t - (double)sec) + 0.5);
190  }
191  else // m_t < 0
192  {
193  int64_t sec = (int64_t)(-m_t);
194  microsec = (uint32_t)(1e6*((-m_t) - (double)sec) + 0.5);
195  }
196 
197  if (microsec >= 1000000)
198  return 999999;
199  // Unsigned, it can never be less than 0
200  // if (microsec < 0)
201  // return 0;
202  return microsec;
203 }
204 
205 #ifdef RTP_HAVE_QUERYPERFORMANCECOUNTER
206 
207 inline uint64_t RTPTime::CalculateMicroseconds(uint64_t performancecount,uint64_t performancefrequency)
208 {
209  uint64_t f = performancefrequency;
210  uint64_t a = performancecount;
211  uint64_t b = a/f;
212  uint64_t c = a%f; // a = b*f+c => (a*1000000)/f = b*1000000+(c*1000000)/f
213 
214  return b*C1000000+(c*C1000000)/f;
215 }
216 
217 inline RTPTime RTPTime::CurrentTime()
218 {
219  static int inited = 0;
220  static uint64_t microseconds, initmicroseconds;
221  static LARGE_INTEGER performancefrequency;
222 
223  uint64_t emulate_microseconds, microdiff;
224  SYSTEMTIME systemtime;
225  FILETIME filetime;
226 
227  LARGE_INTEGER performancecount;
228 
229  QueryPerformanceCounter(&performancecount);
230 
231  if(!inited){
232  inited = 1;
233  QueryPerformanceFrequency(&performancefrequency);
234  GetSystemTime(&systemtime);
235  SystemTimeToFileTime(&systemtime,&filetime);
236  microseconds = ( ((uint64_t)(filetime.dwHighDateTime) << 32) + (uint64_t)(filetime.dwLowDateTime) ) / (uint64_t)10;
237  microseconds-= CEPOCH; // EPOCH
238  initmicroseconds = CalculateMicroseconds(performancecount.QuadPart, performancefrequency.QuadPart);
239  }
240 
241  emulate_microseconds = CalculateMicroseconds(performancecount.QuadPart, performancefrequency.QuadPart);
242 
243  microdiff = emulate_microseconds - initmicroseconds;
244 
245  double t = 1e-6*(double)(microseconds + microdiff);
246  return RTPTime(t);
247 }
248 
249 inline void RTPTime::Wait(const RTPTime &delay)
250 {
251  if (delay.m_t <= 0)
252  return;
253 
254  uint64_t sec = (uint64_t)delay.m_t;
255  uint32_t microsec = (uint32_t)(1e6*(delay.m_t-(double)sec));
256  DWORD t = ((DWORD)sec)*1000+(((DWORD)microsec)/1000);
257  Sleep(t);
258 }
259 
260 #else // unix style
261 
262 #ifdef RTP_HAVE_CLOCK_GETTIME
263 inline double RTPTime_timespecToDouble(struct timespec &ts)
264 {
265  return (double)ts.tv_sec + 1e-9*(double)ts.tv_nsec;
266 }
267 
268 inline RTPTime RTPTime::CurrentTime()
269 {
270  static bool s_initialized = false;
271  static double s_startOffet = 0;
272 
273  if (!s_initialized)
274  {
275  s_initialized = true;
276 
277  // Get the corresponding times in system time and monotonic time
278  struct timespec tpSys, tpMono;
279 
280  clock_gettime(CLOCK_REALTIME, &tpSys);
281  clock_gettime(CLOCK_MONOTONIC, &tpMono);
282 
283  double tSys = RTPTime_timespecToDouble(tpSys);
284  double tMono = RTPTime_timespecToDouble(tpMono);
285 
286  s_startOffet = tSys - tMono;
287  return tSys;
288  }
289 
290  struct timespec tpMono;
291  clock_gettime(CLOCK_MONOTONIC, &tpMono);
292 
293  double tMono0 = RTPTime_timespecToDouble(tpMono);
294  return tMono0 + s_startOffet;
295 }
296 
297 #else // gettimeofday fallback
298 
300 {
301  struct timeval tv;
302 
303  gettimeofday(&tv,0);
304  return RTPTime((uint64_t)tv.tv_sec,(uint32_t)tv.tv_usec);
305 }
306 #endif // RTP_HAVE_CLOCK_GETTIME
307 
308 inline void RTPTime::Wait(const RTPTime &delay)
309 {
310  if (delay.m_t <= 0)
311  return;
312 
313  uint64_t sec = (uint64_t)delay.m_t;
314  uint64_t nanosec = (uint32_t)(1e9*(delay.m_t-(double)sec));
315 
316  struct timespec req,rem;
317  int ret;
318 
319  req.tv_sec = (time_t)sec;
320  req.tv_nsec = ((long)nanosec);
321  do
322  {
323  ret = nanosleep(&req,&rem);
324  req = rem;
325  } while (ret == -1 && errno == EINTR);
326 }
327 
328 #endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
329 
330 inline RTPTime &RTPTime::operator-=(const RTPTime &t)
331 {
332  m_t -= t.m_t;
333  return *this;
334 }
335 
336 inline RTPTime &RTPTime::operator+=(const RTPTime &t)
337 {
338  m_t += t.m_t;
339  return *this;
340 }
341 
343 {
344  uint32_t sec = (uint32_t)m_t;
345  uint32_t microsec = (uint32_t)((m_t - (double)sec)*1e6);
346 
347  uint32_t msw = sec+RTP_NTPTIMEOFFSET;
348  uint32_t lsw;
349  double x;
350 
351  x = microsec/1000000.0;
352  x *= (65536.0*65536.0);
353  lsw = (uint32_t)x;
354 
355  return RTPNTPTime(msw,lsw);
356 }
357 
358 inline bool RTPTime::operator<(const RTPTime &t) const
359 {
360  return m_t < t.m_t;
361 }
362 
363 inline bool RTPTime::operator>(const RTPTime &t) const
364 {
365  return m_t > t.m_t;
366 }
367 
368 inline bool RTPTime::operator<=(const RTPTime &t) const
369 {
370  return m_t <= t.m_t;
371 }
372 
373 inline bool RTPTime::operator>=(const RTPTime &t) const
374 {
375  return m_t >= t.m_t;
376 }
377 
378 class JRTPLIB_IMPORTEXPORT RTPTimeInitializerObject
379 {
380 public:
381  RTPTimeInitializerObject();
382  void Dummy() { dummy++; }
383 private:
384  int dummy;
385 };
386 
387 extern RTPTimeInitializerObject timeinit;
388 
389 } // end namespace
390 
391 
392 #endif // RTPTIMEUTILITIES_H
393 
This is a simple wrapper for the most significant word (MSW) and least significant word (LSW) of an N...
Definition: rtptimeutilities.h:67
RTPNTPTime(uint32_t m, uint32_t l)
This constructor creates and instance with MSW m and LSW l.
Definition: rtptimeutilities.h:70
uint32_t GetMSW() const
Returns the most significant word.
Definition: rtptimeutilities.h:73
uint32_t GetLSW() const
Returns the least significant word.
Definition: rtptimeutilities.h:76
This class is used to specify wallclock time, delay intervals etc.
Definition: rtptimeutilities.h:86
int64_t GetSeconds() const
Returns the number of seconds stored in this instance.
Definition: rtptimeutilities.h:177
static void Wait(const RTPTime &delay)
This function waits the amount of time specified in delay.
Definition: rtptimeutilities.h:308
uint32_t GetMicroSeconds() const
Returns the number of microseconds stored in this instance.
Definition: rtptimeutilities.h:182
static RTPTime CurrentTime()
Returns an RTPTime instance representing the current wallclock time.
Definition: rtptimeutilities.h:299
double GetDouble() const
Returns the time stored in this instance, expressed in units of seconds.
Definition: rtptimeutilities.h:117
RTPNTPTime GetNTPTime() const
Returns the NTP time corresponding to the time stored in this instance.
Definition: rtptimeutilities.h:342
RTPTime(double t)
Creates an RTPTime instance representing t, which is expressed in units of seconds.
Definition: rtptimeutilities.h:138