JRTPLIB  3.11.0
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 #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  // Unsigned, it can never be less than 0
199  // if (microsec < 0)
200  // return 0;
201  return microsec;
202 }
203 
204 #ifdef RTP_HAVE_QUERYPERFORMANCECOUNTER
205 
206 inline uint64_t RTPTime::CalculateMicroseconds(uint64_t performancecount,uint64_t performancefrequency)
207 {
208  uint64_t f = performancefrequency;
209  uint64_t a = performancecount;
210  uint64_t b = a/f;
211  uint64_t c = a%f; // a = b*f+c => (a*1000000)/f = b*1000000+(c*1000000)/f
212 
213  return b*C1000000+(c*C1000000)/f;
214 }
215 
217 {
218  static int inited = 0;
219  static uint64_t microseconds, initmicroseconds;
220  static LARGE_INTEGER performancefrequency;
221 
222  uint64_t emulate_microseconds, microdiff;
223  SYSTEMTIME systemtime;
224  FILETIME filetime;
225 
226  LARGE_INTEGER performancecount;
227 
228  QueryPerformanceCounter(&performancecount);
229 
230  if(!inited){
231  inited = 1;
232  QueryPerformanceFrequency(&performancefrequency);
233  GetSystemTime(&systemtime);
234  SystemTimeToFileTime(&systemtime,&filetime);
235  microseconds = ( ((uint64_t)(filetime.dwHighDateTime) << 32) + (uint64_t)(filetime.dwLowDateTime) ) / (uint64_t)10;
236  microseconds-= CEPOCH; // EPOCH
237  initmicroseconds = CalculateMicroseconds(performancecount.QuadPart, performancefrequency.QuadPart);
238  }
239 
240  emulate_microseconds = CalculateMicroseconds(performancecount.QuadPart, performancefrequency.QuadPart);
241 
242  microdiff = emulate_microseconds - initmicroseconds;
243 
244  double t = 1e-6*(double)(microseconds + microdiff);
245  return RTPTime(t);
246 }
247 
248 inline void RTPTime::Wait(const RTPTime &delay)
249 {
250  if (delay.m_t <= 0)
251  return;
252 
253  uint64_t sec = (uint64_t)delay.m_t;
254  uint32_t microsec = (uint32_t)(1e6*(delay.m_t-(double)sec));
255  DWORD t = ((DWORD)sec)*1000+(((DWORD)microsec)/1000);
256  Sleep(t);
257 }
258 
259 #else // unix style
260 
261 #ifdef RTP_HAVE_CLOCK_GETTIME
262 inline double RTPTime_timespecToDouble(struct timespec &ts)
263 {
264  return (double)ts.tv_sec + 1e-9*(double)ts.tv_nsec;
265 }
266 
268 {
269  static bool s_initialized = false;
270  static double s_startOffet = 0;
271 
272  if (!s_initialized)
273  {
274  s_initialized = true;
275 
276  // Get the corresponding times in system time and monotonic time
277  struct timespec tpSys, tpMono;
278 
279  clock_gettime(CLOCK_REALTIME, &tpSys);
280  clock_gettime(CLOCK_MONOTONIC, &tpMono);
281 
282  double tSys = RTPTime_timespecToDouble(tpSys);
283  double tMono = RTPTime_timespecToDouble(tpMono);
284 
285  s_startOffet = tSys - tMono;
286  return tSys;
287  }
288 
289  struct timespec tpMono;
290  clock_gettime(CLOCK_MONOTONIC, &tpMono);
291 
292  double tMono0 = RTPTime_timespecToDouble(tpMono);
293  return tMono0 + s_startOffet;
294 }
295 
296 #else // gettimeofday fallback
297 
299 {
300  struct timeval tv;
301 
302  gettimeofday(&tv,0);
303  return RTPTime((uint64_t)tv.tv_sec,(uint32_t)tv.tv_usec);
304 }
305 #endif // RTP_HAVE_CLOCK_GETTIME
306 
307 inline void RTPTime::Wait(const RTPTime &delay)
308 {
309  if (delay.m_t <= 0)
310  return;
311 
312  uint64_t sec = (uint64_t)delay.m_t;
313  uint64_t nanosec = (uint32_t)(1e9*(delay.m_t-(double)sec));
314 
315  struct timespec req,rem;
316 
317  req.tv_sec = (time_t)sec;
318  req.tv_nsec = ((long)nanosec);
319  nanosleep(&req,&rem);
320 }
321 
322 #endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
323 
324 inline RTPTime &RTPTime::operator-=(const RTPTime &t)
325 {
326  m_t -= t.m_t;
327  return *this;
328 }
329 
330 inline RTPTime &RTPTime::operator+=(const RTPTime &t)
331 {
332  m_t += t.m_t;
333  return *this;
334 }
335 
337 {
338  uint32_t sec = (uint32_t)m_t;
339  uint32_t microsec = (uint32_t)((m_t - (double)sec)*1e6);
340 
341  uint32_t msw = sec+RTP_NTPTIMEOFFSET;
342  uint32_t lsw;
343  double x;
344 
345  x = microsec/1000000.0;
346  x *= (65536.0*65536.0);
347  lsw = (uint32_t)x;
348 
349  return RTPNTPTime(msw,lsw);
350 }
351 
352 inline bool RTPTime::operator<(const RTPTime &t) const
353 {
354  return m_t < t.m_t;
355 }
356 
357 inline bool RTPTime::operator>(const RTPTime &t) const
358 {
359  return m_t > t.m_t;
360 }
361 
362 inline bool RTPTime::operator<=(const RTPTime &t) const
363 {
364  return m_t <= t.m_t;
365 }
366 
367 inline bool RTPTime::operator>=(const RTPTime &t) const
368 {
369  return m_t >= t.m_t;
370 }
371 
372 class JRTPLIB_IMPORTEXPORT RTPTimeInitializerObject
373 {
374 public:
375  RTPTimeInitializerObject();
376  void Dummy() { dummy++; }
377 private:
378  int dummy;
379 };
380 
381 extern RTPTimeInitializerObject timeinit;
382 
383 } // end namespace
384 
385 
386 #endif // RTPTIMEUTILITIES_H
387 
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:336
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
Definition: rtpfaketransmitter.h:64
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:307
static RTPTime CurrentTime()
Returns an RTPTime instance representing the current wallclock time.
Definition: rtptimeutilities.h:298