summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--frontend.h4
-rw-r--r--frontend_svr.c33
-rw-r--r--frontend_svr.h7
-rw-r--r--tools/udp_pes_scheduler.c86
-rw-r--r--tools/udp_pes_scheduler.h15
5 files changed, 102 insertions, 43 deletions
diff --git a/frontend.h b/frontend.h
index 4d18f746..5d28a774 100644
--- a/frontend.h
+++ b/frontend.h
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: frontend.h,v 1.4 2006-07-02 17:11:06 phintuka Exp $
+ * $Id: frontend.h,v 1.5 2006-07-07 05:32:14 phintuka Exp $
*
*/
@@ -48,7 +48,7 @@ class cXinelibThread : public cThread, public cListObject
public:
void PauseOutput(void) { TrickSpeed(0); }
void ResumeOutput(void) { TrickSpeed(1); }
- void TrickSpeed(int Speed);
+ virtual void TrickSpeed(int Speed);
void SetVolume(int NewVolume);
void SetLiveMode(bool);
void SetStillMode(bool);
diff --git a/frontend_svr.c b/frontend_svr.c
index 017a033d..18f9fb1b 100644
--- a/frontend_svr.c
+++ b/frontend_svr.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: frontend_svr.c,v 1.8 2006-07-06 02:57:59 phintuka Exp $
+ * $Id: frontend_svr.c,v 1.9 2006-07-07 05:32:14 phintuka Exp $
*
*/
@@ -457,6 +457,16 @@ int cXinelibServer::Xine_Control(const char *cmd)
return 1;
}
+void cXinelibServer::TrickSpeed(int Speed)
+{
+ if(Speed == 0)
+ m_Scheduler->Pause(true);
+ else
+ m_Scheduler->Pause(false);
+
+ cXinelibThread::TrickSpeed(Speed);
+}
+
bool cXinelibServer::EndOfStreamReached(void)
{
LOCK_THREAD;
@@ -577,7 +587,7 @@ bool cXinelibServer::Listen(int listen_port)
// set listen for discovery messages
CLOSESOCKET(fd_discovery);
- if(xc.remote_usebcast && fd_discovery<0) {
+ if(xc.remote_usebcast) {
struct sockaddr_in sin;
if ((fd_discovery = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_TCP*/)) < 0) {
LOGERR("socket() failed (UDP discovery)");
@@ -608,7 +618,7 @@ bool cXinelibServer::Listen(int listen_port)
CLOSESOCKET(fd_multicast);
CLOSESOCKET(fd_rtcp);
- if(xc.remote_usertp && fd_multicast < 0) {
+ if(xc.remote_usertp) {
//
// RTP
//
@@ -671,7 +681,7 @@ bool cXinelibServer::Listen(int listen_port)
if(xc.remote_rtp_always_on)
LOGMSG("WARNING: RTP Configuration: transmission is always on !");
if(xc.remote_rtp_always_on || m_iMulticastMask)
- m_Scheduler->AddHandle(fd_multicast);
+ m_Scheduler->AddHandle(fd_multicast, fd_rtcp);
}
}
@@ -688,7 +698,6 @@ uchar *cXinelibServer::GrabImage(int &Size, bool Jpeg,
return NULL;
}
-
//
// (Client) Control message handling
//
@@ -826,7 +835,7 @@ void cXinelibServer::Handle_Control_RTP(int cli, const char *arg)
}
if(!m_iMulticastMask)
- m_Scheduler->AddHandle(fd_multicast);
+ m_Scheduler->AddHandle(fd_multicast, fd_rtcp);
m_bMulticast[cli] = true;
m_iMulticastMask |= (1<<cli);
@@ -1170,16 +1179,6 @@ void cXinelibServer::Handle_Discovery_Broadcast()
}
}
-void cXinelibServer::Handle_RTCP(void)
-{
- // Called locked !
- if(fd_rtcp >= 0 && (xc.remote_rtp_always_on || m_iMulticastMask)) {
- if(m_Scheduler) {
- m_Scheduler->Send_RTCP(fd_rtcp, m_Frames, m_StreamPos);
- }
- }
-}
-
void cXinelibServer::Action(void)
{
@@ -1308,8 +1307,6 @@ void cXinelibServer::Action(void)
} /* for(fds) */
- Handle_RTCP();
-
Unlock();
} /* Check poll result */
diff --git a/frontend_svr.h b/frontend_svr.h
index fbb28d07..a4414753 100644
--- a/frontend_svr.h
+++ b/frontend_svr.h
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: frontend_svr.h,v 1.3 2006-07-04 02:06:16 phintuka Exp $
+ * $Id: frontend_svr.h,v 1.4 2006-07-07 05:32:14 phintuka Exp $
*
*/
@@ -36,9 +36,10 @@ class cXinelibServer : public cXinelibThread
protected:
virtual void Action(void);
- void Handle_RTCP(void);
-
public:
+ // Playback control
+ virtual void TrickSpeed(int Speed);
+
// Data transfer
virtual bool Poll(cPoller &Poller, int TimeoutMs);
virtual bool Flush(int TimeoutMs);
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<MAX_UDP_HANDLES; i++)
m_Handles[i] = -1;
+ m_fd_rtp = m_fd_rtcp = -1;
m_BackLog = new cUdpBackLog;
@@ -147,7 +165,7 @@ cUdpScheduler::~cUdpScheduler()
delete m_BackLog;
}
-bool cUdpScheduler::AddHandle(int fd)
+bool cUdpScheduler::AddHandle(int fd, int fd_rtcp)
{
cMutexLock ml(&m_Lock);
@@ -159,6 +177,11 @@ bool cUdpScheduler::AddHandle(int fd)
return true;
}
+ if(fd_rtcp >=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; i<content-frame; i+=16)
@@ -370,6 +416,8 @@ void cUdpScheduler::Send_RTCP(int fd_rtcp, uint32_t Frames, uint64_t Octets)
frame[i+8],frame[i+9],frame[i+10],frame[i+11],
frame[i+12],frame[i+13],frame[i+14],frame[i+15]);
#endif
+
+ m_LastRtcpTime = scr;
}
}
@@ -462,17 +510,14 @@ void cUdpScheduler::Action(void)
sched_get_priority_min(SCHED_RR),
sched_get_priority_max(SCHED_RR));
}
-
- /* UDP Scheduler needs high priority */
- SetPriority(0);
- SetPriority(-1);
- SetPriority(-2);
- SetPriority(-3);
- SetPriority(-4);
- SetPriority(-5);
}
#endif
+ /* UDP Scheduler needs high priority */
+ SetPriority(-5);
+ (void)nice(-5);
+ errno = 0;
+
m_Lock.Lock();
while(m_Running) {
@@ -486,6 +531,9 @@ void cUdpScheduler::Action(void)
if(m_QueuePending <= 0) {
m_Cond.TimedWait(m_Lock, 100);
if(m_QueuePending <= 0) {
+ // Still nothing...
+ // Send padding frame once in 100ms so clients can detect
+ // possible missing frames and server shutdown
static unsigned char padding[] = {0x00,0x00,0x01,0xBE,0x00,0x02,0xff,0xff};
int prevseq = (m_QueueNextSeq + UDP_BUFFER_SIZE - 1) & UDP_BUFFER_MASK;
stream_udp_header_t *frame = m_BackLog->Get(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