Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

real.c

00001 /*****************************************************************************
00002  * real.c: real rtsp input
00003  *****************************************************************************
00004  * Copyright (C) 2002-2004 the xine project
00005  * Copyright (C) 2005 VideoLAN
00006  * $Id: file.c 10310 2005-03-11 22:36:40Z anil $
00007  *
00008  * Authors: Gildas Bazin <[email protected]>
00009  *          Adapted from xine which itself adapted it from joschkas real tools.
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00024  *****************************************************************************/
00025 #include <stdio.h>
00026 #include <string.h>
00027 
00028 #include <vlc/vlc.h>
00029 
00030 #include "rtsp.h"
00031 #include "real.h"
00032 #include "real_sdpplin.h"
00033 
00034 const unsigned char xor_table[] = {
00035     0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53,
00036     0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70,
00037     0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09,
00038     0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02,
00039     0x10, 0x57, 0x05, 0x18, 0x54, 0x00, 0x00, 0x00 };
00040 
00041 #define BE_32(x) GetDWBE(x)
00042 #define LE_32(x) GetDWLE(x)
00043 #define BE_16(x) GetWBE(x)
00044 #define LE_16(x) GetWLE(x)
00045 #define BE_32C(x,y) do {uint32_t in=y; *(uint32_t *)(x)=GetDWBE(&in);} while(0)
00046 #define LE_32C(x,y) do {uint32_t in=y; *(uint32_t *)(x)=GetDWLE(&in);} while(0)
00047 #define MAX(x,y) ((x>y) ? x : y)
00048 
00049 
00050 static void hash(char *field, char *param)
00051 {
00052   uint32_t a, b, c, d;
00053 
00054   /* fill variables */
00055   a = LE_32(field);
00056   b = LE_32(field+4);
00057   c = LE_32(field+8);
00058   d = LE_32(field+12);
00059 
00060   lprintf("hash input: %x %x %x %x\n", a, b, c, d);
00061   lprintf("hash parameter:\n");
00062 
00063   a = ((b & c) | (~b & d)) + LE_32((param+0x00)) + a - 0x28955B88;
00064   a = ((a << 0x07) | (a >> 0x19)) + b;
00065   d = ((a & b) | (~a & c)) + LE_32((param+0x04)) + d - 0x173848AA;
00066   d = ((d << 0x0c) | (d >> 0x14)) + a;
00067   c = ((d & a) | (~d & b)) + LE_32((param+0x08)) + c + 0x242070DB;
00068   c = ((c << 0x11) | (c >> 0x0f)) + d;
00069   b = ((c & d) | (~c & a)) + LE_32((param+0x0c)) + b - 0x3E423112;
00070   b = ((b << 0x16) | (b >> 0x0a)) + c;
00071   a = ((b & c) | (~b & d)) + LE_32((param+0x10)) + a - 0x0A83F051;
00072   a = ((a << 0x07) | (a >> 0x19)) + b;
00073   d = ((a & b) | (~a & c)) + LE_32((param+0x14)) + d + 0x4787C62A;
00074   d = ((d << 0x0c) | (d >> 0x14)) + a;
00075   c = ((d & a) | (~d & b)) + LE_32((param+0x18)) + c - 0x57CFB9ED;
00076   c = ((c << 0x11) | (c >> 0x0f)) + d;
00077   b = ((c & d) | (~c & a)) + LE_32((param+0x1c)) + b - 0x02B96AFF;
00078   b = ((b << 0x16) | (b >> 0x0a)) + c;
00079   a = ((b & c) | (~b & d)) + LE_32((param+0x20)) + a + 0x698098D8;
00080   a = ((a << 0x07) | (a >> 0x19)) + b;
00081   d = ((a & b) | (~a & c)) + LE_32((param+0x24)) + d - 0x74BB0851;
00082   d = ((d << 0x0c) | (d >> 0x14)) + a;
00083   c = ((d & a) | (~d & b)) + LE_32((param+0x28)) + c - 0x0000A44F;
00084   c = ((c << 0x11) | (c >> 0x0f)) + d;
00085   b = ((c & d) | (~c & a)) + LE_32((param+0x2C)) + b - 0x76A32842;
00086   b = ((b << 0x16) | (b >> 0x0a)) + c;
00087   a = ((b & c) | (~b & d)) + LE_32((param+0x30)) + a + 0x6B901122;
00088   a = ((a << 0x07) | (a >> 0x19)) + b;
00089   d = ((a & b) | (~a & c)) + LE_32((param+0x34)) + d - 0x02678E6D;
00090   d = ((d << 0x0c) | (d >> 0x14)) + a;
00091   c = ((d & a) | (~d & b)) + LE_32((param+0x38)) + c - 0x5986BC72;
00092   c = ((c << 0x11) | (c >> 0x0f)) + d;
00093   b = ((c & d) | (~c & a)) + LE_32((param+0x3c)) + b + 0x49B40821;
00094   b = ((b << 0x16) | (b >> 0x0a)) + c;
00095 
00096   a = ((b & d) | (~d & c)) + LE_32((param+0x04)) + a - 0x09E1DA9E;
00097   a = ((a << 0x05) | (a >> 0x1b)) + b;
00098   d = ((a & c) | (~c & b)) + LE_32((param+0x18)) + d - 0x3FBF4CC0;
00099   d = ((d << 0x09) | (d >> 0x17)) + a;
00100   c = ((d & b) | (~b & a)) + LE_32((param+0x2c)) + c + 0x265E5A51;
00101   c = ((c << 0x0e) | (c >> 0x12)) + d;
00102   b = ((c & a) | (~a & d)) + LE_32((param+0x00)) + b - 0x16493856;
00103   b = ((b << 0x14) | (b >> 0x0c)) + c;
00104   a = ((b & d) | (~d & c)) + LE_32((param+0x14)) + a - 0x29D0EFA3;
00105   a = ((a << 0x05) | (a >> 0x1b)) + b;
00106   d = ((a & c) | (~c & b)) + LE_32((param+0x28)) + d + 0x02441453;
00107   d = ((d << 0x09) | (d >> 0x17)) + a;
00108   c = ((d & b) | (~b & a)) + LE_32((param+0x3c)) + c - 0x275E197F;
00109   c = ((c << 0x0e) | (c >> 0x12)) + d;
00110   b = ((c & a) | (~a & d)) + LE_32((param+0x10)) + b - 0x182C0438;
00111   b = ((b << 0x14) | (b >> 0x0c)) + c;
00112   a = ((b & d) | (~d & c)) + LE_32((param+0x24)) + a + 0x21E1CDE6;
00113   a = ((a << 0x05) | (a >> 0x1b)) + b;
00114   d = ((a & c) | (~c & b)) + LE_32((param+0x38)) + d - 0x3CC8F82A;
00115   d = ((d << 0x09) | (d >> 0x17)) + a;
00116   c = ((d & b) | (~b & a)) + LE_32((param+0x0c)) + c - 0x0B2AF279;
00117   c = ((c << 0x0e) | (c >> 0x12)) + d;
00118   b = ((c & a) | (~a & d)) + LE_32((param+0x20)) + b + 0x455A14ED;
00119   b = ((b << 0x14) | (b >> 0x0c)) + c;
00120   a = ((b & d) | (~d & c)) + LE_32((param+0x34)) + a - 0x561C16FB;
00121   a = ((a << 0x05) | (a >> 0x1b)) + b;
00122   d = ((a & c) | (~c & b)) + LE_32((param+0x08)) + d - 0x03105C08;
00123   d = ((d << 0x09) | (d >> 0x17)) + a;
00124   c = ((d & b) | (~b & a)) + LE_32((param+0x1c)) + c + 0x676F02D9;
00125   c = ((c << 0x0e) | (c >> 0x12)) + d;
00126   b = ((c & a) | (~a & d)) + LE_32((param+0x30)) + b - 0x72D5B376;
00127   b = ((b << 0x14) | (b >> 0x0c)) + c;
00128 
00129   a = (b ^ c ^ d) + LE_32((param+0x14)) + a - 0x0005C6BE;
00130   a = ((a << 0x04) | (a >> 0x1c)) + b;
00131   d = (a ^ b ^ c) + LE_32((param+0x20)) + d - 0x788E097F;
00132   d = ((d << 0x0b) | (d >> 0x15)) + a;
00133   c = (d ^ a ^ b) + LE_32((param+0x2c)) + c + 0x6D9D6122;
00134   c = ((c << 0x10) | (c >> 0x10)) + d;
00135   b = (c ^ d ^ a) + LE_32((param+0x38)) + b - 0x021AC7F4;
00136   b = ((b << 0x17) | (b >> 0x09)) + c;
00137   a = (b ^ c ^ d) + LE_32((param+0x04)) + a - 0x5B4115BC;
00138   a = ((a << 0x04) | (a >> 0x1c)) + b;
00139   d = (a ^ b ^ c) + LE_32((param+0x10)) + d + 0x4BDECFA9;
00140   d = ((d << 0x0b) | (d >> 0x15)) + a;
00141   c = (d ^ a ^ b) + LE_32((param+0x1c)) + c - 0x0944B4A0;
00142   c = ((c << 0x10) | (c >> 0x10)) + d;
00143   b = (c ^ d ^ a) + LE_32((param+0x28)) + b - 0x41404390;
00144   b = ((b << 0x17) | (b >> 0x09)) + c;
00145   a = (b ^ c ^ d) + LE_32((param+0x34)) + a + 0x289B7EC6;
00146   a = ((a << 0x04) | (a >> 0x1c)) + b;
00147   d = (a ^ b ^ c) + LE_32((param+0x00)) + d - 0x155ED806;
00148   d = ((d << 0x0b) | (d >> 0x15)) + a;
00149   c = (d ^ a ^ b) + LE_32((param+0x0c)) + c - 0x2B10CF7B;
00150   c = ((c << 0x10) | (c >> 0x10)) + d;
00151   b = (c ^ d ^ a) + LE_32((param+0x18)) + b + 0x04881D05;
00152   b = ((b << 0x17) | (b >> 0x09)) + c;
00153   a = (b ^ c ^ d) + LE_32((param+0x24)) + a - 0x262B2FC7;
00154   a = ((a << 0x04) | (a >> 0x1c)) + b;
00155   d = (a ^ b ^ c) + LE_32((param+0x30)) + d - 0x1924661B;
00156   d = ((d << 0x0b) | (d >> 0x15)) + a;
00157   c = (d ^ a ^ b) + LE_32((param+0x3c)) + c + 0x1fa27cf8;
00158   c = ((c << 0x10) | (c >> 0x10)) + d;
00159   b = (c ^ d ^ a) + LE_32((param+0x08)) + b - 0x3B53A99B;
00160   b = ((b << 0x17) | (b >> 0x09)) + c;
00161 
00162   a = ((~d | b) ^ c)  + LE_32((param+0x00)) + a - 0x0BD6DDBC;
00163   a = ((a << 0x06) | (a >> 0x1a)) + b; 
00164   d = ((~c | a) ^ b)  + LE_32((param+0x1c)) + d + 0x432AFF97;
00165   d = ((d << 0x0a) | (d >> 0x16)) + a; 
00166   c = ((~b | d) ^ a)  + LE_32((param+0x38)) + c - 0x546BDC59;
00167   c = ((c << 0x0f) | (c >> 0x11)) + d; 
00168   b = ((~a | c) ^ d)  + LE_32((param+0x14)) + b - 0x036C5FC7;
00169   b = ((b << 0x15) | (b >> 0x0b)) + c; 
00170   a = ((~d | b) ^ c)  + LE_32((param+0x30)) + a + 0x655B59C3;
00171   a = ((a << 0x06) | (a >> 0x1a)) + b; 
00172   d = ((~c | a) ^ b)  + LE_32((param+0x0C)) + d - 0x70F3336E;
00173   d = ((d << 0x0a) | (d >> 0x16)) + a; 
00174   c = ((~b | d) ^ a)  + LE_32((param+0x28)) + c - 0x00100B83;
00175   c = ((c << 0x0f) | (c >> 0x11)) + d; 
00176   b = ((~a | c) ^ d)  + LE_32((param+0x04)) + b - 0x7A7BA22F;
00177   b = ((b << 0x15) | (b >> 0x0b)) + c; 
00178   a = ((~d | b) ^ c)  + LE_32((param+0x20)) + a + 0x6FA87E4F;
00179   a = ((a << 0x06) | (a >> 0x1a)) + b; 
00180   d = ((~c | a) ^ b)  + LE_32((param+0x3c)) + d - 0x01D31920;
00181   d = ((d << 0x0a) | (d >> 0x16)) + a; 
00182   c = ((~b | d) ^ a)  + LE_32((param+0x18)) + c - 0x5CFEBCEC;
00183   c = ((c << 0x0f) | (c >> 0x11)) + d; 
00184   b = ((~a | c) ^ d)  + LE_32((param+0x34)) + b + 0x4E0811A1;
00185   b = ((b << 0x15) | (b >> 0x0b)) + c; 
00186   a = ((~d | b) ^ c)  + LE_32((param+0x10)) + a - 0x08AC817E;
00187   a = ((a << 0x06) | (a >> 0x1a)) + b; 
00188   d = ((~c | a) ^ b)  + LE_32((param+0x2c)) + d - 0x42C50DCB;
00189   d = ((d << 0x0a) | (d >> 0x16)) + a; 
00190   c = ((~b | d) ^ a)  + LE_32((param+0x08)) + c + 0x2AD7D2BB;
00191   c = ((c << 0x0f) | (c >> 0x11)) + d; 
00192   b = ((~a | c) ^ d)  + LE_32((param+0x24)) + b - 0x14792C6F;
00193   b = ((b << 0x15) | (b >> 0x0b)) + c; 
00194 
00195   lprintf("hash output: %x %x %x %x\n", a, b, c, d);
00196 
00197   a += LE_32(field);
00198   b += LE_32(field+4);
00199   c += LE_32(field+8);
00200   d += LE_32(field+12);
00201 
00202   LE_32C(field, a);
00203   LE_32C(field+4, b);
00204   LE_32C(field+8, c);
00205   LE_32C(field+12, d);
00206 }
00207 
00208 static void call_hash (char *key, char *challenge, int len) {
00209 
00210   uint8_t *ptr1, *ptr2;
00211   uint32_t a, b, c, d, tmp;
00212 
00213   ptr1=(key+16);
00214   ptr2=(key+20);
00215 
00216   a = LE_32(ptr1);
00217   b = (a >> 3) & 0x3f;
00218   a += len * 8;
00219   LE_32C(ptr1, a);
00220 
00221   if (a < (uint32_t)(len << 3))
00222   {
00223     lprintf("not verified: (len << 3) > a true\n");
00224     ptr2 += 4;
00225   }
00226 
00227   tmp = LE_32(ptr2) + (len >> 0x1d);
00228   LE_32C(ptr2, tmp);
00229   a = 64 - b;
00230   c = 0;
00231   if (a <= (uint32_t)len)
00232   {
00233     memcpy(key+b+24, challenge, a);
00234     hash(key, key+24);
00235     c = a;
00236     d = c + 0x3f;
00237 
00238     while ( d < (uint32_t)len ) {
00239       lprintf("not verified:  while ( d < len )\n");
00240       hash(key, challenge+d-0x3f);
00241       d += 64;
00242       c += 64;
00243     }
00244     b = 0;
00245   }
00246 
00247   memcpy(key+b+24, challenge+c, len-c);
00248 }
00249 
00250 static void calc_response (char *result, char *field) {
00251   char buf1[128];
00252   char buf2[128];
00253   int i;
00254 
00255   memset (buf1, 0, 64);
00256   *buf1 = 128;
00257 
00258   memcpy (buf2, field+16, 8);
00259   i = ( LE_32((buf2)) >> 3 ) & 0x3f;
00260 
00261   if (i < 56)
00262   {
00263     i = 56 - i;
00264   } else
00265   {
00266     lprintf("not verified: ! (i < 56)\n");
00267     i = 120 - i;
00268   }
00269 
00270   call_hash (field, buf1, i);
00271   call_hash (field, buf2, 8);
00272   memcpy (result, field, 16);
00273 }
00274 
00275 static void calc_response_string (char *result, char *challenge) {
00276   char field[128];
00277   char zres[20];
00278   int  i;
00279 
00280   /* initialize our field */
00281   BE_32C (field,      0x01234567);
00282   BE_32C ((field+4),  0x89ABCDEF);
00283   BE_32C ((field+8),  0xFEDCBA98);
00284   BE_32C ((field+12), 0x76543210);
00285   BE_32C ((field+16), 0x00000000);
00286   BE_32C ((field+20), 0x00000000);
00287 
00288   /* calculate response */
00289   call_hash(field, challenge, 64);
00290   calc_response(zres,field);
00291 
00292   /* convert zres to ascii string */
00293   for (i=0; i<16; i++ ) {
00294     char a, b;
00295 
00296     a = (zres[i] >> 4) & 15;
00297     b = zres[i] & 15;
00298 
00299     result[i*2]   = ((a<10) ? (a+48) : (a+87)) & 255;
00300     result[i*2+1] = ((b<10) ? (b+48) : (b+87)) & 255;
00301   }
00302 }
00303 
00304 void real_calc_response_and_checksum (char *response, char *chksum, char *challenge) {
00305 
00306   int   ch_len, table_len, resp_len;
00307   int   i;
00308   char *ptr;
00309   char  buf[128];
00310 
00311   /* initialize return values */
00312   memset(response, 0, 64);
00313   memset(chksum, 0, 34);
00314 
00315   /* initialize buffer */
00316   memset(buf, 0, 128);
00317   ptr=buf;
00318   BE_32C(ptr, 0xa1e9149d);
00319   ptr+=4;
00320   BE_32C(ptr, 0x0e6b3b59);
00321   ptr+=4;
00322 
00323   /* some (length) checks */
00324   if (challenge != NULL)
00325   {
00326     ch_len = strlen (challenge);
00327 
00328     if (ch_len == 40) /* what a hack... */
00329     {
00330       challenge[32]=0;
00331       ch_len=32;
00332     }
00333     if ( ch_len > 56 ) ch_len=56;
00334 
00335     /* copy challenge to buf */
00336     memcpy(ptr, challenge, ch_len);
00337   }
00338 
00339   if (xor_table != NULL)
00340   {
00341     table_len = strlen(xor_table);
00342 
00343     if (table_len > 56) table_len=56;
00344 
00345     /* xor challenge bytewise with xor_table */
00346     for (i=0; i<table_len; i++)
00347       ptr[i] = ptr[i] ^ xor_table[i];
00348   }
00349 
00350   calc_response_string (response, buf);
00351 
00352   /* add tail */
00353   resp_len = strlen (response);
00354   strcpy (&response[resp_len], "01d0a8e3");
00355 
00356   /* calculate checksum */
00357   for (i=0; i<resp_len/4; i++)
00358     chksum[i] = response[i*4];
00359 }
00360 
00361 
00362 /*
00363  * takes a MLTI-Chunk and a rule number got from match_asm_rule,
00364  * returns a pointer to selected data and number of bytes in that.
00365  */
00366 static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection, char **out) {
00367 
00368   int numrules, codec, size;
00369   int i;
00370 
00371   /* MLTI chunk should begin with MLTI */
00372   if ((mlti_chunk[0] != 'M')
00373       ||(mlti_chunk[1] != 'L')
00374       ||(mlti_chunk[2] != 'T')
00375       ||(mlti_chunk[3] != 'I'))
00376   {
00377     lprintf("MLTI tag not detected, copying data\n");
00378     memcpy(*out, mlti_chunk, mlti_size);
00379     return mlti_size;
00380   }
00381 
00382   mlti_chunk+=4;
00383 
00384   /* next 16 bits are the number of rules */
00385   numrules=BE_16(mlti_chunk);
00386   if (selection >= numrules) return 0;
00387 
00388   /* now <numrules> indices of codecs follows */
00389   /* we skip to selection                     */
00390   mlti_chunk+=(selection+1)*2;
00391 
00392   /* get our index */
00393   codec=BE_16(mlti_chunk);
00394 
00395   /* skip to number of codecs */
00396   mlti_chunk+=(numrules-selection)*2;
00397 
00398   /* get number of codecs */
00399   numrules=BE_16(mlti_chunk);
00400 
00401   if (codec >= numrules) {
00402     lprintf("codec index >= number of codecs. %i %i\n", codec, numrules);
00403     return 0;
00404   }
00405 
00406   mlti_chunk+=2;
00407 
00408   /* now seek to selected codec */
00409   for (i=0; i<codec; i++) {
00410     size=BE_32(mlti_chunk);
00411     mlti_chunk+=size+4;
00412   }
00413   size=BE_32(mlti_chunk);
00414 
00415   memcpy(*out, mlti_chunk+4, size);
00416   return size;
00417 }
00418 
00419 /*
00420  * looking at stream description.
00421  */
00422 
00423 rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) {
00424 
00425   sdpplin_t *desc = NULL;
00426   rmff_header_t *header = NULL;
00427   char *buf = NULL;
00428   int len, i;
00429   int max_bit_rate=0;
00430   int avg_bit_rate=0;
00431   int max_packet_size=0;
00432   int avg_packet_size=0;
00433   int duration=0;
00434 
00435   if( !data ) return NULL;
00436 
00437   desc=sdpplin_parse(data);
00438   if( !desc ) return NULL;
00439 
00440   buf= (char *)malloc(sizeof(char)*2048);
00441   if( !buf ) goto error;
00442 
00443   header = (rmff_header_t*)malloc(sizeof(rmff_header_t));
00444   if( !header ) goto error;
00445 
00446   memset(header, 0, sizeof(rmff_header_t));
00447   header->fileheader=rmff_new_fileheader(4+desc->stream_count);
00448   header->cont=rmff_new_cont(
00449       desc->title,
00450       desc->author,
00451       desc->copyright,
00452       desc->abstract);
00453 
00454   header->data=rmff_new_dataheader(0,0);
00455   if( !header->data ) goto error;
00456 
00457   header->streams = (rmff_mdpr_t**) malloc(sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
00458   if( !header->streams ) goto error;
00459 
00460   memset(header->streams, 0, sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
00461   lprintf("number of streams: %u\n", desc->stream_count);
00462 
00463   for (i=0; i<desc->stream_count; i++) {
00464 
00465     int j=0;
00466     int n;
00467     char b[64];
00468     int rulematches[16];
00469 
00470     lprintf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth);
00471 
00472     n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches);
00473     for (j=0; j<n; j++) {
00474       lprintf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id);
00475       sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]);
00476       strcat(*stream_rules, b);
00477     }
00478 
00479     if (!desc->stream[i]->mlti_data) {
00480       len = 0;
00481       if( buf ) free( buf );
00482       buf = NULL;
00483     } else
00484       len=select_mlti_data(desc->stream[i]->mlti_data,
00485         desc->stream[i]->mlti_data_size, rulematches[0], &buf);
00486 
00487     header->streams[i]=rmff_new_mdpr(
00488       desc->stream[i]->stream_id,
00489         desc->stream[i]->max_bit_rate,
00490         desc->stream[i]->avg_bit_rate,
00491         desc->stream[i]->max_packet_size,
00492         desc->stream[i]->avg_packet_size,
00493         desc->stream[i]->start_time,
00494         desc->stream[i]->preroll,
00495         desc->stream[i]->duration,
00496         desc->stream[i]->stream_name,
00497         desc->stream[i]->mime_type,
00498         len,
00499         buf);
00500     if( !header->streams[i] ) goto error;
00501 
00502     duration=MAX(duration,desc->stream[i]->duration);
00503     max_bit_rate+=desc->stream[i]->max_bit_rate;
00504     avg_bit_rate+=desc->stream[i]->avg_bit_rate;
00505     max_packet_size=MAX(max_packet_size, desc->stream[i]->max_packet_size);
00506     if (avg_packet_size)
00507       avg_packet_size=(avg_packet_size + desc->stream[i]->avg_packet_size) / 2;
00508     else
00509       avg_packet_size=desc->stream[i]->avg_packet_size;
00510   }
00511 
00512   if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',')
00513       (*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */
00514 
00515   header->prop=rmff_new_prop(
00516       max_bit_rate,
00517       avg_bit_rate,
00518       max_packet_size,
00519       avg_packet_size,
00520       0,
00521       duration,
00522       0,
00523       0,
00524       0,
00525       desc->stream_count,
00526       desc->flags);
00527   if( !header->prop ) goto error;
00528 
00529   rmff_fix_header(header);
00530 
00531   if( desc ) sdpplin_free( desc );
00532   if( buf ) free(buf);
00533   return header;
00534 
00535 error:
00536   if( desc ) sdpplin_free( desc );
00537   if( header ) rmff_free_header( header );
00538   if( buf ) free( buf );
00539   return NULL;
00540 }
00541 
00542 int real_get_rdt_chunk_header(rtsp_client_t *rtsp_session, rmff_pheader_t *ph) {
00543 
00544   int n=1;
00545   uint8_t header[8];
00546   int size;
00547   int flags1;
00548   int unknown1;
00549   uint32_t ts;
00550 
00551   n=rtsp_read_data(rtsp_session, header, 8);
00552   if (n<8) return 0;
00553   if (header[0] != 0x24) {
00554     lprintf("rdt chunk not recognized: got 0x%02x\n", header[0]);
00555     return 0;
00556   }
00557   size=(header[1]<<16)+(header[2]<<8)+(header[3]);
00558   flags1=header[4];
00559   if ((flags1!=0x40)&&(flags1!=0x42)) {
00560     lprintf("got flags1: 0x%02x\n",flags1);
00561     if (header[6]==0x06) {
00562       lprintf("got end of stream packet\n");
00563       return 0;
00564     }
00565     header[0]=header[5];
00566     header[1]=header[6];
00567     header[2]=header[7];
00568     n=rtsp_read_data(rtsp_session, header+3, 5);
00569     if (n<5) return 0;
00570     lprintf("ignoring bytes:\n");
00571     n=rtsp_read_data(rtsp_session, header+4, 4);
00572     if (n<4) return 0;
00573     flags1=header[4];
00574     size-=9;
00575   }
00576   unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]);
00577   n=rtsp_read_data(rtsp_session, header, 6);
00578   if (n<6) return 0;
00579   ts=BE_32(header);
00580 
00581 #if 0
00582   lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n",
00583           ts, size, flags1, unknown1, header[4], header[5]);
00584 #endif
00585 
00586   size+=2;
00587   ph->object_version=0;
00588   ph->length=size;
00589   ph->stream_number=(flags1>>1)&1;
00590   ph->timestamp=ts;
00591   ph->reserved=0;
00592   ph->flags=0;      /* TODO: determine keyframe flag and insert here? */
00593   return size;
00594 }
00595 
00596 int real_get_rdt_chunk(rtsp_client_t *rtsp_session, rmff_pheader_t *ph,
00597                        unsigned char **buffer) {
00598 
00599   int n;
00600   rmff_dump_pheader(ph, *buffer);
00601   n=rtsp_read_data(rtsp_session, *buffer + 12, ph->length - 12);
00602   return (n <= 0) ? 0 : n+12;
00603 }
00604 
00606 #define MAX_DESC_BUF (20 * 1024 * 1024)
00607 rmff_header_t  *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandwidth) {
00608 
00609   char *description=NULL;
00610   char *session_id=NULL;
00611   rmff_header_t *h;
00612   char *challenge1 = NULL;
00613   char challenge2[64];
00614   char checksum[34];
00615   char *subscribe=NULL;
00616   char *buf=(char*)malloc(sizeof(char)*256);
00617   char *mrl=rtsp_get_mrl(rtsp_session);
00618   unsigned int size;
00619   int status;
00620 
00621   /* get challenge */
00622   challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1"));
00623   lprintf("Challenge1: %s\n", challenge1);
00624 
00625   /* request stream description */
00626   rtsp_schedule_field(rtsp_session, "Accept: application/sdp");
00627   sprintf(buf, "Bandwidth: %u", bandwidth);
00628   rtsp_schedule_field(rtsp_session, buf);
00629   rtsp_schedule_field(rtsp_session, "GUID: 00000000-0000-0000-0000-000000000000");
00630   rtsp_schedule_field(rtsp_session, "RegionData: 0");
00631   rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
00632   rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1");
00633   rtsp_schedule_field(rtsp_session, "Language: en-US");
00634   rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup");
00635 
00636   status=rtsp_request_describe(rtsp_session,NULL);
00637   if ( status<200 || status>299 ) {
00638     char *alert=rtsp_search_answers(rtsp_session,"Alert");
00639     if (alert) {
00640         lprintf("real: got message from server:\n%s\n", alert);
00641     }
00642     printf( "bou\n");
00643     rtsp_send_ok(rtsp_session);
00644     if( challenge1 ) free(challenge1);
00645     if( alert ) free(alert);
00646     if( buf ) free(buf);
00647     return NULL;
00648   }
00649 
00650   /* receive description */
00651   size=0;
00652   if (!rtsp_search_answers(rtsp_session,"Content-length"))
00653     lprintf("real: got no Content-length!\n");
00654   else
00655     size=atoi(rtsp_search_answers(rtsp_session,"Content-length"));
00656 
00657   if (size > MAX_DESC_BUF) {
00658     printf("real: Content-length for description too big (> %uMB)!\n",
00659         MAX_DESC_BUF/(1024*1024) );
00660     goto error;
00661   }
00662 
00663   if (!rtsp_search_answers(rtsp_session,"ETag"))
00664     lprintf("real: got no ETag!\n");
00665   else
00666     session_id=strdup(rtsp_search_answers(rtsp_session,"ETag"));
00667 
00668   lprintf("Stream description size: %i\n", size);
00669 
00670   description = (char*)malloc(sizeof(char)*(size+1));
00671   if( !description )
00672     goto error;
00673   if( rtsp_read_data(rtsp_session, description, size) <= 0)
00674     goto error;
00675   description[size]=0;
00676   fprintf(stderr,description);
00677 
00678   /* parse sdp (sdpplin) and create a header and a subscribe string */
00679   subscribe = (char *) malloc(sizeof(char)*256);
00680   if( !subscribe )
00681     goto error;
00682 
00683   strcpy(subscribe, "Subscribe: ");
00684   h=real_parse_sdp(description, &subscribe, bandwidth);
00685   if (!h)
00686     goto error;
00687 
00688   rmff_fix_header(h);
00689 
00690 #if 0
00691   fprintf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n",
00692       h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams);
00693 #endif
00694 
00695   /* setup our streams */
00696   real_calc_response_and_checksum (challenge2, checksum, challenge1);
00697   buf = realloc(buf, strlen(challenge2) + strlen(checksum) + 32);
00698   sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum);
00699   rtsp_schedule_field(rtsp_session, buf);
00700   buf = realloc(buf, strlen(session_id) + 32);
00701   sprintf(buf, "If-Match: %s", session_id);
00702   rtsp_schedule_field(rtsp_session, buf);
00703   rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
00704   buf = realloc(buf, strlen(mrl) + 32);
00705   sprintf(buf, "%s/streamid=0", mrl);
00706   rtsp_request_setup(rtsp_session,buf);
00707 
00708   if (h->prop->num_streams > 1) {
00709     rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
00710     buf = realloc(buf, strlen(session_id) + 32);
00711     sprintf(buf, "If-Match: %s", session_id);
00712     rtsp_schedule_field(rtsp_session, buf);
00713     buf = realloc(buf, strlen(mrl) + 32);
00714     sprintf(buf, "%s/streamid=1", mrl);
00715     rtsp_request_setup(rtsp_session,buf);
00716   }
00717   /* set stream parameter (bandwidth) with our subscribe string */
00718   rtsp_schedule_field(rtsp_session, subscribe);
00719   rtsp_request_setparameter(rtsp_session,NULL);
00720 
00721   /* and finally send a play request */
00722   rtsp_schedule_field(rtsp_session, "Range: npt=0-");
00723   rtsp_request_play(rtsp_session,NULL);
00724 
00725   if( challenge1 ) free( challenge1 );
00726   if( session_id ) free( session_id );
00727   if( description ) free(description);
00728   if( subscribe ) free(subscribe);
00729   if( buf ) free(buf);
00730   return h;
00731 
00732 error:
00733   if( h ) rmff_free_header( h );
00734   if( challenge1 ) free( challenge1 );
00735   if( session_id ) free( session_id );
00736   if( description ) free(description);
00737   if( subscribe ) free(subscribe);
00738   if( buf ) free(buf);
00739   return NULL;
00740 }

Generated on Tue Dec 20 10:14:26 2005 for vlc-0.8.4a by  doxygen 1.4.2