~thopiekar/+junk/vlc-2.0.8-github_community

« back to all changes in this revision

Viewing changes to modules/access/rtsp/real.c

  • Committer: Thomas-Karl Pietrowski
  • Date: 2014-02-25 08:48:22 UTC
  • Revision ID: thopiekar@googlemail.com-20140225084822-52495jnrzv3qlei6
vlc to build against libva-emgd-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * real.c: real rtsp input
 
3
 *****************************************************************************
 
4
 * Copyright (C) 2002-2004 the xine project
 
5
 * Copyright (C) 2005 VideoLAN
 
6
 * $Id: 86eab8ca045453227745b4e6b3755a14cee5cf95 $
 
7
 *
 
8
 * Authors: Gildas Bazin <gbazin@videolan.org>
 
9
 *          Adapted from xine which itself adapted it from joschkas real tools.
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 *
 
16
 * This program is distributed in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License along
 
22
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
23
 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 
24
 *****************************************************************************/
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
# include "config.h"
 
28
#endif
 
29
 
 
30
#include <vlc_common.h>
 
31
#include <vlc_memory.h>
 
32
 
 
33
#include "rtsp.h"
 
34
#include "real.h"
 
35
#include "real_sdpplin.h"
 
36
 
 
37
#define XOR_TABLE_LEN 37
 
38
static const unsigned char xor_table[] = {
 
39
    0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53,
 
40
    0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70,
 
41
    0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09,
 
42
    0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02,
 
43
    0x10, 0x57, 0x05, 0x18, 0x54, 0x00, 0x00, 0x00 };
 
44
 
 
45
#define BE_32(x) GetDWBE(x)
 
46
#define LE_32(x) GetDWLE(x)
 
47
#define BE_16(x) GetWBE(x)
 
48
#define LE_16(x) GetWLE(x)
 
49
#define BE_32C(x,y) do {uint32_t in=y; *(uint32_t *)(x)=GetDWBE(&in);} while(0)
 
50
#define LE_32C(x,y) do {uint32_t in=y; *(uint32_t *)(x)=GetDWLE(&in);} while(0)
 
51
#define MAX(x,y) ((x>y) ? x : y)
 
52
 
 
53
static void hash(char *field, char *param)
 
