real_sdpplin.c 8.67 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Copyright (C) 2002-2003 the xine project
 *
 * This file is part of xine, a free video player.
 *
 * xine is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * xine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 *
20
 * $Id$
21
22
23
24
 *
 * sdp/sdpplin parser.
 *
 */
25

26
#include "real.h"
27
#include "vlc_strings.h"
28
#define BUFLEN 32000
29

30
static inline char *nl(char *data) {
31
32
  char *nlptr = (data) ? strchr(data,'\n') : NULL;
  return (nlptr) ? nlptr + 1 : NULL;
33
34
}

35
static int filter(const char *in, const char *filter, char **out, size_t outlen) {
36
37

  int flen=strlen(filter);
38
  size_t len;
39
40
41

  if (!in) return 0;

Konstantin Pavlov's avatar
Konstantin Pavlov committed
42
  len = (strchr(in,'\n')) ? (size_t)(strchr(in,'\n')-in) : strlen(in);
43
44
45
46
  if (!strncmp(in,filter,flen)) {
    if(in[flen]=='"') flen++;
    if(in[len-1]==13) len--;
    if(in[len-1]=='"') len--;
47
48
49
50
51
    if( len-flen+1 > outlen )
    {
        printf("Discarding end of string to avoid overflow");
        len=outlen+flen-1;
    }
52
53
54
55
56
    memcpy(*out, in+flen, len-flen+1);
    (*out)[len-flen]=0;
    return len-flen;
  }
  return 0;
57
58
}

59
60
static sdpplin_stream_t *sdpplin_parse_stream(char **data) {

ivoire's avatar
ivoire committed
61
62
63
64
  sdpplin_stream_t *desc;
  char* buf = NULL;
  char* decoded = NULL;
  int handled;
65

ivoire's avatar
ivoire committed
66
67
68
  desc = calloc( 1, sizeof(sdpplin_stream_t) );
  if( !desc )
    return NULL;
69

ivoire's avatar
ivoire committed
70
71
72
73
74
75
76
  buf = malloc( BUFLEN );
  if( !buf )
    goto error;

  decoded = malloc( BUFLEN );
  if( !decoded )
    goto error;
77

78
  if (filter(*data, "m=", &buf, BUFLEN)) {
79
80
81
82
83
84
    desc->id = strdup(buf);
  } else {
    lprintf("sdpplin: no m= found.\n");
    goto error;
  }
  *data=nl(*data);
85

86
87
  while (*data && **data && *data[0]!='m') {
    handled=0;
88

89
    if(filter(*data,"a=control:streamid=",&buf, BUFLEN)) {
90
91
92
93
94
95
96
97
98
99
        /* This way negative values are mapped to unfeasibly high
         * values, and will be discarded afterward
         */
        unsigned long tmp = strtoul(buf, NULL, 10);
        if ( tmp > UINT16_MAX )
            lprintf("stream id out of bound: %lu\n", tmp);
        else
            desc->stream_id=tmp;
        handled=1;
        *data=nl(*data);
100
    }
101
    if(filter(*data,"a=MaxBitRate:integer;",&buf, BUFLEN)) {
102
103
104
105
106
107
      desc->max_bit_rate=atoi(buf);
      if (!desc->avg_bit_rate)
        desc->avg_bit_rate=desc->max_bit_rate;
      handled=1;
      *data=nl(*data);
    }
108
    if(filter(*data,"a=MaxPacketSize:integer;",&buf, BUFLEN)) {
109
110
111
112
113
114
      desc->max_packet_size=atoi(buf);
      if (!desc->avg_packet_size)
        desc->avg_packet_size=desc->max_packet_size;
      handled=1;
      *data=nl(*data);
    }
115
    if(filter(*data,"a=StartTime:integer;",&buf, BUFLEN)) {
116
117
118
119
      desc->start_time=atoi(buf);
      handled=1;
      *data=nl(*data);
    }
120
    if(filter(*data,"a=Preroll:integer;",&buf, BUFLEN)) {
121
122
123
124
      desc->preroll=atoi(buf);
      handled=1;
      *data=nl(*data);
    }
125
    if(filter(*data,"a=length:npt=",&buf, BUFLEN)) {
126
127
128
      desc->duration=(uint32_t)(atof(buf)*1000);
      handled=1;
      *data=nl(*data);
129
    }
130
    if(filter(*data,"a=StreamName:string;",&buf, BUFLEN)) {
131
132
133
134
      desc->stream_name=strdup(buf);
      desc->stream_name_size=strlen(desc->stream_name);
      handled=1;
      *data=nl(*data);
135
    }
136
    if(filter(*data,"a=mimetype:string;",&buf, BUFLEN)) {
137
138
139
140
141
      desc->mime_type=strdup(buf);
      desc->mime_type_size=strlen(desc->mime_type);
      handled=1;
      *data=nl(*data);
    }
142
    if(filter(*data,"a=OpaqueData:buffer;",&buf, BUFLEN)) {
143
144
145
      desc->mlti_data_size =
          vlc_b64_decode_binary_to_buffer(decoded, BUFLEN, buf );
      if ( desc->mlti_data_size ) {
146
          desc->mlti_data = malloc(desc->mlti_data_size);
147
148
149
150
151
          memcpy(desc->mlti_data, decoded, desc->mlti_data_size);
          handled=1;
          *data=nl(*data);
          lprintf("mlti_data_size: %i\n", desc->mlti_data_size);
      }
152
    }
153
    if(filter(*data,"a=ASMRuleBook:string;",&buf, BUFLEN)) {
154
155
156
157
158
159
      desc->asm_rule_book=strdup(buf);
      handled=1;
      *data=nl(*data);
    }

    if(!handled) {
160
#ifdef LOG
161
162
163
164
      int len=strchr(*data,'\n')-(*data);
      memcpy(buf, *data, len+1);
      buf[len]=0;
      printf("libreal: sdpplin: not handled: '%s'\n", buf);
165
#endif
166
      *data=nl(*data);
167
    }
168
  }
169
170
  free( buf );
  free( decoded) ;
171
  return desc;
172
173

error:
174
175
176
  free( decoded );
  free( desc );
  free( buf );
177
  return NULL;
178
179
}

