From b2c7c4f92a37df4a9cb38b299959e1dbcbb52884 Mon Sep 17 00:00:00 2001 From: phintuka Date: Fri, 7 Jul 2006 05:32:14 +0000 Subject: Added pause/resume to udp scheduler PTS clock Moved RTCP scheduling to udp scheduler --- tools/udp_pes_scheduler.c | 86 +++++++++++++++++++++++++++++++++++++---------- tools/udp_pes_scheduler.h | 15 +++++++-- 2 files changed, 81 insertions(+), 20 deletions(-) (limited to 'tools') diff --git a/tools/udp_pes_scheduler.c b/tools/udp_pes_scheduler.c index caa69485..ad98c035 100644 --- a/tools/udp_pes_scheduler.c +++ b/tools/udp_pes_scheduler.c @@ -4,7 +4,7 @@ * See the main source file 'xineliboutput.c' for copyright information and * how to reach the author. * - * $Id: udp_pes_scheduler.c,v 1.7 2006-07-04 02:34:07 phintuka Exp $ + * $Id: udp_pes_scheduler.c,v 1.8 2006-07-07 05:32:14 phintuka Exp $ * */ @@ -42,11 +42,15 @@ _syscall0(pid_t, gettid) cTimePts::cTimePts(void) { + m_Paused = false; Set(); } int64_t cTimePts::Now(void) { + if(m_Paused) + return begin; + struct timeval t; if (gettimeofday(&t, NULL) == 0) { @@ -71,6 +75,17 @@ void cTimePts::Set(int64_t Pts) begin = Pts; } +void cTimePts::Pause(void) +{ + Set(Now()); + m_Paused = true; +} + +void cTimePts::Resume(void) +{ + m_Paused = false; +} + //----------------------- cUdpScheduler ------------------------------------- //#define LOG_RESEND @@ -86,7 +101,7 @@ const int64_t INITIAL_BURST_TIME = (int64_t)(45000); // pts units (90kHz) // assume seek when when pts difference between two frames exceeds this (1.5 seconds) const int64_t JUMP_LIMIT_TIME = (int64_t)(3*90000/2); // pts units (90kHz) -const int RTCP_MIN_INTERVAL = 90000; // max. once in second +const int RTCP_MIN_INTERVAL = 45000; // max. twice in second typedef enum { eScrDetect, @@ -116,12 +131,15 @@ cUdpScheduler::cUdpScheduler() m_ssrc = random(); LOGDBG("RTP SSRC: 0x%08x", m_ssrc); m_LastRtcpTime = 0; + m_Frames = 0; + m_Octets = 0; // queuing int i; for(i=0; i=0 ) { + m_fd_rtp = fd; + m_fd_rtcp = fd_rtcp; + } + return false; } @@ -176,6 +199,9 @@ void cUdpScheduler::RemoveHandle(int fd) m_Handles[MAX_UDP_HANDLES-1] = -1; + if(fd == m_fd_rtp) + m_fd_rtp = m_fd_rtcp = -1; + if(m_Handles[0] < 0) { // No clients left ... @@ -184,6 +210,9 @@ void cUdpScheduler::RemoveHandle(int fd) m_QueuePending = 0; delete m_BackLog; m_BackLog = new cUdpBackLog; + + m_Frames = 0; + m_Octets = 0; } } @@ -240,6 +269,16 @@ void cUdpScheduler::Clear(void) m_Cond.Broadcast(); } +void cUdpScheduler::Pause(bool On) +{ + cMutexLock ml(&m_Lock); + + if(On) + MasterClock.Pause(); + else + MasterClock.Resume(); +} + bool cUdpScheduler::Queue(uint64_t StreamPos, const uchar *Data, int Length) { cMutexLock ml(&m_Lock); @@ -313,15 +352,20 @@ int cUdpScheduler::calc_elapsed_vtime(int64_t pts, bool Audio) return (int) diff; } -void cUdpScheduler::Send_RTCP(int fd_rtcp, uint32_t Frames, uint64_t Octets) +void cUdpScheduler::Send_RTCP(void) { + if(m_fd_rtcp < 0) + return; + uint64_t scr = RtpScr.Now(); if(scr > (m_LastRtcpTime + RTCP_MIN_INTERVAL)) { uint8_t frame[2048], *content = frame; + char hostname[64] = ""; rtcp_packet_t *msg = (rtcp_packet_t *)content; struct timeval tv; - gettimeofday(&tv,NULL); + gettimeofday(&tv, NULL); + gethostname(hostname, 63); // SR (Sender report) msg->hdr.raw[0] = 0x81; // RTP version = 2, Report count = 1 */ @@ -332,8 +376,8 @@ void cUdpScheduler::Send_RTCP(int fd_rtcp, uint32_t Frames, uint64_t Octets) msg->sr.ntp_sec = htonl(tv.tv_sec + 0x83AA7E80); msg->sr.ntp_frac = htonl((uint32_t)((double)tv.tv_usec*(double)(1LL<<32)*1.0e-6)); msg->sr.rtp_ts = htonl((uint32_t)(scr & 0xffffffff)); - msg->sr.psent = htonl((uint32_t)(Frames & 0xffffffff)); - msg->sr.osent = htonl((uint32_t)(Octets & 0xffffffff)); + msg->sr.psent = htonl((uint32_t)(m_Frames & 0xffffffff)); + msg->sr.osent = htonl((uint32_t)(m_Octets & 0xffffffff)); content += sizeof(rtcp_common_t) + sizeof(rtcp_sr_t); msg = (rtcp_packet_t *)content; @@ -345,7 +389,9 @@ void cUdpScheduler::Send_RTCP(int fd_rtcp, uint32_t Frames, uint64_t Octets) msg->sdes.ssrc = m_ssrc; msg->sdes.item[0].type = RTCP_SDES_CNAME; - sprintf(msg->sdes.item[0].data, "VDR@%s:%d%c%c%c", xc.remote_rtp_addr, xc.remote_rtp_port, 0, 0, 0); + sprintf(msg->sdes.item[0].data, "VDR@%s:%d%c%c%c", + hostname[0] ? hostname : xc.remote_rtp_addr, + xc.remote_rtp_port, 0, 0, 0); msg->sdes.item[0].length = strlen(msg->sdes.item[0].data); msg->hdr.length = htons(1 + 1 + ((msg->sdes.item[0].length - 2) + 3) / 4); @@ -354,7 +400,7 @@ void cUdpScheduler::Send_RTCP(int fd_rtcp, uint32_t Frames, uint64_t Octets) msg = (rtcp_packet_t *)content; // Send - int err = send(fd_rtcp, frame, content - frame, 0); + (void) send(m_fd_rtcp, frame, content - frame, 0); #ifdef LOG_RTCP LOGMSG("RTCP send (%d)", err); for(int i=0; iGet(prevseq); @@ -605,6 +653,10 @@ void cUdpScheduler::Action(void) } m_Lock.Lock(); + m_Frames ++; + m_Octets += PayloadSize; + if((m_Frames & 0xff) == 1) // every 256th frame + Send_RTCP(); } m_Lock.Unlock(); diff --git a/tools/udp_pes_scheduler.h b/tools/udp_pes_scheduler.h index 4fa81a1b..4fe72141 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.2 2006-07-04 02:08:27 phintuka Exp $ + * $Id: udp_pes_scheduler.h,v 1.3 2006-07-07 05:32:14 phintuka Exp $ * */ @@ -23,12 +23,16 @@ class cTimePts private: int64_t begin; struct timeval tbegin; + bool m_Paused; public: cTimePts(void); int64_t Now(void); void Set(int64_t Pts = 0LL); + + void Pause(void); + void Resume(void); }; //----------------------- cUdpPesScheduler ---------------------------------- @@ -45,7 +49,7 @@ class cUdpScheduler : public cThread virtual ~cUdpScheduler(); // fd should be binded & connected to IP:PORT (local+remote) pair ! - bool AddHandle(int fd); + bool AddHandle(int fd, int fd_rtcp=-1); void RemoveHandle(int fd); bool Poll(int TimeoutMs, bool Master); @@ -55,7 +59,7 @@ class cUdpScheduler : public cThread void Clear(void); bool Flush(int TimeoutMs); - void Send_RTCP(int fd_rtcp, uint32_t Frames, uint64_t Octets); + void Pause(bool On); protected: @@ -67,6 +71,7 @@ class cUdpScheduler : public cThread // Clients int m_Handles[MAX_UDP_HANDLES]; + int m_fd_rtp, m_fd_rtcp; // Queue int m_QueueNextSeq; /* next outgoing */ @@ -85,6 +90,8 @@ class cUdpScheduler : public cThread 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; #if 0 int data_sent; /* in current time interval, bytes */ @@ -104,6 +111,8 @@ class cUdpScheduler : public cThread bool m_Running; virtual void Action(void); + + void Send_RTCP(void); }; #endif -- cgit v1.2.3