summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/udp_pes_scheduler.c124
-rw-r--r--tools/udp_pes_scheduler.h17
2 files changed, 120 insertions, 21 deletions
diff --git a/tools/udp_pes_scheduler.c b/tools/udp_pes_scheduler.c
index ebcf5b18..138836d6 100644
--- a/tools/udp_pes_scheduler.c
+++ b/tools/udp_pes_scheduler.c
@@ -4,11 +4,12 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: udp_pes_scheduler.c,v 1.12 2006-08-21 00:08:44 phintuka Exp $
+ * $Id: udp_pes_scheduler.c,v 1.13 2006-10-28 02:30:11 phintuka Exp $
*
*/
#define __STDC_FORMAT_MACROS
+#define __STDC_CONSTANT_MACROS
#include <inttypes.h>
#include <stdint.h>
@@ -38,9 +39,37 @@
//----------------------- cTimePts ------------------------------------------
+#include <time.h>
+
cTimePts::cTimePts(void)
{
- m_Paused = false;
+ 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;
+ }
+ }
+ }
+#else
+# warning Posix monotonic clock not available
+#endif
+
Set();
}
@@ -51,26 +80,62 @@ int64_t cTimePts::Now(void)
struct timeval t;
- if (gettimeofday(&t, NULL) == 0) {
- t.tv_sec -= tbegin.tv_sec;
- if(t.tv_usec < tbegin.tv_usec) {
- t.tv_sec--;
- t.tv_usec += 1000000;
+#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_usec -= tbegin.tv_usec;
- return (uint64(t.tv_sec)) * 90000LL +
- (uint64(t.tv_usec)) * 90LL / 1000LL +
- begin;
+ 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;
+
+ return ( ((int64_t)t.tv_sec) * ((int64_t)m_Multiplier) +
+ ((int64_t)t.tv_usec) * INT64_C(90) / INT64_C(1000) +
+ begin) & MAX_SCR;
- return 0;
}
void cTimePts::Set(int64_t Pts)
{
- gettimeofday(&tbegin, NULL);
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)
@@ -84,6 +149,16 @@ void cTimePts::Resume(void)
m_Paused = false;
}
+void cTimePts::TrickSpeed(int Multiplier)
+{
+ if(Multiplier < 0)
+ m_Multiplier = 90000 / (-Multiplier);
+ else if(Multiplier > 0)
+ m_Multiplier = 90000 * Multiplier;
+ else
+ LOGERR("cTimePts::SetSpeed: Multiplier=%d", Multiplier);
+}
+
//----------------------- cUdpScheduler -------------------------------------
//#define LOG_RESEND
@@ -122,6 +197,7 @@ cUdpScheduler::cUdpScheduler()
current_audio_vtime = 0;
current_video_vtime = 0;
+ MasterClock.Set(INT64_C(0));
#ifdef LOG_SCR
data_sent = 0;
@@ -132,14 +208,18 @@ cUdpScheduler::cUdpScheduler()
last_delay_time = 0;
+ // RTP
+
srandom(time(NULL) ^ getpid());
+
m_ssrc = random();
LOGDBG("RTP SSRC: 0x%08x", m_ssrc);
m_LastRtcpTime = 0;
m_Frames = 0;
m_Octets = 0;
+ RtpScr.Set((int64_t)random());
- // queuing
+ // Queuing
int i;
for(i=0; i<MAX_UDP_HANDLES; i++)
@@ -284,6 +364,22 @@ void cUdpScheduler::Pause(bool On)
MasterClock.Resume();
}
+void cUdpScheduler::TrickSpeed(int Multiplier)
+{
+ cMutexLock ml(&m_Lock);
+
+#ifdef LOG_SCR
+ if(Multiplier == 1 || Multiplier == -1)
+ LOGMSG("UDP clock --> normal");
+ else if(Multiplier < 0)
+ LOGMSG("UDP clock --> %dx", -Multiplier);
+ else
+ LOGMSG("UDP clock --> 1/%d", Multiplier);
+#endif
+
+ MasterClock.TrickSpeed(Multiplier);
+}
+
bool cUdpScheduler::Queue(uint64_t StreamPos, const uchar *Data, int Length)
{
cMutexLock ml(&m_Lock);
diff --git a/tools/udp_pes_scheduler.h b/tools/udp_pes_scheduler.h
index 2aaff3b9..73f8f7df 100644
--- a/tools/udp_pes_scheduler.h
+++ b/tools/udp_pes_scheduler.h
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: udp_pes_scheduler.h,v 1.4 2006-08-18 02:19:01 phintuka Exp $
+ * $Id: udp_pes_scheduler.h,v 1.5 2006-10-28 02:30:11 phintuka Exp $
*
*/
@@ -21,9 +21,11 @@
class cTimePts
{
private:
- int64_t begin;
- struct timeval tbegin;
+ 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);
@@ -33,6 +35,7 @@ class cTimePts
void Pause(void);
void Resume(void);
+ void TrickSpeed(int Multiplier);
};
//----------------------- cUdpPesScheduler ----------------------------------
@@ -60,6 +63,7 @@ class cUdpScheduler : public cThread
bool Flush(int TimeoutMs);
void Pause(bool On);
+ void TrickSpeed(int Multiplier);
protected:
@@ -79,16 +83,15 @@ class cUdpScheduler : public cThread
cUdpBackLog *m_BackLog; /* queue for incoming data (not yet send) and retransmissions */
// Data for scheduling algorithm
-
- cTimePts MasterClock; // Current MPEG PTS (synchronized with current stream)
+ cTimePts MasterClock; /* Current MPEG PTS (synchronized to current stream) */
cCondWait CondWait;
int64_t current_audio_vtime;
int64_t current_video_vtime;
// RTP
- uint32_t m_ssrc; // RTP synchronization source id
- cTimePts RtpScr; // 90 kHz monotonic time source for RTP timestamps
+ uint32_t m_ssrc; /* RTP synchronization source id */
+ cTimePts RtpScr; /* 90 kHz monotonic time source for RTP timestamps */
uint64_t m_LastRtcpTime;
uint32_t m_Frames;
uint32_t m_Octets;