54
{
 
55
  uint32_t a, b, c, d;
 
56
 
 
57
  /* fill variables */
 
58
  a = LE_32(field);
 
59
  b = LE_32(field+4);
 
60
  c = LE_32(field+8);
 
61
  d = LE_32(field+12);
 
62
 
 
63
  lprintf("hash input: %x %x %x %x\n", a, b, c, d);
 
64
  lprintf("hash parameter:\n");
 
65
 
 
66
  a = ((b & c) | (~b & d)) + LE_32((param+0x00)) + a - 0x28955B88;
 
67
  a = ((a << 0x07) | (a >> 0x19)) + b;
 
68
  d = ((a & b) | (~a & c)) + LE_32((param+0x04)) + d - 0x173848AA;
 
69
  d = ((d << 0x0c) | (d >> 0x14)) + a;
 
70
  c = ((d & a) | (~d & b)) + LE_32((param+0x08)) + c + 0x242070DB;
 
71
  c = ((c << 0x11) | (c >> 0x0f)) + d;
 
72
  b = ((c & d) | (~c & a)) + LE_32((param+0x0c)) + b - 0x3E423112;
 
73
  b = ((b << 0x16) | (b >> 0x0a)) + c;
 
74
  a = ((b & c) | (~b & d)) + LE_32((param+0x10)) + a - 0x0A83F051;
 
75
  a = ((a << 0x07) | (a >> 0x19)) + b;
 
76
  d = ((a & b) | (~a & c)) + LE_32((param+0x14)) + d + 0x4787C62A;
 
77
  d = ((d << 0x0c) | (d >> 0x14)) + a;
 
78
  c = ((d & a) | (~d & b)) + LE_32((param+0x18)) + c - 0x57CFB9ED;
 
79
  c = ((c << 0x11) | (c >> 0x0f)) + d;
 
80
  b = ((c & d) | (~c & a)) + LE_32((param+0x1c)) + b - 0x02B96AFF;
 
81
  b = ((b << 0x16) | (b >> 0x0a)) + c;
 
82
  a = ((b & c) | (~b & d)) + LE_32((param+0x20)) + a + 0x698098D8;
 
83
  a = ((a << 0x07) | (a >> 0x19)) + b;
 
84
  d = ((a & b) | (~a & c)) + LE_32((param+0x24)) + d - 0x74BB0851;
 
85
  d = ((d << 0x0c) | (d >> 0x14)) + a;
 
86
  c = ((d & a) | (~d & b)) + LE_32((param+0x28)) + c - 0x0000A44F;
 
87
  c = ((c << 0x11) | (c >> 0x0f)) + d;
 
88
  b = ((c & d) | (~c & a)) + LE_32((param+0x2C)) + b - 0x76A32842;
 
89
  b = ((b << 0x16) | (b >> 0x0a)) + c;
 
90
  a = ((b & c) | (~b & d)) + LE_32((param+0x30)) + a + 0x6B901122;
 
91
  a = ((a << 0x07) | (a >> 0x19)) + b;
 
92
  d = ((a & b) | (~a & c)) + LE_32((param+0x34)) + d - 0x02678E6D;
 
93
  d = ((d << 0x0c) | (d >> 0x14)) + a;
 
94
  c = ((d & a) | (~d & b)) + LE_32((param+0x38)) + c - 0x5986BC72;
 
95
  c = ((c << 0x11) | (c >> 0x0f)) + d;
 
96
  b = ((c & d) | (~c & a)) + LE_32((param+0x3c)) + b + 0x49B40821;
 
97
  b = ((b << 0x16) | (b >> 0x0a)) + c;
 
98
 
 
99
  a = ((b & d) | (~d & c)) + LE_32((param+0x04)) + a - 0x09E1DA9E;
 
100
  a = ((a << 0x05) | (a >> 0x1b)) + b;
 
101
  d = ((a & c) | (~c & b)) + LE_32((param+0x18)) + d - 0x3FBF4CC0;
 
102
  d = ((d << 0x09) | (d >> 0x17)) + a;
 
103
  c = ((d & b) | (~b & a)) + LE_32((param+0x2c)) + c + 0x265E5A51;
 
104
  c = ((c << 0x0e) | (c >> 0x12)) + d;
 
105
  b = ((c & a) | (~a & d)) + LE_32((param+0x00)) + b - 0x16493856;
 
106
  b = ((b << 0x14) | (b >> 0x0c)) + c;
 
107
  a = ((b & d) | (~d & c)) + LE_32((param+0x14)) + a - 0x29D0EFA3;
 
108
  a = ((a << 0x05) | (a >> 0x1b)) + b;
 
109
  d = ((a & c) | (~c & b)) + LE_32((param+0x28)) + d + 0x02441453;
 
110
  d = ((d << 0x09) | (d >> 0x17)) + a;
 
111
  c = ((d & b) | (~b & a)) + LE_32((param+0x3c)) + c - 0x275E197F;
 
112
  c = ((c << 0x0e) | (c >> 0x12)) + d;
 
113
  b = ((c & a) | (~a & d)) + LE_32((param+0x10)) + b - 0x182C0438;
 
114
  b = ((b << 0x14) | (b >> 0x0c)) + c;
 
115
  a = ((b & d) | (~d & c)) + LE_32((param+0x24)) + a + 0x21E1CDE6;
 
116
  a = ((a << 0x05) | (a >> 0x1b)) + b;
 
117
  d = ((a & c) | (~c & b)) + LE_32((param+0x38)) + d - 0x3CC8F82A;
 
118
  d = ((d << 0x09) | (d >> 0x17)) + a;
 
119
  c = ((d & b) | (~b & a)) + LE_32((param+0x0c)) + c - 0x0B2AF279;
 
120
  c = ((c << 0x0e) | (c >> 0x12)) + d;
 
121
  b = ((c & a) | (~a & d)) + LE_32((param+0x20)) + b + 0x455A14ED;
 
122
  b = ((b << 0x14) | (b >> 0x0c)) + c;
 
123
  a = ((b & d) | (~d & c)) + LE_32((param+0x34)) + a - 0x561C16FB;
 
124
  a = ((a << 0x05) | (a >> 0x1b)) + b;
 
125
  d = ((a & c) | (~c & b)) + LE_32((param+0x08)) + d - 0x03105C08;
 
126
  d = ((d << 0x09) | (d >> 0x17)) + a;
 
127
  c = ((d & b) | (~b & a)) + LE_32((param+0x1c)) + c + 0x676F02D9;
 
128
  c = ((c << 0x0e) | (c >> 0x12)) + d;
 
129
  b = ((c & a) | (~a & d)) + LE_32((param+0x30)) + b - 0x72D5B376;
 
130
  b = ((b << 0x14) | (b >> 0x0c)) + c;
 
131
 
 
132
  a = (b ^ c ^ d) + LE_32((param+0x14)) + a - 0x0005C6BE;
 
133
  a = ((a << 0x04) | (a >> 0x1c)) + b;
 
134
  d = (a ^ b ^ c) + LE_32((param+0x20)) + d - 0x788E097F;
 
135
  d = ((d << 0x0b) | (d >> 0x15)) + a;
 
136
  c = (d ^ a ^ b) + LE_32((param+0x2c)) + c + 0x6D9D6122;
 
137
  c = ((c << 0x10) | (c >> 0x10)) + d;
 
138
  b = (c ^ d ^ a) + LE_32((param+0x38)) + b - 0x021AC7F4;
 
139
  b = ((b << 0x17) | (b >> 0x09)) + c;
 
140
  a = (b ^ c ^ d) + LE_32((param+0x04)) + a - 0x5B4115BC;
 
141
  a = ((a << 0x04) | (a >> 0x1c)) + b;
 
142
  d = (a ^ b ^ c) + LE_32((param+0x10)) + d + 0x4BDECFA9;
 
143
  d = ((d << 0x0b) | (d >> 0x15)) + a;
 
144
  c = (d ^ a ^ b) + LE_32((param+0x1c)) + c - 0x0944B4A0;
 
145
  c = ((c << 0x10) | (c >> 0x10)) + d;
 
146
  b = (c ^ d ^ a) + LE_32((param+0x28)) + b - 0x41404390;
 
147
  b = ((b << 0x17) | (b >> 0x09)) + c;
 
148
  a = (b ^ c ^ d) + LE_32((param+0x34)) + a + 0x289B7EC6;
 
149
  a = ((a << 0x04) | (a >> 0x1c)) + b;
 
150
  d = (a ^ b ^ c) + LE_32((param+0x00)) + d - 0x155ED806;
 
151
  d = ((d << 0x0b) | (d >> 0x15)) + a;
 
152
  c = (d ^ a ^ b) + LE_32((param+0x0c)) + c - 0x2B10CF7B;
 
153
  c = ((c << 0x10) | (c >> 0x10)) + d;
 
154
  b = (c ^ d ^ a) + LE_32((param+0x18)) + b + 0x04881D05;
 
155
  b = ((b << 0x17) | (b >> 0x09)) + c;
 
156
  a = (b ^ c ^ d) + LE_32((param+0x24)) + a - 0x262B2FC7;
 
157
  a = ((a << 0x04) | (a >> 0x1c)) + b;
 
158
  d = (a ^ b ^ c) + LE_32((param+0x30)) + d - 0x1924661B;
 
159
  d = ((d << 0x0b) | (d >> 0x15)) + a;
 
160
  c = (d ^ a ^ b) + LE_32((param+0x3c)) + c + 0x1fa27cf8;
 
161
  c = ((c << 0x10) | (c >> 0x10)) + d;
 
162
  b = (c ^ d ^ a) + LE_32((param+0x08)) + b - 0x3B53A99B;
 
163
  b = ((b << 0x17) | (b >> 0x09)) + c;
 
164
 
 
165
  a = ((~d | b) ^ c)  + LE_32((param+0x00)) + a - 0x0BD6DDBC;
 
166
  a = ((a << 0x06) | (a >> 0x1a)) + b;
 
167
  d = ((~c | a) ^ b)  + LE_32((param+0x1c)) + d + 0x432AFF97;
 
168
  d = ((d << 0x0a) | (d >> 0x16)) + a;
 
169
  c = ((~b | d) ^ a)  + LE_32((param+0x38)) + c - 0x546BDC59;
 
170
  c = ((c << 0x0f) | (c >> 0x11)) + d;
 
171
  b = ((~a | c) ^ d)  + LE_32((param+0x14)) + b - 0x036C5FC7;
 
172
  b = ((b << 0x15) | (b >> 0x0b)) + c;
 
173
  a = ((~d | b) ^ c)  + LE_32((param+0x30)) + a + 0x655B59C3;
 
174
  a = ((a << 0x06) | (a >> 0x1a)) + b;
 
175
  d = ((~c | a) ^ b)  + LE_32((param+0x0C)) + d - 0x70F3336E;
 
176
  d = ((d << 0x0a) | (d >> 0x16)) + a;
 
177
  c = ((~b | d) ^ a)  + LE_32((param+0x28)) + c - 0x00100B83;
 
178
  c = ((c << 0x0f) | (c >> 0x11)) + d;
 
179
  b = ((~a | c) ^ d)  + LE_32((param+0x04)) + b - 0x7A7BA22F;
 
180
  b = ((b << 0x15) | (b >> 0x0b)) + c;
 
181
  a = ((~d | b) ^ c)  + LE_32((param+0x20)) + a + 0x6FA87E4F;
 
182
  a = ((a << 0x06) | (a >> 0x1a)) + b;
 
183
  d = ((~c | a) ^ b)  + LE_32((param+0x3c)) + d - 0x01D31920;
 
184
  d = ((d << 0x0a) | (d >> 0x16)) + a;
 
185
  c = ((~b | d) ^ a)  + LE_32((param+0x18)) + c - 0x5CFEBCEC;
 
186
  c = ((c << 0x0f) | (c >> 0x11)) + d;
 
187
  b = ((~a | c) ^ d)  + LE_32((param+0x34)) + b + 0x4E0811A1;
 
188
  b = ((b << 0x15) | (b >> 0x0b)) + c;
 
189
  a = ((~d | b) ^ c)  + LE_32((param+0x10)) + a - 0x08AC817E;
 
190
  a = ((a << 0x06) | (a >> 0x1a)) + b;
 
191
  d = ((~c | a) ^ b)  + LE_32((param+0x2c)) + d - 0x42C50DCB;
 
192
  d = ((d << 0x0a) | (d >> 0x16)) + a;
 
193
  c = ((~b | d) ^ a)  + LE_32((param+0x08)) + c + 0x2AD7D2BB;
 
194
  c = ((c << 0x0f) | (c >> 0x11)) + d;
 
195
  b = ((~a | c) ^ d)  + LE_32((param+0x24)) + b - 0x14792C6F;
 
196
  b = ((b << 0x15) | (b >> 0x0b)) + c;
 
197
 
 
198
  lprintf("hash output: %x %x %x %x\n", a, b, c, d);
 
199
 
 
200
  a += LE_32(field);
 
201
  b += LE_32(field+4);
 
202
  c += LE_32(field+8);
 
203
  d += LE_32(field+12);
 
204
 
 
205
  LE_32C(field, a);
 
206
  LE_32C(field+4, b);
 
207
  LE_32C(field+8, c);
 
208
  LE_32C(field+12, d);
 
209
}
 
