1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/*
* udp_pes_scheduler.h: PES scheduler for UDP/RTP streams
*
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
* $Id: udp_pes_scheduler.h,v 1.23 2010-03-14 11:50:50 phintuka Exp $
*
*/
#ifndef __UDP_PES_SCHEDULER_H
#define __UDP_PES_SCHEDULER_H
#include <stdint.h>
#include <vdr/tools.h> // uchar
#include <vdr/thread.h>
#include "cxsocket.h"
#include "time_pts.h"
#define MAX_UDP_HANDLES 16
class cUdpBackLog;
class cUdpScheduler : public cThread
{
public:
cUdpScheduler();
virtual ~cUdpScheduler();
// fd should be binded & connected to IP:PORT (local+remote) pair !
bool AddHandle(int fd); /* UDP unicast */
void RemoveHandle(int fd); /* UDP unicast */
bool AddRtp(void); /* UDP/RTP multicast */
void RemoveRtp(void); /* UDP/RTP multicast */
bool AddHandle(cxSocket& s) { return AddHandle(s.handle()); }
void RemoveHandle(cxSocket& s) { RemoveHandle(s.handle()); }
bool Clients(void) { return m_Handles[0] >= 0; }
int Poll(int TimeoutMs, bool Master);
bool Queue(eStreamId StreamId, uint64_t StreamPos, const uchar *Data, int Length);
void QueuePadding(void);
void ReSend(int fd, uint64_t Pos, int Seq1, int Seq2);
void Clear(void);
bool Flush(int TimeoutMs);
void Pause(bool On);
void TrickSpeed(const int Multiplier);
void SetScrSpeed(const int Speed = 90000);
protected:
// Signalling
cCondVar m_Cond;
cMutex m_Lock;
// Clients
int m_Handles[MAX_UDP_HANDLES];
uint m_wmem[MAX_UDP_HANDLES]; /* kernel buffer size */
cxSocket m_fd_rtp;
cxSocket m_fd_rtcp;
// Queue
uint m_QueueNextSeq; /* next outgoing */
uint m_QueuePending; /* outgoing queue size */
cUdpBackLog *m_BackLog; /* queue for incoming data (not yet send) and retransmissions */
cMutex m_BackLogDeleteMutex;
// Scheduling
typedef enum {
/* from worst to best */
eScrDetect = 0,
eScrFromVideo = 1,
eScrFromPS1 = 2,
eScrFromAudio = 3,
eScrFromPcr = 4,
} ScrSource_t;
cTimePts m_MasterClock; /* Current MPEG PTS (synchronized to current stream) */
bool m_TrickSpeed; /* current (replay) speed */
bool m_Master; /* if true, we are master metronom for playback */
ScrSource_t m_ScrSource;
int64_t m_CurrentAudioVtime;
int64_t m_CurrentVideoVtime;
int64_t m_CurrentPcr;
uint m_BurstBytes; /* number of bytes sent without sleeps */
uint m_BurstFrames; /* number of frames sent without sleeps */
cCondWait m_CondWait;
int CalcElapsedVtime(int64_t pts, ScrSource_t ScrSource);
void Schedule(const uchar *Data, int Length);
void Scheduler_Sleep(int ms);
void QueuePaddingInternal(void);
// RTP
uint32_t m_ssrc; /* RTP synchronization source id */
cTimePts m_RtpScr; /* 90 kHz monotonic time source for RTP timestamps */
// RTCP
uint64_t m_LastRtcpTime;
uint32_t m_Frames;
uint32_t m_Octets;
void Send_RTCP(void);
// SAP
int m_fd_sap;
void Send_SAP(bool Announce = true);
// Thread
virtual void Action(void);
};
#endif
|