summaryrefslogtreecommitdiff
path: root/tools/udp_pes_scheduler.h
blob: 84913e6bd890e8b4ffa75c388a470b894d83c809 (plain)
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
131
/*
 * 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.9 2007-01-01 09:44:42 phintuka Exp $
 *
 */

#ifndef __UDP_PES_SCHEDULER_H
#define __UDP_PES_SCHEDULER_H

#include <stdint.h>

#include <vdr/tools.h>  // uchar
#include <vdr/thread.h>

//----------------------- cTimePts ------------------------------------------

class cTimePts 
{
  private:
    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);

    int64_t Now(void);
    void    Set(int64_t Pts = 0LL);

    void Pause(void);
    void Resume(void);
    void TrickSpeed(int Multiplier);
};

//----------------------- cUdpPesScheduler ----------------------------------

#include "cxsocket.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; }
    bool Poll(int TimeoutMs, bool Master);
    bool Queue(uint64_t StreamPos, const uchar *Data, int Length);
    void ReSend(int fd, uint64_t Pos, int Seq1, int Seq2);

    void Clear(void);
    bool Flush(int TimeoutMs);

    void Pause(bool On);
    void TrickSpeed(int Multiplier);

  protected:

    // Data for payload handling & buffering

    // Signalling
    cCondVar  m_Cond;
    cMutex    m_Lock;

    // Clients
    int       m_Handles[MAX_UDP_HANDLES];
    int       m_wmem[MAX_UDP_HANDLES];  /* kernel buffer size */

    cxSocket  m_fd_rtp;
    cxSocket  m_fd_rtcp;

    // Queue
    int m_QueueNextSeq;      /* next outgoing */
    int m_QueuePending;      /* outgoing queue size */
    cUdpBackLog *m_BackLog;  /* queue for incoming data (not yet send) and retransmissions */

    // Data for scheduling algorithm
    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 */

    // RTCP
    uint64_t  m_LastRtcpTime;
    uint32_t  m_Frames;
    uint32_t  m_Octets;

    // Scheduling 

    int64_t last_delay_time;
    bool    m_TrickSpeed;

    bool m_Master;   /* if true, we are master metronom for playback */
  
    int  calc_elapsed_vtime(int64_t pts, bool Audio);
    void Schedule(const uchar *Data, int Length);

    bool m_Running;
    virtual void Action(void);

    void Send_RTCP(void);

    int  m_fd_sap;

    void Send_SAP(bool Announce = true);
};

#endif