210
 
 
211
static void call_hash (char *key, char *challenge, unsigned int len) {
 
212
  uint8_t *ptr1, *ptr2;
 
213
  uint32_t a, b, c, d, tmp;
 
214
 
 
215
  ptr1=(uint8_t*)(key+16);
 
216
  ptr2=(uint8_t*)(key+20);
 
217
 
 
218
  a = LE_32(ptr1);
 
219
  b = (a >> 3) & 0x3f;
 
220
  a += len * 8;
 
221
  LE_32C(ptr1, a);
 
222
 
 
223
  if (a < (len << 3))
 
224
  {
 
225
    lprintf("not verified: (len << 3) > a true\n");
 
226
    ptr2 += 4;
 
227
  }
 
228
 
 
229
  tmp = LE_32(ptr2) + (len >> 0x1d);
 
230
  LE_32C(ptr2, tmp);
 
231
  a = 64 - b;
 
232
  c = 0;
 
233
  if (a <= len)
 
234
  {
 
235
    memcpy(key+b+24, challenge, a);
 
236
    hash(key, key+24);
 
237
    c = a;
 
238
    d = c + 0x3f;
 
239
 
 
240
    while ( d < len ) {
 
241
      lprintf("not verified:  while ( d < len )\n");
 
242
      hash(key, challenge+d-0x3f);
 
243
      d += 64;
 
244
      c += 64;
 
245
    }
 
246
    b = 0;
 
247
  }
 
248
 
 
249
  memcpy(key+b+24, challenge+c, len-c);
 
250
}
 
