1 /* Imported from the dvbstream-0.2 project
3 * Modified for use with MPlayer, for details see the changelog at
4 * http://svn.mplayerhq.hu/mplayer/trunk/
13 #include <sys/types.h>
17 #include <netinet/in.h>
18 #include <sys/socket.h>
19 #include <arpa/inet.h>
28 /* MPEG-2 TS RTP stack */
34 // RTP reorder routines
35 // Also handling of repeated UDP packets (a bug of ExtremeNetworks switches firmware)
36 // rtpreord procedures
37 // write rtp packets in cache
38 // get rtp packets reordered
40 #define MAXRTPPACKETSIN 32 // The number of max packets being reordered
43 unsigned int v
:2; /* version: 2 */
44 unsigned int p
:1; /* is there padding appended: 0 */
45 unsigned int x
:1; /* number of extension headers: 0 */
46 unsigned int cc
:4; /* number of CSRC identifiers: 0 */
47 unsigned int m
:1; /* marker: 0 */
48 unsigned int pt
:7; /* payload type: 33 for MPEG2 TS - RFC 1890 */
49 unsigned int sequence
:16; /* sequence number: random */
52 struct rtpheader
{ /* in network byte order */
54 int timestamp
; /* start: random */
55 int ssrc
; /* random */
60 unsigned char data
[MAXRTPPACKETSIN
][STREAM_BUFFER_SIZE
];
61 unsigned short seq
[MAXRTPPACKETSIN
];
62 unsigned short len
[MAXRTPPACKETSIN
];
65 static struct rtpbuffer rtpbuf
;
67 static int getrtp2(int fd
, struct rtpheader
*rh
, char** data
, int* lengthData
);
69 // RTP Reordering functions
70 // Algorithm works as follows:
71 // If next packet is in sequence just copy it to buffer
72 // Otherwise copy it in cache according to its sequence number
73 // Cache is a circular array where "rtpbuf.first" points to next sequence slot
74 // and keeps track of expected sequence
76 // Initialize rtp cache
77 static void rtp_cache_reset(unsigned short seq
)
82 rtpbuf
.seq
[0] = ++seq
;
84 for (i
=0; i
<MAXRTPPACKETSIN
; i
++) {
89 // Write in a cache the rtp packet in right rtp sequence order
90 static int rtp_cache(int fd
, char *buffer
, int length
)
96 static int is_first
= 1;
98 getrtp2(fd
, &rh
, &data
, &length
);
103 newseq
= seq
- rtpbuf
.seq
[rtpbuf
.first
];
105 if ((newseq
== 0) || is_first
)
109 //mp_msg(MSGT_NETWORK, MSGL_DBG4, "RTP (seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
110 rtpbuf
.first
= ( 1 + rtpbuf
.first
) % MAXRTPPACKETSIN
;
111 rtpbuf
.seq
[rtpbuf
.first
] = ++seq
;
115 if (newseq
> MAXRTPPACKETSIN
)
117 mp_msg(MSGT_NETWORK
, MSGL_DBG2
, "Overrun(seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf
.first
, rtpbuf
.seq
[rtpbuf
.first
], seq
, newseq
);
118 rtp_cache_reset(seq
);
126 // Is it a stray packet re-sent to network?
127 for (i
=0; i
<MAXRTPPACKETSIN
; i
++) {
128 if (rtpbuf
.seq
[i
] == seq
) {
129 mp_msg(MSGT_NETWORK
, MSGL_ERR
, "Stray packet (seq[%d]=%d seq=%d, newseq=%d found at %d)\n", rtpbuf
.first
, rtpbuf
.seq
[rtpbuf
.first
], seq
, newseq
, i
);
130 return 0; // Yes, it is!
133 // Some heuristic to decide when to drop packet or to restart everything
134 if (newseq
> -(3 * MAXRTPPACKETSIN
)) {
135 mp_msg(MSGT_NETWORK
, MSGL_ERR
, "Too Old packet (seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf
.first
, rtpbuf
.seq
[rtpbuf
.first
], seq
, newseq
);
136 return 0; // Yes, it is!
139 mp_msg(MSGT_NETWORK
, MSGL_ERR
, "Underrun(seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf
.first
, rtpbuf
.seq
[rtpbuf
.first
], seq
, newseq
);
141 rtp_cache_reset(seq
);
145 mp_msg(MSGT_NETWORK
, MSGL_DBG4
, "Out of Seq (seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf
.first
, rtpbuf
.seq
[rtpbuf
.first
], seq
, newseq
);
146 newseq
= ( newseq
+ rtpbuf
.first
) % MAXRTPPACKETSIN
;
147 memcpy (rtpbuf
.data
[newseq
], data
, length
);
148 rtpbuf
.len
[newseq
] = length
;
149 rtpbuf
.seq
[newseq
] = seq
;
154 memcpy (buffer
, data
, length
);
158 // Get next packet in cache
159 // Look in cache to get first packet in sequence
160 static int rtp_get_next(int fd
, char *buffer
, int length
)
163 unsigned short nextseq
;
165 // If we have empty buffer we loop to fill it
166 for (i
=0; i
< MAXRTPPACKETSIN
-3; i
++) {
167 if (rtpbuf
.len
[rtpbuf
.first
] != 0) break;
169 length
= rtp_cache(fd
, buffer
, length
) ;
171 // returns on first packet in sequence
173 //mp_msg(MSGT_NETWORK, MSGL_DBG4, "Getting rtp [%d] %hu\n", i, rtpbuf.first);
175 } else if (length
< 0) break;
177 // Only if length == 0 loop continues!
181 while (rtpbuf
.len
[i
] == 0) {
182 mp_msg(MSGT_NETWORK
, MSGL_ERR
, "Lost packet %hu\n", rtpbuf
.seq
[i
]);
183 i
= ( 1 + i
) % MAXRTPPACKETSIN
;
184 if (rtpbuf
.first
== i
) break;
188 // Copy next non empty packet from cache
189 mp_msg(MSGT_NETWORK
, MSGL_DBG4
, "Getting rtp from cache [%d] %hu\n", rtpbuf
.first
, rtpbuf
.seq
[rtpbuf
.first
]);
190 memcpy (buffer
, rtpbuf
.data
[rtpbuf
.first
], rtpbuf
.len
[rtpbuf
.first
]);
191 length
= rtpbuf
.len
[rtpbuf
.first
]; // can be zero?
193 // Reset fisrt slot and go next in cache
194 rtpbuf
.len
[rtpbuf
.first
] = 0;
195 nextseq
= rtpbuf
.seq
[rtpbuf
.first
];
196 rtpbuf
.first
= ( 1 + rtpbuf
.first
) % MAXRTPPACKETSIN
;
197 rtpbuf
.seq
[rtpbuf
.first
] = nextseq
+ 1;
203 // Read next rtp packet using cache
204 int read_rtp_from_server(int fd
, char *buffer
, int length
) {
205 // Following test is ASSERT (i.e. uneuseful if code is correct)
206 if(buffer
==NULL
|| length
<STREAM_BUFFER_SIZE
) {
207 mp_msg(MSGT_NETWORK
, MSGL_ERR
, "RTP buffer invalid; no data return from network\n");
211 // loop just to skip empty packets
212 while ((length
= rtp_get_next(fd
, buffer
, length
)) == 0) {
213 mp_msg(MSGT_NETWORK
, MSGL_ERR
, "Got empty packet from RTP cache!?\n");
219 static int getrtp2(int fd
, struct rtpheader
*rh
, char** data
, int* lengthData
) {
220 static char buf
[1600];
222 char* charP
= (char*) &intP
;
225 lengthPacket
=recv(fd
,buf
,1590,0);
227 mp_msg(MSGT_NETWORK
,MSGL_ERR
,"rtp: socket read error\n");
228 else if (lengthPacket
<12)
229 mp_msg(MSGT_NETWORK
,MSGL_ERR
,"rtp: packet too small (%d) to be an rtp frame (>12bytes)\n", lengthPacket
);
230 if(lengthPacket
<12) {
234 rh
->b
.v
= (unsigned int) ((buf
[0]>>6)&0x03);
235 rh
->b
.p
= (unsigned int) ((buf
[0]>>5)&0x01);
236 rh
->b
.x
= (unsigned int) ((buf
[0]>>4)&0x01);
237 rh
->b
.cc
= (unsigned int) ((buf
[0]>>0)&0x0f);
238 rh
->b
.m
= (unsigned int) ((buf
[1]>>7)&0x01);
239 rh
->b
.pt
= (unsigned int) ((buf
[1]>>0)&0x7f);
241 memcpy(charP
+2,&buf
[2],2);
242 rh
->b
.sequence
= ntohl(intP
);
244 memcpy(charP
,&buf
[4],4);
245 rh
->timestamp
= ntohl(intP
);
247 headerSize
= 12 + 4*rh
->b
.cc
; /* in bytes */
249 *lengthData
= lengthPacket
- headerSize
;
250 *data
= (char*) buf
+ headerSize
;
252 // mp_msg(MSGT_NETWORK,MSGL_DBG2,"Reading rtp: v=%x p=%x x=%x cc=%x m=%x pt=%x seq=%x ts=%x lgth=%d\n",rh->b.v,rh->b.p,rh->b.x,rh->b.cc,rh->b.m,rh->b.pt,rh->b.sequence,rh->timestamp,lengthPacket);