JRTPLIB  3.10.0
rtptimeutilities.h
Go to the documentation of this file.
1 /*
2 
3  This file is a part of JRTPLIB
4  Copyright (c) 1999-2016 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 #endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
47 
48 #define RTP_NTPTIMEOFFSET 2208988800UL
49 
50 #ifdef RTP_HAVE_VSUINT64SUFFIX
51 #define C1000000 1000000ui64
52 #define CEPOCH 11644473600000000ui64
53 #else
54 #define C1000000 1000000ULL
55 #define CEPOCH 11644473600000000ULL
56 #endif // RTP_HAVE_VSUINT64SUFFIX
57 
58 namespace jrtplib
59 {
60 
65 class JRTPLIB_IMPORTEXPORT RTPNTPTime
66 {
67 public:
69  RTPNTPTime(uint32_t m,uint32_t l) { msw = m ; lsw = l; }
70 
72  uint32_t GetMSW() const { return msw; }
73 
75  uint32_t GetLSW() const { return lsw; }
76 private:
77  uint32_t msw,lsw;
78 };
79 
84 class JRTPLIB_IMPORTEXPORT RTPTime
85 {
86 public:
91  static RTPTime CurrentTime();
92 
94  static void Wait(const RTPTime &delay);
95 
97  RTPTime(double t);
98 
104  RTPTime(RTPNTPTime ntptime);
105 
107  RTPTime(int64_t seconds, uint32_t microseconds);
108 
110  int64_t GetSeconds() const;
111 
113  uint32_t GetMicroSeconds() const;
114 
116  double GetDouble() const { return m_t; }
117 
119  RTPNTPTime GetNTPTime() const;
120 
121  RTPTime &operator-=(const RTPTime &t);
122  RTPTime &operator+=(const RTPTime &t);
123  bool operator<(const RTPTime &t) const;
124  bool operator>(const RTPTime &t) const;
125  bool operator<=(const RTPTime &t) const;
126  bool operator>=(const RTPTime &t) const;
127 
128  bool IsZero() const { return m_t == 0; }
129 private:
130 #ifdef RTP_HAVE_QUERYPERFORMANCECOUNTER
131  static inline uint64_t CalculateMicroseconds(uint64_t performancecount,uint64_t performancefrequency);
132 #endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
133 
134  double m_t;
135 };
136 
137 inline RTPTime::RTPTime(double t)
138 {
139  m_t = t;
140 }
141 
142 inline RTPTime::RTPTime(int64_t seconds, uint32_t microseconds)
143 {
144  if (seconds >= 0)
145  {
146  m_t = (double)seconds + 1e-6*(double)microseconds;
147  }
148  else
149  {
150  int64_t possec = -seconds;
151 
152  m_t = (double)possec + 1e-6*(double)microseconds;
153  m_t = -m_t;
154  }
155 }
156 
158 {
159  if (ntptime.GetMSW() < RTP_NTPTIMEOFFSET)
160  {
161  m_t = 0;
162  }
163  else
164  {
165  uint32_t sec = ntptime.GetMSW() - RTP_NTPTIMEOFFSET;
166 
167  double x = (double)ntptime.GetLSW();
168  x /= (65536.0*65536.0);
169  x *= 1000000.0;
170  uint32_t microsec = (uint32_t)x;
171 
172  m_t = (double)sec + 1e-6*(double)microsec;
173  }
174 }
175 
176 inline int64_t RTPTime::GetSeconds() const
177 {
178  return (int64_t)m_t;
179 }
180 
181 inline uint32_t RTPTime::GetMicroSeconds() const
182 {
183  uint32_t microsec;
184 
185  if (m_t >= 0)
186  {
187  int64_t sec = (int64_t)m_t;
188  microsec = (uint32_t)(1e6*(m_t - (double)sec) + 0.5);
189  }
190  else // m_t < 0
191  {
192  int64_t sec = (int64_t)(-m_t);
193  microsec = (uint32_t)(1e6*((-m_t) - (double)sec) + 0.5);
194  }
195 
196  if (microsec >= 1000000)
197  return 999999;
198  if (microsec < 0)
199  return 0;
200  return microsec;
201 }
202 
203 #ifdef RTP_HAVE_QUERYPERFORMANCECOUNTER
204 
205 inline uint64_t RTPTime::CalculateMicroseconds(uint64_t performancecount,uint64_t performancefrequency)
206 {
207  uint64_t f = performancefrequency;
208  uint64_t a = performancecount;
209  uint64_t b = a/f;
210  uint64_t c = a%f; // a = b*f+c => (a*1000000)/f = b*1000000+(c*1000000)/f
211 
212  return b*C1000000+(c*C1000000)/f;
213 }
214 
215 inline RTPTime RTPTime::CurrentTime()
216 {
217  static int inited = 0;
218  static uint64_t microseconds, initmicroseconds;
219  static LARGE_INTEGER performancefrequency;
220 
221  uint64_t emulate_microseconds, microdiff;
222  SYSTEMTIME systemtime;
223  FILETIME filetime;
224 
225  LARGE_INTEGER performancecount;
226 
227  QueryPerformanceCounter(&performancecount);
228 
229  if(!inited){
230  inited = 1;
231  QueryPerformanceFrequency(&performancefrequency);
232  GetSystemTime(&systemtime);
233  SystemTimeToFileTime(&systemtime,&filetime);
234  microseconds = ( ((uint64_t)(filetime.dwHighDateTime) << 32) + (uint64_t)(filetime.dwLowDateTime) ) / (uint64_t)10;
235  microseconds-= CEPOCH; // EPOCH
236  initmicroseconds = CalculateMicroseconds(performancecount.QuadPart, performancefrequency.QuadPart);
237  }
238 
239  emulate_microseconds = CalculateMicroseconds(performancecount.QuadPart, performancefrequency.QuadPart);
240 
241  microdiff = emulate_microseconds - initmicroseconds;
242 
243  double t = 1e-6*(double)(microseconds + microdiff);
244  return RTPTime(t);
245 }
246 
247 inline void RTPTime::Wait(const RTPTime &delay)
248 {
249  if (delay.m_t <= 0)
250  return;
251 
252  uint64_t sec = (uint64_t)delay.m_t;
253  uint32_t microsec = (uint32_t)(1e6*(delay.m_t-(double)sec));
254  DWORD t = ((DWORD)sec)*1000+(((DWORD)microsec)/1000);
255  Sleep(t);
256 }
257 
258 #else // unix style
259 
260 #ifdef RTP_HAVE_CLOCK_GETTIME
261 inline double RTPTime_timespecToDouble(struct timespec &ts)
262 {
263  return (double)ts.tv_sec + 1e-9*(double)ts.tv_nsec;
264 }
265 
266 inline RTPTime RTPTime::CurrentTime()
267 {
268  static bool s_initialized = false;
269  static double s_startOffet = 0;
270 
271  if (!s_initialized)
272  {
273  s_initialized = true;
274 
275  // Get the corresponding times in system time and monotonic time
276  struct timespec tpSys, tpMono;
277 
278  clock_gettime(CLOCK_REALTIME, &tpSys);
279  clock_gettime(CLOCK_MONOTONIC, &tpMono);
280 
281  double tSys = RTPTime_timespecToDouble(tpSys);
282  double tMono = RTPTime_timespecToDouble(tpMono);
283 
284  s_startOffet = tSys - tMono;
285  return tSys;
286  }
287 
288  struct timespec tpMono;
289  clock_gettime(CLOCK_MONOTONIC, &tpMono);
290 
291  double tMono0 = RTPTime_timespecToDouble(tpMono);
292  return tMono0 + s_startOffet;
293 }
294 
295 #else // gettimeofday fallback
296 
298 {
299  struct timeval tv;
300 
301  gettimeofday(&tv,0);
302  return RTPTime((uint64_t)tv.tv_sec,(uint32_t)tv.tv_usec);
303 }
304 #endif // RTP_HAVE_CLOCK_GETTIME
305 
306 inline void RTPTime::Wait(const RTPTime &delay)
307 {
308  if (delay.m_t <= 0)
309  return;
310 
311  uint64_t sec = (uint64_t)delay.m_t;
312  uint64_t nanosec = (uint32_t)(1e9*(delay.m_t-(double)sec));
313 
314  struct timespec req,rem;
315 
316  req.tv_sec = (time_t)sec;
317  req.tv_nsec = ((long)nanosec);
318  nanosleep(&req,&rem);
319 }
320 
321 #endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
322 
323 inline RTPTime &RTPTime::operator-=(const RTPTime &t)
324 {
325  m_t -= t.m_t;
326  return *this;
327 }
328 
329 inline RTPTime &RTPTime::operator+=(const RTPTime &t)
330 {
331  m_t += t.m_t;
332  return *this;
333 }
334 
336 {
337  uint32_t sec = (uint32_t)m_t;
338  uint32_t microsec = (uint32_t)((m_t - (double)sec)*1e6);
339 
340  uint32_t msw = sec+RTP_NTPTIMEOFFSET;
341  uint32_t lsw;
342  double x;
343 
344  x = microsec/1000000.0;
345  x *= (65536.0*65536.0);
346  lsw = (uint32_t)x;
347 
348  return RTPNTPTime(msw,lsw);
349 }
350 
351 inline bool RTPTime::operator<(const RTPTime &t) const
352 {
353  return m_t < t.m_t;
354 }
355 
356 inline bool RTPTime::operator>(const RTPTime &t) const
357 {
358  return m_t > t.m_t;
359 }
360 
361 inline bool RTPTime::operator<=(const RTPTime &t) const
362 {
363  return m_t <= t.m_t;
364 }
365 
366 inline bool RTPTime::operator>=(const RTPTime &t) const
367 {
368  return m_t >= t.m_t;
369 }
370 
371 class JRTPLIB_IMPORTEXPORT RTPTimeInitializerObject
372 {
373 public:
374  RTPTimeInitializerObject();
375  void Dummy() { dummy++; }
376 private:
377  int dummy;
378 };
379 
380 extern RTPTimeInitializerObject timeinit;
381 
382 } // end namespace
383 
384 
385 #endif // RTPTIMEUTILITIES_H
386 
uint32_t GetMicroSeconds() const
Returns the number of microseconds stored in this instance.
Definition: rtptimeutilities.h:181
RTPNTPTime GetNTPTime() const
Returns the NTP time corresponding to the time stored in this instance.
Definition: rtptimeutilities.h:335
This is a simple wrapper for the most significant word (MSW) and least significant word (LSW) of an N...
Definition: rtptimeutilities.h:65
RTPNTPTime(uint32_t m, uint32_t l)
This constructor creates and instance with MSW m and LSW l.
Definition: rtptimeutilities.h:69
double GetDouble() const
Returns the time stored in this instance, expressed in units of seconds.
Definition: rtptimeutilities.h:116
RTPTime(double t)
Creates an RTPTime instance representing t, which is expressed in units of seconds.
Definition: rtptimeutilities.h:137
This class is used to specify wallclock time, delay intervals etc.
Definition: rtptimeutilities.h:84
uint32_t GetLSW() const
Returns the least significant word.
Definition: rtptimeutilities.h:75
uint32_t GetMSW() const
Returns the most significant word.
Definition: rtptimeutilities.h:72
int64_t GetSeconds() const
Returns the number of seconds stored in this instance.
Definition: rtptimeutilities.h:176
static void Wait(const RTPTime &delay)
This function waits the amount of time specified in delay.
Definition: rtptimeutilities.h:306
static RTPTime CurrentTime()
Returns an RTPTime instance representing the current wallclock time.
Definition: rtptimeutilities.h:297