251
 
 
252
static void calc_response (char *result, char *field) {
 
253
  char buf1[128];
 
254
  char buf2[128];
 
255
  int i;
 
256
 
 
257
  memset (buf1, 0, 64);
 
258
  *buf1 = 128;
 
259
 
 
260
  memcpy (buf2, field+16, 8);
 
261
  i = ( LE_32((buf2)) >> 3 ) & 0x3f;
 
262
 
 
263
  if (i < 56)
 
264
  {
 
265
    i = 56 - i;
 
266
  } else
 
267
  {
 
268
    lprintf("not verified: ! (i < 56)\n");
 
269
    i = 120 - i;
 
270
  }
 
271
 
 
272
  call_hash (field, buf1, i);
 
273
  call_hash (field, buf2, 8);
 
274
  memcpy (result, field, 16);
 
275
}
 
276
 
 
277
static void calc_response_string (char *result, char *challenge) {
 
278
 
 
279
  char field[128] = {
 
280
    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
 
281
    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
 
282
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
283
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 
284
  };
 
285
  char zres[20];
 
286
  int  i;
 
287
 
 
288
  /* calculate response */
 
289
  call_hash(field, challenge, 64);
 
290
  calc_response(zres,field);
 
291
 
 
292
  /* convert zres to ascii string */
 
293
  for (i=0; i<16; i++ ) {
 
294
    char a, b;
 
295
 
 
296
    a = (zres[i] >> 4) & 15;
 
297
    b = zres[i] & 15;
 
298
 
 
299
    result[i*2]   = ((a<10) ? (a+48) : (a+87)) & 255;
 
300
    result[i*2+1] = ((b<10) ? (b+48) : (b+87)) & 255;
 
301
  }
 
302
}
 