180

ivoire's avatar
ivoire committed
181
182
183
184
185
186
187
188
sdpplin_t *sdpplin_parse(char *data)
{
  sdpplin_t*        desc;
  sdpplin_stream_t* stream;
  char*             buf;
  char*             decoded;
  int               handled;
  int               len;
189

ivoire's avatar
ivoire committed
190
191
192
193
194
195
196
  desc = calloc( 1, sizeof(sdpplin_t) );
  if( !desc )
    return NULL;

  buf = malloc( BUFLEN );
  if( !buf )
  {
197
198
199
    free( desc );
    return NULL;
  }
ivoire's avatar
ivoire committed
200
201
202
203

  decoded = malloc( BUFLEN );
  if( !decoded )
  {
204
205
206
207
    free( buf );
    free( desc );
    return NULL;
  }
208
209
  desc->stream = NULL;

210
211
212
  while (data && *data) {
    handled=0;

213
    if (filter(data, "m=", &buf, BUFLEN)) {
214
215
216
217
218
219
        if ( !desc->stream ) {
            fprintf(stderr, "sdpplin.c: stream identifier found before stream count, skipping.");
            continue;
        }
        stream=sdpplin_parse_stream(&data);
        lprintf("got data for stream id %u\n", stream->stream_id);
220
221
222
223
        if ( stream->stream_id >= desc->stream_count )
            lprintf("stream id %u is greater than stream count %u\n", stream->stream_id, desc->stream_count);
        else
            desc->stream[stream->stream_id]=stream;
224
        continue;
225
    }
226
    if(filter(data,"a=Title:buffer;",&buf, BUFLEN)) {
227
228
229
230
      desc->title=vlc_b64_decode(buf);
      if(desc->title) {
        handled=1;
        data=nl(data);
231
      }
232
    }
233
    if(filter(data,"a=Author:buffer;",&buf, BUFLEN)) {
234
235
236
237
      desc->author=vlc_b64_decode(buf);
      if(desc->author) {
        handled=1;
        data=nl(data);
238
      }
239
    }
240
    if(filter(data,"a=Copyright:buffer;",&buf, BUFLEN)) {
241
242
243
244
      desc->copyright=vlc_b64_decode(buf);
      if(desc->copyright) {
        handled=1;
        data=nl(data);
245
      }
246
    }
247
    if(filter(data,"a=Abstract:buffer;",&buf, BUFLEN)) {
248
249
250
251
      desc->abstract=vlc_b64_decode(buf);
      if(desc->abstract) {
        handled=1;
        data=nl(data);
252
      }
253
    }
254
    if(filter(data,"a=StreamCount:integer;",&buf, BUFLEN)) {
255
256
257
258
259
260
261
262
263
264
265
        /* This way negative values are mapped to unfeasibly high
         * values, and will be discarded afterward
         */
        unsigned long tmp = strtoul(buf, NULL, 10);
        if ( tmp > UINT16_MAX )
            lprintf("stream count out of bound: %lu\n", tmp);
        else
            desc->stream_count = tmp;
        desc->stream = malloc(sizeof(sdpplin_stream_t*)*desc->stream_count);
        handled=1;
        data=nl(data);
266
    }
267
    if(filter(data,"a=Flags:integer;",&buf, BUFLEN)) {
268
269
270
271
272
273
      desc->flags=atoi(buf);
      handled=1;
      data=nl(data);
    }

    if(!handled) {
274
#ifdef LOG
275
276
277
278
      int len=strchr(data,'\n')-data;
      memcpy(buf, data, len+1);
      buf[len]=0;
      printf("libreal: sdpplin: not handled: '%s'\n", buf);
279
#endif
280
      data=nl(data);
281
    }
282
  }
283

284
285
  free( decoded );
  free( buf );
286
  return desc;
287
288
}

289
290
291
292
293
294
295
296
void sdpplin_free(sdpplin_t *description) {

  int i;

  if( !description ) return;

  for( i=0; i<description->stream_count; i++ ) {
    if( description->stream[i] ) {
297
298
299
300
301
302
303
304
305
306
307
      free( description->stream[i]->id );
      free( description->stream[i]->bandwidth );
      free( description->stream[i]->range );
      free( description->stream[i]->length );
      free( description->stream[i]->rtpmap );
      free( description->stream[i]->mimetype );
      free( description->stream[i]->stream_name );
      free( description->stream[i]->mime_type );
      free( description->stream[i]->mlti_data );
      free( description->stream[i]->rmff_flags );
      free( description->stream[i]->asm_rule_book );
308
      free( description->stream[i] );
309
    }
310
  }
ivoire's avatar
ivoire committed
311
312
  if( description->stream_count )
    free( description->stream );
313

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
  free( description->owner );
  free( description->session_name );
  free( description->session_info );
  free( description->uri );
  free( description->email );
  free( description->phone );
  free( description->connection );
  free( description->bandwidth );
  free( description->title );
  free( description->author );
  free( description->copyright );
  free( description->keywords );
  free( description->asm_rule_book );
  free( description->abstract );
  free( description->range );
ivoire's avatar
ivoire committed
329
  free( description );
330
}
331