Mercurial > mplayer.hg
annotate libmpdemux/realrtsp/real.c @ 17332:88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
bandwidth, if bandwidth cmdline option is given. Also, if that's given,
it uses it for sdp stream selection. If not given, the behavior is the
same as before.
It's used to implement something like turboplay in realplayer.
Patch by Tomas Janousek >>> tomi (At) nomi (.) cz <<<
author | rtognimp |
---|---|
date | Fri, 06 Jan 2006 14:39:10 +0000 |
parents | 88a58f2dda55 |
children | eb60c209a117 |
rev | line source |
---|---|
9922 | 1 /* |
2 * This file was ported to MPlayer from xine CVS real.c,v 1.8 2003/03/30 17:11:50 | |
3 */ | |
4 | |
5 /* | |
6 * Copyright (C) 2002 the xine project | |
7 * | |
8 * This file is part of xine, a free video player. | |
9 * | |
10 * xine is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * xine is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program; if not, write to the Free Software | |
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
23 * | |
24 * | |
25 * special functions for real streams. | |
26 * adopted from joschkas real tools. | |
27 * | |
28 */ | |
29 | |
30 #include <stdio.h> | |
31 #include <string.h> | |
32 | |
10115 | 33 #include "../config.h" |
34 #include "../bswap.h" | |
9922 | 35 #include "real.h" |
36 #include "asmrp.h" | |
37 #include "sdpplin.h" | |
12266 | 38 #include "xbuffer.h" |
9922 | 39 |
40 /* | |
41 #define LOG | |
42 */ | |
43 | |
44 const unsigned char xor_table[] = { | |
45 0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53, | |
46 0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70, | |
47 0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09, | |
48 0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02, | |
49 0x10, 0x57, 0x05, 0x18, 0x54, 0x00, 0x00, 0x00 }; | |
50 | |
51 | |
10115 | 52 #define BE_32C(x,y) (*((uint32_t*)(x))=be2me_32(y)) |
9922 | 53 |
10115 | 54 #define BE_16(x) be2me_16(*(uint16_t*)(x)) |
9922 | 55 |
10115 | 56 #define BE_32(x) be2me_32(*(uint32_t*)(x)) |
9922 | 57 |
12845 | 58 #ifndef MAX |
9922 | 59 #define MAX(x,y) ((x>y) ? x : y) |
12845 | 60 #endif |
9922 | 61 |
62 #ifdef LOG | |
63 static void hexdump (const char *buf, int length) { | |
64 | |
65 int i; | |
66 | |
67 printf (" hexdump> "); | |
68 for (i = 0; i < length; i++) { | |
69 unsigned char c = buf[i]; | |
70 | |
71 printf ("%02x", c); | |
72 | |
73 if ((i % 16) == 15) | |
74 printf ("\n "); | |
75 | |
76 if ((i % 2) == 1) | |
77 printf (" "); | |
78 | |
79 } | |
80 printf ("\n"); | |
81 } | |
82 #endif | |
83 | |
84 | |
85 static void hash(char *field, char *param) { | |
86 | |
87 uint32_t a, b, c, d; | |
88 | |
89 | |
90 /* fill variables */ | |
10115 | 91 a= le2me_32(*(uint32_t*)(field)); |
92 b= le2me_32(*(uint32_t*)(field+4)); | |
93 c= le2me_32(*(uint32_t*)(field+8)); | |
94 d= le2me_32(*(uint32_t*)(field+12)); | |
9922 | 95 |
96 #ifdef LOG | |
97 printf("real: hash input: %x %x %x %x\n", a, b, c, d); | |
98 printf("real: hash parameter:\n"); | |
99 hexdump(param, 64); | |
10115 | 100 printf("real: hash field:\n"); |
101 hexdump(field, 64+24); | |
9922 | 102 #endif |
103 | |
10115 | 104 a = ((b & c) | (~b & d)) + le2me_32(*((uint32_t*)(param+0x00))) + a - 0x28955B88; |
9922 | 105 a = ((a << 0x07) | (a >> 0x19)) + b; |
10115 | 106 d = ((a & b) | (~a & c)) + le2me_32(*((uint32_t*)(param+0x04))) + d - 0x173848AA; |
9922 | 107 d = ((d << 0x0c) | (d >> 0x14)) + a; |
10115 | 108 c = ((d & a) | (~d & b)) + le2me_32(*((uint32_t*)(param+0x08))) + c + 0x242070DB; |
9922 | 109 c = ((c << 0x11) | (c >> 0x0f)) + d; |
10115 | 110 b = ((c & d) | (~c & a)) + le2me_32(*((uint32_t*)(param+0x0c))) + b - 0x3E423112; |
9922 | 111 b = ((b << 0x16) | (b >> 0x0a)) + c; |
10115 | 112 a = ((b & c) | (~b & d)) + le2me_32(*((uint32_t*)(param+0x10))) + a - 0x0A83F051; |
9922 | 113 a = ((a << 0x07) | (a >> 0x19)) + b; |
10115 | 114 d = ((a & b) | (~a & c)) + le2me_32(*((uint32_t*)(param+0x14))) + d + 0x4787C62A; |
9922 | 115 d = ((d << 0x0c) | (d >> 0x14)) + a; |
10115 | 116 c = ((d & a) | (~d & b)) + le2me_32(*((uint32_t*)(param+0x18))) + c - 0x57CFB9ED; |
9922 | 117 c = ((c << 0x11) | (c >> 0x0f)) + d; |
10115 | 118 b = ((c & d) | (~c & a)) + le2me_32(*((uint32_t*)(param+0x1c))) + b - 0x02B96AFF; |
9922 | 119 b = ((b << 0x16) | (b >> 0x0a)) + c; |
10115 | 120 a = ((b & c) | (~b & d)) + le2me_32(*((uint32_t*)(param+0x20))) + a + 0x698098D8; |
9922 | 121 a = ((a << 0x07) | (a >> 0x19)) + b; |
10115 | 122 d = ((a & b) | (~a & c)) + le2me_32(*((uint32_t*)(param+0x24))) + d - 0x74BB0851; |
9922 | 123 d = ((d << 0x0c) | (d >> 0x14)) + a; |
10115 | 124 c = ((d & a) | (~d & b)) + le2me_32(*((uint32_t*)(param+0x28))) + c - 0x0000A44F; |
9922 | 125 c = ((c << 0x11) | (c >> 0x0f)) + d; |
10115 | 126 b = ((c & d) | (~c & a)) + le2me_32(*((uint32_t*)(param+0x2C))) + b - 0x76A32842; |
9922 | 127 b = ((b << 0x16) | (b >> 0x0a)) + c; |
10115 | 128 a = ((b & c) | (~b & d)) + le2me_32(*((uint32_t*)(param+0x30))) + a + 0x6B901122; |
9922 | 129 a = ((a << 0x07) | (a >> 0x19)) + b; |
10115 | 130 d = ((a & b) | (~a & c)) + le2me_32(*((uint32_t*)(param+0x34))) + d - 0x02678E6D; |
9922 | 131 d = ((d << 0x0c) | (d >> 0x14)) + a; |
10115 | 132 c = ((d & a) | (~d & b)) + le2me_32(*((uint32_t*)(param+0x38))) + c - 0x5986BC72; |
9922 | 133 c = ((c << 0x11) | (c >> 0x0f)) + d; |
10115 | 134 b = ((c & d) | (~c & a)) + le2me_32(*((uint32_t*)(param+0x3c))) + b + 0x49B40821; |
9922 | 135 b = ((b << 0x16) | (b >> 0x0a)) + c; |
136 | |
10115 | 137 a = ((b & d) | (~d & c)) + le2me_32(*((uint32_t*)(param+0x04))) + a - 0x09E1DA9E; |
9922 | 138 a = ((a << 0x05) | (a >> 0x1b)) + b; |
10115 | 139 d = ((a & c) | (~c & b)) + le2me_32(*((uint32_t*)(param+0x18))) + d - 0x3FBF4CC0; |
9922 | 140 d = ((d << 0x09) | (d >> 0x17)) + a; |
10115 | 141 c = ((d & b) | (~b & a)) + le2me_32(*((uint32_t*)(param+0x2c))) + c + 0x265E5A51; |
9922 | 142 c = ((c << 0x0e) | (c >> 0x12)) + d; |
10115 | 143 b = ((c & a) | (~a & d)) + le2me_32(*((uint32_t*)(param+0x00))) + b - 0x16493856; |
9922 | 144 b = ((b << 0x14) | (b >> 0x0c)) + c; |
10115 | 145 a = ((b & d) | (~d & c)) + le2me_32(*((uint32_t*)(param+0x14))) + a - 0x29D0EFA3; |
9922 | 146 a = ((a << 0x05) | (a >> 0x1b)) + b; |
10115 | 147 d = ((a & c) | (~c & b)) + le2me_32(*((uint32_t*)(param+0x28))) + d + 0x02441453; |
9922 | 148 d = ((d << 0x09) | (d >> 0x17)) + a; |
10115 | 149 c = ((d & b) | (~b & a)) + le2me_32(*((uint32_t*)(param+0x3c))) + c - 0x275E197F; |
9922 | 150 c = ((c << 0x0e) | (c >> 0x12)) + d; |
10115 | 151 b = ((c & a) | (~a & d)) + le2me_32(*((uint32_t*)(param+0x10))) + b - 0x182C0438; |
9922 | 152 b = ((b << 0x14) | (b >> 0x0c)) + c; |
10115 | 153 a = ((b & d) | (~d & c)) + le2me_32(*((uint32_t*)(param+0x24))) + a + 0x21E1CDE6; |
9922 | 154 a = ((a << 0x05) | (a >> 0x1b)) + b; |
10115 | 155 d = ((a & c) | (~c & b)) + le2me_32(*((uint32_t*)(param+0x38))) + d - 0x3CC8F82A; |
9922 | 156 d = ((d << 0x09) | (d >> 0x17)) + a; |
10115 | 157 c = ((d & b) | (~b & a)) + le2me_32(*((uint32_t*)(param+0x0c))) + c - 0x0B2AF279; |
9922 | 158 c = ((c << 0x0e) | (c >> 0x12)) + d; |
10115 | 159 b = ((c & a) | (~a & d)) + le2me_32(*((uint32_t*)(param+0x20))) + b + 0x455A14ED; |
9922 | 160 b = ((b << 0x14) | (b >> 0x0c)) + c; |
10115 | 161 a = ((b & d) | (~d & c)) + le2me_32(*((uint32_t*)(param+0x34))) + a - 0x561C16FB; |
9922 | 162 a = ((a << 0x05) | (a >> 0x1b)) + b; |
10115 | 163 d = ((a & c) | (~c & b)) + le2me_32(*((uint32_t*)(param+0x08))) + d - 0x03105C08; |
9922 | 164 d = ((d << 0x09) | (d >> 0x17)) + a; |
10115 | 165 c = ((d & b) | (~b & a)) + le2me_32(*((uint32_t*)(param+0x1c))) + c + 0x676F02D9; |
9922 | 166 c = ((c << 0x0e) | (c >> 0x12)) + d; |
10115 | 167 b = ((c & a) | (~a & d)) + le2me_32(*((uint32_t*)(param+0x30))) + b - 0x72D5B376; |
9922 | 168 b = ((b << 0x14) | (b >> 0x0c)) + c; |
169 | |
10115 | 170 a = (b ^ c ^ d) + le2me_32(*((uint32_t*)(param+0x14))) + a - 0x0005C6BE; |
9922 | 171 a = ((a << 0x04) | (a >> 0x1c)) + b; |
10115 | 172 d = (a ^ b ^ c) + le2me_32(*((uint32_t*)(param+0x20))) + d - 0x788E097F; |
9922 | 173 d = ((d << 0x0b) | (d >> 0x15)) + a; |
10115 | 174 c = (d ^ a ^ b) + le2me_32(*((uint32_t*)(param+0x2c))) + c + 0x6D9D6122; |
9922 | 175 c = ((c << 0x10) | (c >> 0x10)) + d; |
10115 | 176 b = (c ^ d ^ a) + le2me_32(*((uint32_t*)(param+0x38))) + b - 0x021AC7F4; |
9922 | 177 b = ((b << 0x17) | (b >> 0x09)) + c; |
10115 | 178 a = (b ^ c ^ d) + le2me_32(*((uint32_t*)(param+0x04))) + a - 0x5B4115BC; |
9922 | 179 a = ((a << 0x04) | (a >> 0x1c)) + b; |
10115 | 180 d = (a ^ b ^ c) + le2me_32(*((uint32_t*)(param+0x10))) + d + 0x4BDECFA9; |
9922 | 181 d = ((d << 0x0b) | (d >> 0x15)) + a; |
10115 | 182 c = (d ^ a ^ b) + le2me_32(*((uint32_t*)(param+0x1c))) + c - 0x0944B4A0; |
9922 | 183 c = ((c << 0x10) | (c >> 0x10)) + d; |
10115 | 184 b = (c ^ d ^ a) + le2me_32(*((uint32_t*)(param+0x28))) + b - 0x41404390; |
9922 | 185 b = ((b << 0x17) | (b >> 0x09)) + c; |
10115 | 186 a = (b ^ c ^ d) + le2me_32(*((uint32_t*)(param+0x34))) + a + 0x289B7EC6; |
9922 | 187 a = ((a << 0x04) | (a >> 0x1c)) + b; |
10115 | 188 d = (a ^ b ^ c) + le2me_32(*((uint32_t*)(param+0x00))) + d - 0x155ED806; |
9922 | 189 d = ((d << 0x0b) | (d >> 0x15)) + a; |
10115 | 190 c = (d ^ a ^ b) + le2me_32(*((uint32_t*)(param+0x0c))) + c - 0x2B10CF7B; |
9922 | 191 c = ((c << 0x10) | (c >> 0x10)) + d; |
10115 | 192 b = (c ^ d ^ a) + le2me_32(*((uint32_t*)(param+0x18))) + b + 0x04881D05; |
9922 | 193 b = ((b << 0x17) | (b >> 0x09)) + c; |
10115 | 194 a = (b ^ c ^ d) + le2me_32(*((uint32_t*)(param+0x24))) + a - 0x262B2FC7; |
9922 | 195 a = ((a << 0x04) | (a >> 0x1c)) + b; |
10115 | 196 d = (a ^ b ^ c) + le2me_32(*((uint32_t*)(param+0x30))) + d - 0x1924661B; |
9922 | 197 d = ((d << 0x0b) | (d >> 0x15)) + a; |
10115 | 198 c = (d ^ a ^ b) + le2me_32(*((uint32_t*)(param+0x3c))) + c + 0x1fa27cf8; |
9922 | 199 c = ((c << 0x10) | (c >> 0x10)) + d; |
10115 | 200 b = (c ^ d ^ a) + le2me_32(*((uint32_t*)(param+0x08))) + b - 0x3B53A99B; |
9922 | 201 b = ((b << 0x17) | (b >> 0x09)) + c; |
202 | |
10115 | 203 a = ((~d | b) ^ c) + le2me_32(*((uint32_t*)(param+0x00))) + a - 0x0BD6DDBC; |
9922 | 204 a = ((a << 0x06) | (a >> 0x1a)) + b; |
10115 | 205 d = ((~c | a) ^ b) + le2me_32(*((uint32_t*)(param+0x1c))) + d + 0x432AFF97; |
9922 | 206 d = ((d << 0x0a) | (d >> 0x16)) + a; |
10115 | 207 c = ((~b | d) ^ a) + le2me_32(*((uint32_t*)(param+0x38))) + c - 0x546BDC59; |
9922 | 208 c = ((c << 0x0f) | (c >> 0x11)) + d; |
10115 | 209 b = ((~a | c) ^ d) + le2me_32(*((uint32_t*)(param+0x14))) + b - 0x036C5FC7; |
9922 | 210 b = ((b << 0x15) | (b >> 0x0b)) + c; |
10115 | 211 a = ((~d | b) ^ c) + le2me_32(*((uint32_t*)(param+0x30))) + a + 0x655B59C3; |
9922 | 212 a = ((a << 0x06) | (a >> 0x1a)) + b; |
10115 | 213 d = ((~c | a) ^ b) + le2me_32(*((uint32_t*)(param+0x0C))) + d - 0x70F3336E; |
9922 | 214 d = ((d << 0x0a) | (d >> 0x16)) + a; |
10115 | 215 c = ((~b | d) ^ a) + le2me_32(*((uint32_t*)(param+0x28))) + c - 0x00100B83; |
9922 | 216 c = ((c << 0x0f) | (c >> 0x11)) + d; |
10115 | 217 b = ((~a | c) ^ d) + le2me_32(*((uint32_t*)(param+0x04))) + b - 0x7A7BA22F; |
9922 | 218 b = ((b << 0x15) | (b >> 0x0b)) + c; |
10115 | 219 a = ((~d | b) ^ c) + le2me_32(*((uint32_t*)(param+0x20))) + a + 0x6FA87E4F; |
9922 | 220 a = ((a << 0x06) | (a >> 0x1a)) + b; |
10115 | 221 d = ((~c | a) ^ b) + le2me_32(*((uint32_t*)(param+0x3c))) + d - 0x01D31920; |
9922 | 222 d = ((d << 0x0a) | (d >> 0x16)) + a; |
10115 | 223 c = ((~b | d) ^ a) + le2me_32(*((uint32_t*)(param+0x18))) + c - 0x5CFEBCEC; |
9922 | 224 c = ((c << 0x0f) | (c >> 0x11)) + d; |
10115 | 225 b = ((~a | c) ^ d) + le2me_32(*((uint32_t*)(param+0x34))) + b + 0x4E0811A1; |
9922 | 226 b = ((b << 0x15) | (b >> 0x0b)) + c; |
10115 | 227 a = ((~d | b) ^ c) + le2me_32(*((uint32_t*)(param+0x10))) + a - 0x08AC817E; |
9922 | 228 a = ((a << 0x06) | (a >> 0x1a)) + b; |
10115 | 229 d = ((~c | a) ^ b) + le2me_32(*((uint32_t*)(param+0x2c))) + d - 0x42C50DCB; |
9922 | 230 d = ((d << 0x0a) | (d >> 0x16)) + a; |
10115 | 231 c = ((~b | d) ^ a) + le2me_32(*((uint32_t*)(param+0x08))) + c + 0x2AD7D2BB; |
9922 | 232 c = ((c << 0x0f) | (c >> 0x11)) + d; |
10115 | 233 b = ((~a | c) ^ d) + le2me_32(*((uint32_t*)(param+0x24))) + b - 0x14792C6F; |
9922 | 234 b = ((b << 0x15) | (b >> 0x0b)) + c; |
235 | |
236 #ifdef LOG | |
237 printf("real: hash output: %x %x %x %x\n", a, b, c, d); | |
238 #endif | |
239 | |
10115 | 240 a += le2me_32(*((uint32_t *)(field+0))); |
241 *((uint32_t *)(field+0)) = le2me_32(a); | |
242 b += le2me_32(*((uint32_t *)(field+4))); | |
243 *((uint32_t *)(field+4)) = le2me_32(b); | |
244 c += le2me_32(*((uint32_t *)(field+8))); | |
245 *((uint32_t *)(field+8)) = le2me_32(c); | |
246 d += le2me_32(*((uint32_t *)(field+12))); | |
247 *((uint32_t *)(field+12)) = le2me_32(d); | |
248 | |
249 #ifdef LOG | |
250 printf("real: hash field:\n"); | |
251 hexdump(field, 64+24); | |
252 #endif | |
9922 | 253 } |
254 | |
255 static void call_hash (char *key, char *challenge, int len) { | |
256 | |
257 uint32_t *ptr1, *ptr2; | |
258 uint32_t a, b, c, d; | |
10115 | 259 uint32_t tmp; |
260 | |
9922 | 261 ptr1=(uint32_t*)(key+16); |
262 ptr2=(uint32_t*)(key+20); | |
263 | |
10115 | 264 a = le2me_32(*ptr1); |
9922 | 265 b = (a >> 3) & 0x3f; |
266 a += len * 8; | |
10115 | 267 *ptr1 = le2me_32(a); |
9922 | 268 |
269 if (a < (len << 3)) | |
270 { | |
271 #ifdef LOG | |
272 printf("not verified: (len << 3) > a true\n"); | |
273 #endif | |
274 ptr2 += 4; | |
275 } | |
276 | |
10115 | 277 tmp = le2me_32(*ptr2); |
278 tmp += (len >> 0x1d); | |
279 *ptr2 = le2me_32(tmp); | |
9922 | 280 a = 64 - b; |
281 c = 0; | |
282 if (a <= len) | |
283 { | |
284 | |
285 memcpy(key+b+24, challenge, a); | |
286 hash(key, key+24); | |
287 c = a; | |
288 d = c + 0x3f; | |
289 | |
290 while ( d < len ) { | |
291 | |
292 #ifdef LOG | |
293 printf("not verified: while ( d < len )\n"); | |
294 #endif | |
295 hash(key, challenge+d-0x3f); | |
296 d += 64; | |
297 c += 64; | |
298 } | |
299 b = 0; | |
300 } | |
301 | |
302 memcpy(key+b+24, challenge+c, len-c); | |
303 } | |
304 | |
305 static void calc_response (char *result, char *field) { | |
306 | |
307 char buf1[128]; | |
308 char buf2[128]; | |
309 int i; | |
310 | |
311 memset (buf1, 0, 64); | |
312 *buf1 = 128; | |
313 | |
314 memcpy (buf2, field+16, 8); | |
315 | |
10115 | 316 i = ( le2me_32(*((uint32_t*)(buf2))) >> 3 ) & 0x3f; |
9922 | 317 |
318 if (i < 56) { | |
319 i = 56 - i; | |
320 } else { | |
321 #ifdef LOG | |
322 printf("not verified: ! (i < 56)\n"); | |
323 #endif | |
324 i = 120 - i; | |
325 } | |
326 | |
327 call_hash (field, buf1, i); | |
328 call_hash (field, buf2, 8); | |
329 | |
330 memcpy (result, field, 16); | |
331 | |
332 } | |
333 | |
334 | |
335 static void calc_response_string (char *result, char *challenge) { | |
336 | |
337 char field[128]; | |
338 char zres[20]; | |
339 int i; | |
340 | |
341 /* initialize our field */ | |
342 BE_32C (field, 0x01234567); | |
343 BE_32C ((field+4), 0x89ABCDEF); | |
344 BE_32C ((field+8), 0xFEDCBA98); | |
345 BE_32C ((field+12), 0x76543210); | |
346 BE_32C ((field+16), 0x00000000); | |
347 BE_32C ((field+20), 0x00000000); | |
348 | |
349 /* calculate response */ | |
350 call_hash(field, challenge, 64); | |
351 calc_response(zres,field); | |
352 | |
353 /* convert zres to ascii string */ | |
354 for (i=0; i<16; i++ ) { | |
355 char a, b; | |
356 | |
357 a = (zres[i] >> 4) & 15; | |
358 b = zres[i] & 15; | |
359 | |
360 result[i*2] = ((a<10) ? (a+48) : (a+87)) & 255; | |
361 result[i*2+1] = ((b<10) ? (b+48) : (b+87)) & 255; | |
362 } | |
363 } | |
364 | |
365 void real_calc_response_and_checksum (char *response, char *chksum, char *challenge) { | |
366 | |
367 int ch_len, table_len, resp_len; | |
368 int i; | |
369 char *ptr; | |
370 char buf[128]; | |
371 | |
372 /* initialize return values */ | |
373 memset(response, 0, 64); | |
374 memset(chksum, 0, 34); | |
375 | |
376 /* initialize buffer */ | |
377 memset(buf, 0, 128); | |
378 ptr=buf; | |
379 BE_32C(ptr, 0xa1e9149d); | |
380 ptr+=4; | |
381 BE_32C(ptr, 0x0e6b3b59); | |
382 ptr+=4; | |
383 | |
384 /* some (length) checks */ | |
385 if (challenge != NULL) | |
386 { | |
387 ch_len = strlen (challenge); | |
388 | |
389 if (ch_len == 40) /* what a hack... */ | |
390 { | |
391 challenge[32]=0; | |
392 ch_len=32; | |
393 } | |
394 if ( ch_len > 56 ) ch_len=56; | |
395 | |
396 /* copy challenge to buf */ | |
397 memcpy(ptr, challenge, ch_len); | |
398 } | |
399 | |
400 if (xor_table != NULL) | |
401 { | |
402 table_len = strlen(xor_table); | |
403 | |
404 if (table_len > 56) table_len=56; | |
405 | |
406 /* xor challenge bytewise with xor_table */ | |
407 for (i=0; i<table_len; i++) | |
408 ptr[i] = ptr[i] ^ xor_table[i]; | |
409 } | |
410 | |
411 calc_response_string (response, buf); | |
412 | |
413 /* add tail */ | |
414 resp_len = strlen (response); | |
415 strcpy (&response[resp_len], "01d0a8e3"); | |
416 | |
417 /* calculate checksum */ | |
418 for (i=0; i<resp_len/4; i++) | |
419 chksum[i] = response[i*4]; | |
420 } | |
421 | |
422 | |
423 /* | |
424 * takes a MLTI-Chunk and a rule number got from match_asm_rule, | |
425 * returns a pointer to selected data and number of bytes in that. | |
426 */ | |
427 | |
12266 | 428 static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection, char **out) { |
9922 | 429 |
430 int numrules, codec, size; | |
431 int i; | |
432 | |
433 /* MLTI chunk should begin with MLTI */ | |
434 | |
435 if ((mlti_chunk[0] != 'M') | |
436 ||(mlti_chunk[1] != 'L') | |
437 ||(mlti_chunk[2] != 'T') | |
438 ||(mlti_chunk[3] != 'I')) | |
439 { | |
440 #ifdef LOG | |
441 printf("libreal: MLTI tag not detected, copying data\n"); | |
442 #endif | |
12266 | 443 *out = xbuffer_copyin(*out, 0, mlti_chunk, mlti_size); |
9922 | 444 return mlti_size; |
445 } | |
446 | |
447 mlti_chunk+=4; | |
448 | |
449 /* next 16 bits are the number of rules */ | |
450 numrules=BE_16(mlti_chunk); | |
451 if (selection >= numrules) return 0; | |
452 | |
453 /* now <numrules> indices of codecs follows */ | |
454 /* we skip to selection */ | |
455 mlti_chunk+=(selection+1)*2; | |
456 | |
457 /* get our index */ | |
458 codec=BE_16(mlti_chunk); | |
459 | |
460 /* skip to number of codecs */ | |
461 mlti_chunk+=(numrules-selection)*2; | |
462 | |
463 /* get number of codecs */ | |
464 numrules=BE_16(mlti_chunk); | |
465 | |
466 if (codec >= numrules) { | |
467 printf("codec index >= number of codecs. %i %i\n", codec, numrules); | |
468 return 0; | |
469 } | |
470 | |
471 mlti_chunk+=2; | |
472 | |
473 /* now seek to selected codec */ | |
474 for (i=0; i<codec; i++) { | |
475 size=BE_32(mlti_chunk); | |
476 mlti_chunk+=size+4; | |
477 } | |
478 | |
479 size=BE_32(mlti_chunk); | |
480 | |
481 #ifdef LOG | |
482 hexdump(mlti_chunk+4, size); | |
483 #endif | |
12266 | 484 *out = xbuffer_copyin(*out, 0, mlti_chunk+4, size); |
9922 | 485 return size; |
486 } | |
487 | |
488 /* | |
489 * looking at stream description. | |
490 */ | |
491 | |
12266 | 492 rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) { |
9922 | 493 |
494 sdpplin_t *desc; | |
495 rmff_header_t *header; | |
12266 | 496 char *buf; |
9922 | 497 int len, i; |
498 int max_bit_rate=0; | |
499 int avg_bit_rate=0; | |
500 int max_packet_size=0; | |
501 int avg_packet_size=0; | |
502 int duration=0; | |
503 | |
504 | |
505 if (!data) return NULL; | |
506 | |
507 desc=sdpplin_parse(data); | |
508 | |
509 if (!desc) return NULL; | |
510 | |
12266 | 511 buf = xbuffer_init(2048); |
9922 | 512 header=calloc(1,sizeof(rmff_header_t)); |
513 | |
514 header->fileheader=rmff_new_fileheader(4+desc->stream_count); | |
515 header->cont=rmff_new_cont( | |
516 desc->title, | |
517 desc->author, | |
518 desc->copyright, | |
519 desc->abstract); | |
520 header->data=rmff_new_dataheader(0,0); | |
521 header->streams=calloc(1,sizeof(rmff_mdpr_t*)*(desc->stream_count+1)); | |
522 #ifdef LOG | |
523 printf("number of streams: %u\n", desc->stream_count); | |
524 #endif | |
525 | |
526 for (i=0; i<desc->stream_count; i++) { | |
527 | |
528 int j=0; | |
529 int n; | |
530 char b[64]; | |
531 int rulematches[16]; | |
532 | |
533 #ifdef LOG | |
534 printf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth); | |
535 #endif | |
536 n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches); | |
537 for (j=0; j<n; j++) { | |
538 #ifdef LOG | |
539 printf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id); | |
540 #endif | |
541 sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]); | |
12266 | 542 *stream_rules = xbuffer_strcat(*stream_rules, b); |
9922 | 543 } |
544 | |
14144
1fcb18e39ef9
Fix streaming if not mlti_data (for some non-multirate streams)
rtognimp
parents:
13676
diff
changeset
|
545 if (!desc->stream[i]->mlti_data) { |
1fcb18e39ef9
Fix streaming if not mlti_data (for some non-multirate streams)
rtognimp
parents:
13676
diff
changeset
|
546 len = 0; |
1fcb18e39ef9
Fix streaming if not mlti_data (for some non-multirate streams)
rtognimp
parents:
13676
diff
changeset
|
547 buf = NULL; |
1fcb18e39ef9
Fix streaming if not mlti_data (for some non-multirate streams)
rtognimp
parents:
13676
diff
changeset
|
548 } else |
12266 | 549 len=select_mlti_data(desc->stream[i]->mlti_data, desc->stream[i]->mlti_data_size, rulematches[0], &buf); |
9922 | 550 |
551 header->streams[i]=rmff_new_mdpr( | |
552 desc->stream[i]->stream_id, | |
553 desc->stream[i]->max_bit_rate, | |
554 desc->stream[i]->avg_bit_rate, | |
555 desc->stream[i]->max_packet_size, | |
556 desc->stream[i]->avg_packet_size, | |
557 desc->stream[i]->start_time, | |
558 desc->stream[i]->preroll, | |
559 desc->stream[i]->duration, | |
560 desc->stream[i]->stream_name, | |
561 desc->stream[i]->mime_type, | |
562 len, | |
563 buf); | |
564 | |
565 duration=MAX(duration,desc->stream[i]->duration); | |
566 max_bit_rate+=desc->stream[i]->max_bit_rate; | |
567 avg_bit_rate+=desc->stream[i]->avg_bit_rate; | |
568 max_packet_size=MAX(max_packet_size, desc->stream[i]->max_packet_size); | |
569 if (avg_packet_size) | |
570 avg_packet_size=(avg_packet_size + desc->stream[i]->avg_packet_size) / 2; | |
571 else | |
572 avg_packet_size=desc->stream[i]->avg_packet_size; | |
573 } | |
574 | |
12266 | 575 if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',') |
576 (*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */ | |
9922 | 577 |
578 header->prop=rmff_new_prop( | |
579 max_bit_rate, | |
580 avg_bit_rate, | |
581 max_packet_size, | |
582 avg_packet_size, | |
583 0, | |
584 duration, | |
585 0, | |
586 0, | |
587 0, | |
588 desc->stream_count, | |
589 desc->flags); | |
590 | |
591 rmff_fix_header(header); | |
12266 | 592 buf = xbuffer_free(buf); |
9922 | 593 |
594 return header; | |
595 } | |
596 | |
12266 | 597 int real_get_rdt_chunk(rtsp_t *rtsp_session, char **buffer) { |
9922 | 598 |
599 int n=1; | |
600 uint8_t header[8]; | |
601 rmff_pheader_t ph; | |
602 int size; | |
11595
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
603 int flags1, flags2; |
9922 | 604 int unknown1; |
605 uint32_t ts; | |
11595
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
606 static uint32_t prev_ts = -1; |
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
607 static int prev_stream_number = -1; |
9922 | 608 |
609 n=rtsp_read_data(rtsp_session, header, 8); | |
610 if (n<8) return 0; | |
611 if (header[0] != 0x24) | |
612 { | |
613 printf("rdt chunk not recognized: got 0x%02x\n", header[0]); | |
614 return 0; | |
615 } | |
13289
2cb80075204c
chunk size fix from Ross Finlayson, ported from xine
diego
parents:
12845
diff
changeset
|
616 size=(header[1]<<16)+(header[2]<<8)+(header[3]); |
9922 | 617 flags1=header[4]; |
618 if ((flags1!=0x40)&&(flags1!=0x42)) | |
619 { | |
620 #ifdef LOG | |
621 printf("got flags1: 0x%02x\n",flags1); | |
622 #endif | |
13676 | 623 if(header[6] == 0x06) { |
624 printf("Stream EOF detected\n"); | |
625 return -1; | |
626 } | |
9922 | 627 header[0]=header[5]; |
628 header[1]=header[6]; | |
629 header[2]=header[7]; | |
630 n=rtsp_read_data(rtsp_session, header+3, 5); | |
631 if (n<5) return 0; | |
632 #ifdef LOG | |
633 printf("ignoring bytes:\n"); | |
634 hexdump(header, 8); | |
635 #endif | |
636 n=rtsp_read_data(rtsp_session, header+4, 4); | |
637 if (n<4) return 0; | |
638 flags1=header[4]; | |
639 size-=9; | |
640 } | |
11595
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
641 flags2=header[7]; |
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
642 // header[5..6] == frame number in stream |
13289
2cb80075204c
chunk size fix from Ross Finlayson, ported from xine
diego
parents:
12845
diff
changeset
|
643 unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]); |
9922 | 644 n=rtsp_read_data(rtsp_session, header, 6); |
645 if (n<6) return 0; | |
646 ts=BE_32(header); | |
647 | |
648 #ifdef LOG | |
11595
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
649 printf("ts: %u, size: %u, flags: 0x%02x, unknown values: 0x%06x 0x%02x 0x%02x\n", |
9922 | 650 ts, size, flags1, unknown1, header[4], header[5]); |
651 #endif | |
652 size+=2; | |
653 | |
654 ph.object_version=0; | |
655 ph.length=size; | |
656 ph.stream_number=(flags1>>1)&1; | |
657 ph.timestamp=ts; | |
658 ph.reserved=0; | |
11595
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
659 if ((flags2&1) == 0 && (prev_ts != ts || prev_stream_number != ph.stream_number)) |
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
660 { |
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
661 prev_ts = ts; |
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
662 prev_stream_number = ph.stream_number; |
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
663 ph.flags=2; |
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
664 } |
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
665 else |
95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
alex
parents:
11506
diff
changeset
|
666 ph.flags=0; |
12266 | 667 *buffer = xbuffer_ensure_size(*buffer, 12+size); |
668 rmff_dump_pheader(&ph, *buffer); | |
9922 | 669 size-=12; |
12266 | 670 n=rtsp_read_data(rtsp_session, (*buffer)+12, size); |
9922 | 671 |
12271
4adb4a3b52a2
More bounds checking fixes (thnaks to Miguel Freitas)
rtognimp
parents:
12266
diff
changeset
|
672 return (n <= 0) ? 0 : n+12; |
9922 | 673 } |
674 | |
11506
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
675 int convert_timestamp(char *str, int *sec, int *msec) { |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
676 int hh, mm, ss, ms = 0; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
677 if (sscanf(str, "%d:%d:%d.%d", &hh, &mm, &ss, &ms) < 3) { |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
678 hh = 0; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
679 if (sscanf(str, "%d:%d.%d", &mm, &ss, &ms) < 2) { |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
680 mm = 0; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
681 if (sscanf(str, "%d.%d", &ss, &ms) < 1) { |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
682 ss = 0; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
683 ms = 0; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
684 } |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
685 } |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
686 } |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
687 if (sec) |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
688 *sec = hh * 3600 + mm * 60 + ss; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
689 if (msec) |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
690 *msec = ms; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
691 return 1; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
692 } |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
693 |
14159 | 694 //! maximum size of the rtsp description, must be < INT_MAX |
695 #define MAX_DESC_BUF (20 * 1024 * 1024) | |
9922 | 696 rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwidth) { |
697 | |
698 char *description=NULL; | |
699 char *session_id=NULL; | |
700 rmff_header_t *h; | |
701 char *challenge1; | |
702 char challenge2[64]; | |
703 char checksum[34]; | |
12266 | 704 char *subscribe; |
705 char *buf = xbuffer_init(256); | |
9922 | 706 char *mrl=rtsp_get_mrl(rtsp_session); |
707 unsigned int size; | |
708 int status; | |
17332
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
709 uint32_t maxbandwidth = bandwidth; |
9922 | 710 |
711 /* get challenge */ | |
712 challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1")); | |
713 #ifdef LOG | |
714 printf("real: Challenge1: %s\n", challenge1); | |
715 #endif | |
17332
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
716 |
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
717 /* set a reasonable default to get the best stream, unless bandwidth given */ |
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
718 if (!bandwidth) |
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
719 bandwidth = 10485800; |
9922 | 720 |
721 /* request stream description */ | |
722 rtsp_schedule_field(rtsp_session, "Accept: application/sdp"); | |
723 sprintf(buf, "Bandwidth: %u", bandwidth); | |
724 rtsp_schedule_field(rtsp_session, buf); | |
725 rtsp_schedule_field(rtsp_session, "GUID: 00000000-0000-0000-0000-000000000000"); | |
726 rtsp_schedule_field(rtsp_session, "RegionData: 0"); | |
727 rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586"); | |
728 rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1"); | |
729 rtsp_schedule_field(rtsp_session, "Language: en-US"); | |
730 rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup"); | |
731 status=rtsp_request_describe(rtsp_session,NULL); | |
732 | |
733 if ( status<200 || status>299 ) | |
734 { | |
735 char *alert=rtsp_search_answers(rtsp_session,"Alert"); | |
736 if (alert) { | |
737 printf("real: got message from server:\n%s\n", alert); | |
738 } | |
739 rtsp_send_ok(rtsp_session); | |
12266 | 740 buf = xbuffer_free(buf); |
9922 | 741 return NULL; |
742 } | |
743 | |
744 /* receive description */ | |
745 size=0; | |
746 if (!rtsp_search_answers(rtsp_session,"Content-length")) | |
747 printf("real: got no Content-length!\n"); | |
748 else | |
749 size=atoi(rtsp_search_answers(rtsp_session,"Content-length")); | |
750 | |
14159 | 751 // as size is unsigned this also catches the case (size < 0) |
752 if (size > MAX_DESC_BUF) { | |
753 printf("real: Content-length for description too big (> %uMB)!\n", | |
754 MAX_DESC_BUF/(1024*1024) ); | |
755 xbuffer_free(buf); | |
756 return NULL; | |
757 } | |
758 | |
9922 | 759 if (!rtsp_search_answers(rtsp_session,"ETag")) |
760 printf("real: got no ETag!\n"); | |
761 else | |
762 session_id=strdup(rtsp_search_answers(rtsp_session,"ETag")); | |
763 | |
764 #ifdef LOG | |
14159 | 765 printf("real: Stream description size: %u\n", size); |
9922 | 766 #endif |
767 | |
768 description=malloc(sizeof(char)*(size+1)); | |
769 | |
12271
4adb4a3b52a2
More bounds checking fixes (thnaks to Miguel Freitas)
rtognimp
parents:
12266
diff
changeset
|
770 if( rtsp_read_data(rtsp_session, description, size) <= 0) { |
4adb4a3b52a2
More bounds checking fixes (thnaks to Miguel Freitas)
rtognimp
parents:
12266
diff
changeset
|
771 buf = xbuffer_free(buf); |
4adb4a3b52a2
More bounds checking fixes (thnaks to Miguel Freitas)
rtognimp
parents:
12266
diff
changeset
|
772 return NULL; |
4adb4a3b52a2
More bounds checking fixes (thnaks to Miguel Freitas)
rtognimp
parents:
12266
diff
changeset
|
773 } |
9922 | 774 description[size]=0; |
775 | |
776 /* parse sdp (sdpplin) and create a header and a subscribe string */ | |
12266 | 777 subscribe = xbuffer_init(256); |
9922 | 778 strcpy(subscribe, "Subscribe: "); |
12266 | 779 h=real_parse_sdp(description, &subscribe, bandwidth); |
780 if (!h) { | |
781 subscribe = xbuffer_free(subscribe); | |
782 buf = xbuffer_free(buf); | |
783 return NULL; | |
784 } | |
9922 | 785 rmff_fix_header(h); |
786 | |
787 #ifdef LOG | |
788 printf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n", | |
789 h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams); | |
790 #endif | |
791 | |
792 /* setup our streams */ | |
793 real_calc_response_and_checksum (challenge2, checksum, challenge1); | |
12266 | 794 buf = xbuffer_ensure_size(buf, strlen(challenge2) + strlen(checksum) + 32); |
9922 | 795 sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum); |
796 rtsp_schedule_field(rtsp_session, buf); | |
12266 | 797 buf = xbuffer_ensure_size(buf, strlen(session_id) + 32); |
9922 | 798 sprintf(buf, "If-Match: %s", session_id); |
799 rtsp_schedule_field(rtsp_session, buf); | |
800 rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"); | |
12266 | 801 buf = xbuffer_ensure_size(buf, strlen(mrl) + 32); |
9922 | 802 sprintf(buf, "%s/streamid=0", mrl); |
803 rtsp_request_setup(rtsp_session,buf); | |
804 | |
805 if (h->prop->num_streams > 1) { | |
806 rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"); | |
12266 | 807 buf = xbuffer_ensure_size(buf, strlen(session_id) + 32); |
9922 | 808 sprintf(buf, "If-Match: %s", session_id); |
809 rtsp_schedule_field(rtsp_session, buf); | |
810 | |
12266 | 811 buf = xbuffer_ensure_size(buf, strlen(mrl) + 32); |
9922 | 812 sprintf(buf, "%s/streamid=1", mrl); |
813 rtsp_request_setup(rtsp_session,buf); | |
814 } | |
815 /* set stream parameter (bandwidth) with our subscribe string */ | |
816 rtsp_schedule_field(rtsp_session, subscribe); | |
817 rtsp_request_setparameter(rtsp_session,NULL); | |
818 | |
17332
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
819 /* set delivery bandwidth */ |
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
820 if (maxbandwidth) { |
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
821 sprintf(buf, "SetDeliveryBandwidth: Bandwidth=%u;BackOff=0", maxbandwidth); |
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
822 rtsp_schedule_field(rtsp_session, buf); |
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
823 rtsp_request_setparameter(rtsp_session,NULL); |
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
824 } |
88adbc28f60b
This patch makes real rtsp tell the server to deliver data at specified
rtognimp
parents:
14159
diff
changeset
|
825 |
11506
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
826 { |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
827 int s_ss = 0, s_ms = 0, e_ss = 0, e_ms = 0; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
828 char *str; |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
829 if ((str = rtsp_get_param(rtsp_session, "start"))) { |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
830 convert_timestamp(str, &s_ss, &s_ms); |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
831 free(str); |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
832 } |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
833 if ((str = rtsp_get_param(rtsp_session, "end"))) { |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
834 convert_timestamp(str, &e_ss, &e_ms); |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
835 free(str); |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
836 } |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
837 str = buf + sprintf(buf, s_ms ? "%s%d.%d-" : "%s%d-", "Range: npt=", s_ss, s_ms); |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
838 if (e_ss || e_ms) |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
839 sprintf(str, e_ms ? "%d.%d" : "%d", e_ss, e_ms); |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
840 } |
fff1b6f1a9cc
Real rtsp Range parameter (Start and End) support.
rtognimp
parents:
10115
diff
changeset
|
841 rtsp_schedule_field(rtsp_session, buf); |
9922 | 842 /* and finally send a play request */ |
843 rtsp_request_play(rtsp_session,NULL); | |
844 | |
12266 | 845 subscribe = xbuffer_free(subscribe); |
846 buf = xbuffer_free(buf); | |
9922 | 847 return h; |
848 } |