303
 
 
304
static void real_calc_response_and_checksum (char *response, char *chksum, char *challenge) {
 
305
 
 
306
  int   ch_len, resp_len;
 
307
  int   i;
 
308
  char *ptr;
 
309
  char  buf[128];
 
310
 
 
311
  /* initialize return values */
 
312
  memset(response, 0, 64);
 
313
  memset(chksum, 0, 34);
 
314
 
 
315
  /* initialize buffer */
 
316
  memset(buf, 0, 128);
 
317
  ptr=buf;
 
318
  BE_32C(ptr, 0xa1e9149d);
 
319
  ptr+=4;
 
320
  BE_32C(ptr, 0x0e6b3b59);
 
321
  ptr+=4;
 
322
 
 
323
  /* some (length) checks */
 
324
  if (challenge != NULL)
 
325
  {
 
326
    ch_len = strlen (challenge);
 
327
 
 
328
    if (ch_len == 40) /* what a hack... */
 
329
    {
 
330
      challenge[32]=0;
 
331
      ch_len=32;
 
332
    }
 
333
    if ( ch_len > 56 ) ch_len=56;
 
334
 
 
335
    /* copy challenge to buf */
 
336
    memcpy(ptr, challenge, ch_len);
 
337
  }
 
338
 
 
339
  /* xor challenge bytewise with xor_table */
 
340
  for (i=0; i<XOR_TABLE_LEN; i++)
 
341
    ptr[i] = ptr[i] ^ xor_table[i];
 
342
 
 
343
  calc_response_string (response, buf);
 
344
 
 
345
  /* add tail */
 
346
  resp_len = strlen (response);
 
347
  strcpy (&response[resp_len], "01d0a8e3");
 
348
 
 
349
  /* calculate checksum */
 
350
  for (i=0; i<resp_len/4; i++)
 
351
    chksum[i] = response[i*4];
 
352
}
 
353
 
 
354
#define MLTI_BUF_MAX_SIZE 2048
 
355
 
 
356
/*
 
357
 * takes a MLTI-Chunk and a rule number got from match_asm_rule,
 
358
 * returns a pointer to selected data and number of bytes in that.
 
359
 */
 
360
static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection, char **out) {
 
361
 
 
362
  int numrules, codec, size;
 
363
  int i;
 
364
 
 
365
  /* MLTI chunk should begin with MLTI */
 
366
  if ((mlti_chunk[0] != 'M')
 
367
      ||(mlti_chunk[1] != 'L')
 
368
      ||(mlti_chunk[2] != 'T')
 
369
      ||(mlti_chunk[3] != 'I'))
 
370
  {
 
371
    lprintf("MLTI tag not detected, copying data\n");
 
372
    memcpy(*out, mlti_chunk, __MIN(mlti_size,MLTI_BUF_MAX_SIZE));
 
373
    return mlti_size;
 
374
  }
 
375
 
 
376
  mlti_chunk+=4;
 
377
 
 
378
  /* next 16 bits are the number of rules */
 
379
  numrules=BE_16(mlti_chunk);
 
380
  if (selection >= numrules) return 0;
 
381
 
 
382
  /* now <numrules> indices of codecs follows */
 
383
  /* we skip to selection                     */
 
384
  mlti_chunk+=(selection+1)*2;
 
385
 
 
386
  /* get our index */
 
387
  codec=BE_16(mlti_chunk);
 
388
 
 
389
  /* skip to number of codecs */
 
390
  mlti_chunk+=(numrules-selection)*2;
 
391
 
 
392
  /* get number of codecs */
 
393
  numrules=BE_16(mlti_chunk);
 
394
 
 
395
  if (codec >= numrules) {
 
396
    lprintf("codec index >= number of codecs. %i %i\n", codec, numrules);
 
397
    return 0;
 
398
  }
 
399
 
 
400
  mlti_chunk+=2;
 
401
 
 
402
  /* now seek to selected codec */
 
403
  for (i=0; i<codec; i++) {
 
404
    size=BE_32(mlti_chunk);
 
405
    mlti_chunk+=size+4;
 
406
  }
 
407
  size=BE_32(mlti_chunk);
 
408
 
 
409
  memcpy(*out, mlti_chunk+4, __MIN(size,MLTI_BUF_MAX_SIZE));
 
410
  return size;
 
411
}
 
