diff options
-rw-r--r-- | tools/time_pts.c | 154 | ||||
-rw-r--r-- | tools/time_pts.h | 38 |
2 files changed, 192 insertions, 0 deletions
diff --git a/tools/time_pts.c b/tools/time_pts.c new file mode 100644 index 00000000..077a9a17 --- /dev/null +++ b/tools/time_pts.c @@ -0,0 +1,154 @@ +/* + * time_pts.c: Adjustable clock in PTS units + * + * See the main source file 'xineliboutput.c' for copyright information and + * how to reach the author. + * + * $Id: time_pts.c,v 1.1 2007-01-06 03:42:17 phintuka Exp $ + * + */ + +#define __STDC_FORMAT_MACROS +#define __STDC_CONSTANT_MACROS +#include <inttypes.h> +#include <time.h> + +#include <vdr/config.h> + +#include "../logdefs.h" // logging + +#include "time_pts.h" + + +#define MAX_SCR ((int64_t)0x1ffffffffLL) + +#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) +#else +# warning Posix monotonic clock not available +#endif + + +cTimePts::cTimePts(void) +{ + m_Paused = false; + m_Multiplier = 90000; + m_Monotonic = false; + +#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) + struct timespec resolution; + + if(clock_getres(CLOCK_MONOTONIC, &resolution)) { + LOGERR("cTimePts: clock_getres(CLOCK_MONOTONIC) failed"); + } else { + LOGDBG("cTimePts: clock_gettime(CLOCK_MONOTONIC): clock resolution %d us", + ((int)resolution.tv_nsec) / 1000); + + if( resolution.tv_sec == 0 && resolution.tv_nsec <= 1000000 ) { + struct timespec tp; + if(clock_gettime(CLOCK_MONOTONIC, &tp)) { + LOGERR("cTimePts: clock_gettime(CLOCL_MONOTONIC) failed"); + } else { + LOGDBG("cTimePts: using monotonic clock"); + m_Monotonic = true; + } + } + } +#endif + + Set(); +} + +int64_t cTimePts::Now(void) +{ + if(m_Paused) + return begin; + + struct timeval t; + +#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) + if(m_Monotonic) { + struct timespec tp; + + if(clock_gettime(CLOCK_MONOTONIC, &tp)) { + LOGERR("cTimePts: clock_gettime(CLOCK_MONOTONIC) failed"); + return -1; + } + + t.tv_sec = tp.tv_sec; + t.tv_usec = tp.tv_nsec/1000; + + } else if (gettimeofday(&t, NULL)) { + LOGERR("cTimePts: gettimeofday() failed"); + return -1; + } +#else + if (gettimeofday(&t, NULL)) { + LOGERR("cTimePts: gettimeofday() failed"); + return -1; + } +#endif + + t.tv_sec -= tbegin.tv_sec; + if(t.tv_usec < tbegin.tv_usec) { + t.tv_sec--; + t.tv_usec += 1000000; + } + t.tv_usec -= tbegin.tv_usec; + + int64_t pts = 0; + pts += ((int64_t)t.tv_sec) * INT64_C(90000); + pts += ((int64_t)t.tv_usec) * INT64_C(90) / INT64_C(1000); + if(m_Multiplier != 90000) + pts = pts * m_Multiplier / INT64_C(90000); + + return ( pts + begin ) & MAX_SCR; +} + +void cTimePts::Set(int64_t Pts) +{ + begin = Pts; + +#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) + if(m_Monotonic) { + struct timespec tp; + + if(!clock_gettime(CLOCK_MONOTONIC, &tp)) { + tbegin.tv_sec = tp.tv_sec; + tbegin.tv_usec = tp.tv_nsec/1000; + return; + } + + LOGERR("cTimePts: clock_gettime(CLOCL_MONOTONIC) failed"); + m_Monotonic = false; + } +#endif + + gettimeofday(&tbegin, NULL); +} + +void cTimePts::Pause(void) +{ + Set(Now()); + m_Paused = true; +} + +void cTimePts::Resume(void) +{ + if(m_Paused) { + Set(begin); + m_Paused = false; + } +} + +void cTimePts::TrickSpeed(int Multiplier) +{ + Set(Now()); + + if(Multiplier < 0) + m_Multiplier = 90000 * (-Multiplier); + else if(Multiplier > 0) + m_Multiplier = 90000 / Multiplier; + else + LOGERR("cTimePts::SetSpeed: Multiplier=%d", Multiplier); +} + diff --git a/tools/time_pts.h b/tools/time_pts.h new file mode 100644 index 00000000..8222d29f --- /dev/null +++ b/tools/time_pts.h @@ -0,0 +1,38 @@ +/* + * time_pts.h: Adjustable clock in PTS units + * + * See the main source file 'xineliboutput.c' for copyright information and + * how to reach the author. + * + * $Id: time_pts.h,v 1.1 2007-01-06 03:39:15 phintuka Exp $ + * + */ + +#ifndef __TIME_PTS_H +#define __TIME_PTS_H + +#include <stdint.h> // int64_t +#include <sys/time.h> // struct timeval + + +class cTimePts +{ + private: + int64_t begin; /* Start time (PTS) */ + struct timeval tbegin; /* Start time (real time) */ + bool m_Paused; + int m_Multiplier; + bool m_Monotonic; + + public: + cTimePts(void); + + int64_t Now(void); + void Set(int64_t Pts = 0LL); + + void Pause(void); + void Resume(void); + void TrickSpeed(int Multiplier); +}; + +#endif // __TIME_PTS_H |