diff options
author | phintuka <phintuka> | 2007-01-06 03:42:17 +0000 |
---|---|---|
committer | phintuka <phintuka> | 2007-01-06 03:42:17 +0000 |
commit | 3299942e4b20cdad72916fb5a6ce1edcd6604fda (patch) | |
tree | d786e6c3806a77f0bf199fe74dc25d4bdc228461 /tools/time_pts.c | |
parent | a10869604e4865db453cb19d50136c28f407bd29 (diff) | |
download | xineliboutput-3299942e4b20cdad72916fb5a6ce1edcd6604fda.tar.gz xineliboutput-3299942e4b20cdad72916fb5a6ce1edcd6604fda.tar.bz2 |
Initial import (moved from udp_pes_scheduler.c)
Diffstat (limited to 'tools/time_pts.c')
-rw-r--r-- | tools/time_pts.c | 154 |
1 files changed, 154 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); +} + |