412
 
 
413
/*
 
414
 * looking at stream description.
 
415
 */
 
416
 
 
417
static rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) {
 
418
 
 
419
  sdpplin_t *desc = NULL;
 
420
  rmff_header_t *header = NULL;
 
421
  char *buf = NULL;
 
422
  int len, i;
 
423
  int max_bit_rate=0;
 
424
  int avg_bit_rate=0;
 
425
  int max_packet_size=0;
 
426
  int avg_packet_size=0;
 
427
  int duration=0;
 
428
 
 
429
  if( !data ) return NULL;
 
430
 
 
431
  desc=sdpplin_parse(data);
 
432
  if( !desc ) return NULL;
 
433
 
 
434
  buf= (char *)malloc(MLTI_BUF_MAX_SIZE);
 
435
  if( !buf ) goto error;
 
436
 
 
437
  header = calloc( 1, sizeof(rmff_header_t) );
 
438
  if( !header ) goto error;
 
439
 
 
440
  header->fileheader=rmff_new_fileheader(4+desc->stream_count);
 
441
  header->cont=rmff_new_cont(
 
442
      desc->title,
 
443
      desc->author,
 
444
      desc->copyright,
 
445
      desc->abstract);
 
446
 
 
447
  header->data=rmff_new_dataheader(0,0);
 
448
  if( !header->data ) goto error;
 
449
 
 
450
  header->streams = calloc( desc->stream_count+1, sizeof(rmff_mdpr_t*) );
 
451
  if( !header->streams ) goto error;
 
452
 
 
453
  lprintf("number of streams: %u\n", desc->stream_count);
 
454
 
 
455
  for (i=0; i<desc->stream_count; i++) {
 
456
 
 
457
    int j=0;
 
458
    int n;
 
459
    char b[64];
 
460
    int rulematches[16];
 
461
 
 
462
    lprintf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth);
 
463
 
 
464
    n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches, sizeof(rulematches)/sizeof(rulematches[0]));
 
465
    for (j=0; j<n; j++) {
 
466
      lprintf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id);
 
467
      sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]);
 
468
      strcat(*stream_rules, b);
 
469
    }
 
470
 
 
471
    if (!desc->stream[i]->mlti_data) {
 
472
      len = 0;
 
473
      free( buf );
 
474
      buf = NULL;
 
475
    } else
 
476
      len=select_mlti_data(desc->stream[i]->mlti_data,
 
477
        desc->stream[i]->mlti_data_size, rulematches[0], &buf);
 
478
 
 
479
    header->streams[i]=rmff_new_mdpr(
 
480
      desc->stream[i]->stream_id,
 
481
        desc->stream[i]->max_bit_rate,
 
482
        desc->stream[i]->avg_bit_rate,
 
483
        desc->stream[i]->max_packet_size,
 
484
        desc->stream[i]->avg_packet_size,
 
485
        desc->stream[i]->start_time,
 
486
        desc->stream[i]->preroll,
 
487
        desc->stream[i]->duration,
 
488
        desc->stream[i]->stream_name,
 
489
        desc->stream[i]->mime_type,
 
490
        len,
 
491
        buf);
 
492
    if( !header->streams[i] ) goto error;
 
493
 
 
494
    duration=MAX(duration,desc->stream[i]->duration);
 
495
    max_bit_rate+=desc->stream[i]->max_bit_rate;
 
496
    avg_bit_rate+=desc->stream[i]->avg_bit_rate;
 
497
    max_packet_size=MAX(max_packet_size, desc->stream[i]->max_packet_size);
 
498
    if (avg_packet_size)
 
499
      avg_packet_size=(avg_packet_size + desc->stream[i]->avg_packet_size) / 2;
 
500
    else
 
501
      avg_packet_size=desc->stream[i]->avg_packet_size;
 
502
  }
 
503
 
 
504
  if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',')
 
505
      (*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */
 
506
 
 
507
  header->prop=rmff_new_prop(
 
508
      max_bit_rate,
 
509
      avg_bit_rate,
 
510
      max_packet_size,
 
511
      avg_packet_size,
 
512
      0,
 
513
      duration,
 
514
      0,
 
515
      0,
 
516
      0,
 
517
      desc->stream_count,
 
518
      desc->flags);
 
519
  if( !header->prop ) goto error;
 
520
 
 
521
  rmff_fix_header(header);
 
522
 
 
523
  sdpplin_free( desc );
 
524
  free( buf );
 
525
  return header;
 
526
 
 
527
error:
 
528
  sdpplin_free( desc );
 
529
  rmff_free_header( header );
 
530
  free( buf );
 
531
  return NULL;
 
532
}
 
