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
132
133
134
135
136
|
/*
* udp_buffer.h: Ring buffer for UDP/RTP streams
*
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
* $Id: udp_buffer.h,v 1.3 2006-12-14 12:30:25 phintuka Exp $
*
*/
#ifndef __UDP_BUFFER_H
#define __UDP_BUFFER_H
#include <stdint.h>
#include "../xine_input_vdr_net.h" // frame headers
#define UDP_BUFFER_SIZE 0x100 // 2^n
#define UDP_BUFFER_MASK 0xff // 2^n - 1
#if UDP_BUFFER_MASK != UDP_SEQ_MASK
# error Buffer handling error !!!
#endif
class cUdpBackLog
{
friend class cUdpScheduler;
private:
cUdpBackLog(cUdpBackLog&);
stream_rtp_header_impl_t *m_UdpBuffer[UDP_BUFFER_SIZE];
int m_UdpBufLen[UDP_BUFFER_SIZE]; /* size of allocated memory, not frame */
int m_PayloadSize[UDP_BUFFER_SIZE]; /* size of frame */
unsigned int m_SeqNo; /* next (outgoing) sequence number */
unsigned int m_RtpSeqNo; /* next (outgoing) RTP sequence number */
protected:
cUdpBackLog()
{
memset(m_UdpBuffer, 0, sizeof(stream_rtp_header_impl_t *)*UDP_BUFFER_SIZE);
memset(m_UdpBufLen, 0, sizeof(int) * UDP_BUFFER_SIZE);
memset(m_PayloadSize, 0, sizeof(int) * UDP_BUFFER_SIZE);
m_SeqNo = 0;
m_RtpSeqNo = random();
}
void Clear(int HowManyFrames)
{
// Clear n last frames from buffer.
// (called to adjust sequence numbering when some
// already allocated frames won't be sent)
//
// Note: Nothing is freed.
// To completely reset buffer it must be deleted and re-created.
//
m_SeqNo = (m_SeqNo + UDP_BUFFER_SIZE - HowManyFrames) & UDP_BUFFER_MASK;
}
virtual ~cUdpBackLog()
{
for(int i=0; i<UDP_BUFFER_SIZE; i++)
if(m_UdpBuffer[i]) {
//m_UdpBufLen[i] = 0;
delete[] m_UdpBuffer[i];
m_UdpBuffer[i] = NULL;
}
}
stream_rtp_header_impl_t *Get(int UdpSeqNo)
{
int BufIndex = UdpSeqNo & UDP_BUFFER_MASK;
return m_UdpBuffer[BufIndex];
}
int PayloadSize(int UdpSeqNo)
{
int BufIndex = UdpSeqNo & UDP_BUFFER_MASK;
return m_UdpBuffer[BufIndex] ? m_PayloadSize[BufIndex] : 0;
}
stream_rtp_header_impl_t *MakeFrame(uint64_t StreamPos,
const uchar *Data, int DataLen)
{
int UdpPacketLen = DataLen + sizeof(stream_rtp_header_impl_t);
int BufIndex = m_SeqNo & UDP_BUFFER_MASK;
// old buffer too small ? free it
if(m_UdpBuffer[BufIndex] && m_UdpBufLen[BufIndex] < UdpPacketLen) {
delete[] m_UdpBuffer[BufIndex];
m_UdpBuffer[BufIndex] = NULL;
}
// no buffer ? alloc it
if(!m_UdpBuffer[BufIndex]) {
m_UdpBuffer[BufIndex] = (stream_rtp_header_impl_t*)new uchar[UdpPacketLen];
m_UdpBufLen[BufIndex] = UdpPacketLen;
}
m_PayloadSize[BufIndex] = DataLen;
// Fill frame to buffer
stream_rtp_header_impl_t *header = m_UdpBuffer[BufIndex];
memcpy(header->payload, Data, DataLen);
// RTP header
header->rtp_hdr.raw[0] = RTP_VERSION_BYTE | RTP_HDREXT_BIT;
header->rtp_hdr.raw[1] = RTP_PAYLOAD_TYPE;
header->rtp_hdr.seq = htons(m_RtpSeqNo & 0xFFFF);
/*header->rtp_hdr.ts = htonl((uint32_t)(RtpScr.Now() & 0xffffffff));*/
/*header->rtp_hdr.ssrc = htonl(m_ssrc);*/
// RTP header extension
header->hdr_ext.hdr.size = htons(RTP_HEADER_EXT_X_SIZE);
header->hdr_ext.hdr.type = htons(RTP_HEADER_EXT_X_TYPE);
// UDP header
header->hdr_ext.pos = htonull(StreamPos);
header->hdr_ext.seq = htons(m_SeqNo);
header->hdr_ext.padding1[0] = 0;
header->hdr_ext.padding1[1] = 0;
m_RtpSeqNo = (m_RtpSeqNo + 1) & 0xFFFF;
m_SeqNo = (m_SeqNo + 1) & UDP_SEQ_MASK;
return header;
}
};
#endif
|