533
 
 
534
int real_get_rdt_chunk_header(rtsp_client_t *rtsp_session, rmff_pheader_t *ph) {
 
535
 
 
536
  int n=1;
 
537
  uint8_t header[8];
 
538
  int size;
 
539
  int flags1;
 
540
  int unknown1;
 
541
  uint32_t ts;
 
542
 
 
543
  n=rtsp_read_data(rtsp_session, header, 8);
 
544
  if (n<8) return 0;
 
545
  if (header[0] != 0x24)
 
546
  {
 
547
    lprintf("rdt chunk not recognized: got 0x%02x\n", header[0]);
 
548
    return 0;
 
549
  }
 
550
  size=(header[1]<<16)+(header[2]<<8)+(header[3]);
 
551
  flags1=header[4];
 
552
  if ((flags1!=0x40)&&(flags1!=0x42))
 
553
  {
 
554
    lprintf("got flags1: 0x%02x\n",flags1);
 
555
    if (header[6]==0x06)
 
556
    {
 
557
      lprintf("got end of stream packet\n");
 
558
      return 0;
 
559
    }
 
560
    header[0]=header[5];
 
561
    header[1]=header[6];
 
562
    header[2]=header[7];
 
563
    n=rtsp_read_data(rtsp_session, header+3, 5);
 
564
    if (n<5) return 0;
 
565
    lprintf("ignoring bytes:\n");
 
566
    n=rtsp_read_data(rtsp_session, header+4, 4);
 
567
    if (n<4) return 0;
 
568
    flags1=header[4];
 
569
    size-=9;
 
570
  }
 
571
  unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]);
 
572
  n=rtsp_read_data(rtsp_session, header, 6);
 
573
  if (n<6) return 0;
 
574
  ts=BE_32(header);
 
575
 
 
576
#if 0
 
577
  lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n",
 
578
          ts, size, flags1, unknown1, header[4], header[5]);
 
579
#endif
 
580
 
 
581
  size+=2;
 
582
  ph->object_version=0;
 
583
  ph->length=size;
 
584
  ph->stream_number=(flags1>>1)&1;
 
585
  ph->timestamp=ts;
 
586
  ph->reserved=0;
 
587
  ph->flags=0;      /* TODO: determine keyframe flag and insert here? */
 
588
  return size;
 
589
}
 
590
 
 
591
int real_get_rdt_chunk(rtsp_client_t *rtsp_session, rmff_pheader_t *ph,
 
592
                       unsigned char **buffer) {
 
593
 
 
594
  int n;
 
595
  rmff_dump_pheader(ph, (char*)*buffer);
 
596
  if (ph->length<12) return 0;
 
597
  n=rtsp_read_data(rtsp_session, (uint8_t*)(*buffer + 12), ph->length - 12);
 
598
  return (n <= 0) ? 0 : n+12;
 
599
}
 
600
 
 
601
//! maximum size of the rtsp description, must be < INT_MAX
 
602
#define MAX_DESC_BUF (20 * 1024 * 1024)
 
603
rmff_header_t  *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandwidth) {
 
604
 
 
605
  char *description=NULL;
 
606
  char *session_id=NULL;
 
607
  rmff_header_t *h=NULL;
 
608
  char *challenge1 = NULL;
 
609
  char challenge2[64];
 
610
  char checksum[34];
 
611
  char *subscribe=NULL;
 
612
  char *buf = malloc(256);
 
613
  if( !buf )
 
614
    return NULL;
 
615
  char *mrl=rtsp_get_mrl(rtsp_session);
 
616
  unsigned int size;
 
617
  int status;
 
618
 
 
619
  /* get challenge */
 
620
  challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1"));
 
621
  lprintf("Challenge1: %s\n", challenge1);
 
622
 
 
623
  /* request stream description */
 
624
  rtsp_schedule_field(rtsp_session, "Accept: application/sdp");
 
625
  sprintf(buf, "Bandwidth: %u", bandwidth);
 
626
  rtsp_schedule_field(rtsp_session, buf);
 
627
  rtsp_schedule_field(rtsp_session, "GUID: 00000000-0000-0000-0000-000000000000");
 
628
  rtsp_schedule_field(rtsp_session, "RegionData: 0");
 
629
  rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
 
630
  rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1");
 
631
  rtsp_schedule_field(rtsp_session, "Language: en-US");
 
632
  rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup");
 
633
 
 
634
  status=rtsp_request_describe(rtsp_session,NULL);
 
635
  if ( status<200 || status>299 ) {
 
636
    char *alert=rtsp_search_answers(rtsp_session,"Alert");
 
637
    if (alert) {
 
638
        lprintf("real: got message from server:\n%s\n", alert);
 
639
    }
 
640
    rtsp_send_ok( rtsp_session );
 
641
    free( challenge1 );
 
642
    free( alert );
 
643
    free( buf );
 
644
    return NULL;
 
645
  }
 
646
 
 
647
  /* receive description */
 
648
  size=0;
 
649
  if (!rtsp_search_answers(rtsp_session,"Content-length"))
 
650
    lprintf("real: got no Content-length!\n");
 
651
  else
 
652
    size=atoi(rtsp_search_answers(rtsp_session,"Content-length"));
 
653
 
 
654
  if (size > MAX_DESC_BUF) {
 
655
    printf("real: Content-length for description too big (> %uMB)!\n",
 
656
        MAX_DESC_BUF/(1024*1024) );
 
657
    goto error;
 
658
  }
 
659
 
 
660
  if (!rtsp_search_answers(rtsp_session,"ETag"))
 
661
    lprintf("real: got no ETag!\n");
 
662
  else
 
663
    session_id=strdup(rtsp_search_answers(rtsp_session,"ETag"));
 
664
 
 
665
  lprintf("Stream description size: %i\n", size);
 
666
 
 
667
  description = malloc(size+1);
 
668
  if( !description )
 
669
    goto error;
 
670
  if( rtsp_read_data(rtsp_session, (uint8_t*)description, size) <= 0)
 
671
    goto error;
 
672
  description[size]=0;
 
673
  //fprintf(stderr, "%s", description);
 
674
 
 
675
  /* parse sdp (sdpplin) and create a header and a subscribe string */
 
676
  subscribe = malloc(256);
 
677
  if( !subscribe )
 
678
    goto error;
 
679
 
 
680
  strcpy(subscribe, "Subscribe: ");
 
681
  h=real_parse_sdp(description, &subscribe, bandwidth);
 
682
  if (!h)
 
683
    goto error;
 
684
 
 
685
  rmff_fix_header(h);
 
686
 
 
687
#if 0
 
688
  fprintf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n",
 
689
      h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams);
 
690
#endif
 
691
 
 
692
  /* setup our streams */
 
693
  real_calc_response_and_checksum (challenge2, checksum, challenge1);
 
694
  buf = realloc_or_free(buf, strlen(challenge2) + strlen(checksum) + 32);
 
695
  if( !buf ) goto error;
 
696
  sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum);
 
697
  rtsp_schedule_field(rtsp_session, buf);
 
698
  buf = realloc_or_free(buf, strlen(session_id) + 32);
 
699
  if( !buf ) goto error;
 
700
  sprintf(buf, "If-Match: %s", session_id);
 
701
  rtsp_schedule_field(rtsp_session, buf);
 
702
  rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
 
703
  buf = realloc_or_free(buf, strlen(mrl) + 32);
 
704
  if( !buf ) goto error;
 
705
  sprintf(buf, "%s/streamid=0", mrl);
 
706
  rtsp_request_setup(rtsp_session,buf);
 
707
 
 
708
  if (h->prop->num_streams > 1) {
 
709
    rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
 
710
    buf = realloc_or_free(buf, strlen(session_id) + 32);
 
711
    if( !buf ) goto error;
 
712
    sprintf(buf, "If-Match: %s", session_id);
 
713
    rtsp_schedule_field(rtsp_session, buf);
 
714
    buf = realloc_or_free(buf, strlen(mrl) + 32);
 
715
    if( !buf ) goto error;
 
716
    sprintf(buf, "%s/streamid=1", mrl);
 
717
    rtsp_request_setup(rtsp_session,buf);
 
718
  }
 
719
  /* set stream parameter (bandwidth) with our subscribe string */
 
720
  rtsp_schedule_field(rtsp_session, subscribe);
 
721
  rtsp_request_setparameter(rtsp_session,NULL);
 
722
 
 
723
  /* and finally send a play request */
 
724
  rtsp_schedule_field(rtsp_session, "Range: npt=0-");
 
725
  rtsp_request_play(rtsp_session,NULL);
 
726
 
 
727
  free( challenge1 );
 
728
  free( session_id );
 
729
  free( description );
 
730
  free( subscribe );
 
731
  free( buf );
 
732
  return h;
 
733
 
 
734
error:
 
735
  rmff_free_header( h );
 
736
  free( challenge1 );
 
737
  free( session_id );
 
738
  free( description );
 
739
  free( subscribe );
 
740
  free( buf );
 
741
  return NULL;
 
742
}