Mercurial > mplayer.hg
annotate stream/realrtsp/sdpplin.c @ 23611:ecbb54f8d299
make opt argument of demux_info_get const.
author | reimar |
---|---|
date | Sun, 24 Jun 2007 10:20:42 +0000 |
parents | 7ea888a4b348 |
children | 430da0c9fcce |
rev | line source |
---|---|
9922 | 1 /* |
2 * This file was ported to MPlayer from xine CVS sdpplin.c,v 1.1 2002/12/24 01:30:22 | |
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 * sdp/sdpplin parser. | |
26 * | |
27 */ | |
28 | |
15930
f59fdc0d0d14
Do some sanity checks before writing stream information
rtognimp
parents:
15797
diff
changeset
|
29 #include "config.h" |
18799
e16345b97dab
moved generic rtsp related files from realrtsp to librtsp
ben
parents:
18095
diff
changeset
|
30 #include "../librtsp/rtsp.h" |
9922 | 31 #include "sdpplin.h" |
32 #include "xbuffer.h" | |
15930
f59fdc0d0d14
Do some sanity checks before writing stream information
rtognimp
parents:
15797
diff
changeset
|
33 #include "mp_msg.h" |
9922 | 34 |
35 /* | |
36 #define LOG | |
37 */ | |
38 | |
39 /* | |
40 * Decodes base64 strings (based upon b64 package) | |
41 */ | |
42 | |
43 static char *b64_decode(const char *in, char *out, int *size) | |
44 { | |
45 char dtable[256]; /* Encode / decode table */ | |
46 int i,j,k; | |
47 | |
48 for (i = 0; i < 255; i++) { | |
49 dtable[i] = 0x80; | |
50 } | |
51 for (i = 'A'; i <= 'Z'; i++) { | |
52 dtable[i] = 0 + (i - 'A'); | |
53 } | |
54 for (i = 'a'; i <= 'z'; i++) { | |
55 dtable[i] = 26 + (i - 'a'); | |
56 } | |
57 for (i = '0'; i <= '9'; i++) { | |
58 dtable[i] = 52 + (i - '0'); | |
59 } | |
60 dtable['+'] = 62; | |
61 dtable['/'] = 63; | |
62 dtable['='] = 0; | |
63 | |
64 k=0; | |
65 | |
66 /*CONSTANTCONDITION*/ | |
67 for (j=0; j<strlen(in); j+=4) | |
68 { | |
69 char a[4], b[4]; | |
70 | |
71 for (i = 0; i < 4; i++) { | |
72 int c = in[i+j]; | |
73 | |
74 if (dtable[c] & 0x80) { | |
75 printf("Illegal character '%c' in input.\n", c); | |
76 // exit(1); | |
77 return NULL; | |
78 } | |
79 a[i] = (char) c; | |
80 b[i] = (char) dtable[c]; | |
81 } | |
15932
9bb26af4f477
Revert fix v1.3, it breaks streams with cook audio (ex.
rtognimp
parents:
15930
diff
changeset
|
82 out = xbuffer_ensure_size(out, k+4); |
9922 | 83 out[k++] = (b[0] << 2) | (b[1] >> 4); |
84 out[k++] = (b[1] << 4) | (b[2] >> 2); | |
85 out[k++] = (b[2] << 6) | b[3]; | |
86 i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3); | |
87 if (i < 3) { | |
15932
9bb26af4f477
Revert fix v1.3, it breaks streams with cook audio (ex.
rtognimp
parents:
15930
diff
changeset
|
88 out[k]=0; |
9922 | 89 *size=k; |
90 return out; | |
91 } | |
92 } | |
15932
9bb26af4f477
Revert fix v1.3, it breaks streams with cook audio (ex.
rtognimp
parents:
15930
diff
changeset
|
93 out[k]=0; |
9922 | 94 *size=k; |
95 return out; | |
96 } | |
97 | |
98 static char *nl(char *data) { | |
99 | |
12266 | 100 char *nlptr = (data) ? strchr(data,'\n') : NULL; |
101 return (nlptr) ? nlptr + 1 : NULL; | |
9922 | 102 } |
103 | |
104 static int filter(const char *in, const char *filter, char **out) { | |
105 | |
106 int flen=strlen(filter); | |
12266 | 107 int len; |
108 | |
109 if (!in) | |
110 return 0; | |
111 | |
112 len = (strchr(in,'\n')) ? strchr(in,'\n')-in : strlen(in); | |
9922 | 113 |
114 if (!strncmp(in,filter,flen)) | |
115 { | |
116 if(in[flen]=='"') flen++; | |
117 if(in[len-1]==13) len--; | |
118 if(in[len-1]=='"') len--; | |
119 *out = xbuffer_copyin(*out, 0, in+flen, len-flen+1); | |
120 (*out)[len-flen]=0; | |
121 | |
122 return len-flen; | |
123 } | |
124 | |
125 return 0; | |
126 } | |
127 static sdpplin_stream_t *sdpplin_parse_stream(char **data) { | |
128 | |
129 sdpplin_stream_t *desc=calloc(1,sizeof(sdpplin_stream_t)); | |
130 char *buf=xbuffer_init(32); | |
131 char *decoded=xbuffer_init(32); | |
132 int handled; | |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
133 int got_mimetype; |
9922 | 134 |
135 if (filter(*data, "m=", &buf)) { | |
136 desc->id = strdup(buf); | |
137 } else | |
138 { | |
139 printf("sdpplin: no m= found.\n"); | |
140 free(desc); | |
141 xbuffer_free(buf); | |
142 return NULL; | |
143 } | |
144 *data=nl(*data); | |
145 | |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
146 got_mimetype = 0; |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
147 |
12266 | 148 while (*data && **data && *data[0]!='m') { |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
149 #ifdef LOG |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
150 { |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
151 int len=strchr(*data,'\n')-(*data); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
152 buf = xbuffer_copyin(buf, 0, *data, len+1); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
153 buf[len]=0; |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
154 printf("libreal: sdpplin_stream: '%s'\n", buf); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
155 } |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
156 #endif |
9922 | 157 |
158 handled=0; | |
159 | |
160 if(filter(*data,"a=control:streamid=",&buf)) { | |
161 desc->stream_id=atoi(buf); | |
162 handled=1; | |
163 *data=nl(*data); | |
164 } | |
165 | |
166 if(filter(*data,"a=MaxBitRate:integer;",&buf)) { | |
167 desc->max_bit_rate=atoi(buf); | |
168 if (!desc->avg_bit_rate) | |
169 desc->avg_bit_rate=desc->max_bit_rate; | |
170 handled=1; | |
171 *data=nl(*data); | |
172 } | |
173 | |
174 if(filter(*data,"a=MaxPacketSize:integer;",&buf)) { | |
175 desc->max_packet_size=atoi(buf); | |
176 if (!desc->avg_packet_size) | |
177 desc->avg_packet_size=desc->max_packet_size; | |
178 handled=1; | |
179 *data=nl(*data); | |
180 } | |
181 | |
182 if(filter(*data,"a=StartTime:integer;",&buf)) { | |
183 desc->start_time=atoi(buf); | |
184 handled=1; | |
185 *data=nl(*data); | |
186 } | |
187 | |
188 if(filter(*data,"a=Preroll:integer;",&buf)) { | |
189 desc->preroll=atoi(buf); | |
190 handled=1; | |
191 *data=nl(*data); | |
192 } | |
193 | |
194 if(filter(*data,"a=length:npt=",&buf)) { | |
195 desc->duration=(uint32_t)(atof(buf)*1000); | |
196 handled=1; | |
197 *data=nl(*data); | |
198 } | |
199 | |
200 if(filter(*data,"a=StreamName:string;",&buf)) { | |
201 desc->stream_name=strdup(buf); | |
202 desc->stream_name_size=strlen(desc->stream_name); | |
203 handled=1; | |
204 *data=nl(*data); | |
205 } | |
206 | |
207 if(filter(*data,"a=mimetype:string;",&buf)) { | |
208 desc->mime_type=strdup(buf); | |
209 desc->mime_type_size=strlen(desc->mime_type); | |
210 handled=1; | |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
211 got_mimetype = 1; |
9922 | 212 *data=nl(*data); |
213 } | |
214 | |
215 if(filter(*data,"a=OpaqueData:buffer;",&buf)) { | |
216 decoded = b64_decode(buf, decoded, &(desc->mlti_data_size)); | |
19070 | 217 desc->mlti_data=malloc(desc->mlti_data_size); |
9922 | 218 memcpy(desc->mlti_data, decoded, desc->mlti_data_size); |
219 handled=1; | |
220 *data=nl(*data); | |
221 #ifdef LOG | |
222 printf("mlti_data_size: %i\n", desc->mlti_data_size); | |
223 #endif | |
224 } | |
225 | |
226 if(filter(*data,"a=ASMRuleBook:string;",&buf)) { | |
227 desc->asm_rule_book=strdup(buf); | |
228 handled=1; | |
229 *data=nl(*data); | |
230 } | |
231 | |
232 if(!handled) { | |
233 #ifdef LOG | |
234 int len=strchr(*data,'\n')-(*data); | |
235 buf = xbuffer_copyin(buf, 0, *data, len+1); | |
236 buf[len]=0; | |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
237 printf("libreal: sdpplin_stream: not handled: '%s'\n", buf); |
9922 | 238 #endif |
239 *data=nl(*data); | |
240 } | |
241 } | |
242 | |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
243 if (!got_mimetype) { |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
244 mp_msg(MSGT_OPEN, MSGL_V, "libreal: sdpplin_stream: no mimetype\n"); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
245 desc->mime_type = strdup("audio/x-pn-realaudio"); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
246 desc->mime_type_size = strlen(desc->mime_type); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
247 if (desc->stream_id) |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
248 mp_msg(MSGT_OPEN, MSGL_WARN, "libreal: sdpplin_stream: implicit mimetype for stream_id != 0, weird.\n"); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
249 } |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
250 |
9922 | 251 xbuffer_free(buf); |
252 xbuffer_free(decoded); | |
253 | |
254 return desc; | |
255 } | |
256 | |
257 sdpplin_t *sdpplin_parse(char *data) { | |
258 | |
259 sdpplin_t *desc=calloc(1,sizeof(sdpplin_t)); | |
260 char *buf=xbuffer_init(32); | |
261 char *decoded=xbuffer_init(32); | |
262 int handled; | |
263 int len; | |
264 | |
12266 | 265 while (data && *data) { |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
266 #ifdef LOG |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
267 { |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
268 int len=strchr(data,'\n')-(data); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
269 buf = xbuffer_copyin(buf, 0, data, len+1); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
270 buf[len]=0; |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
271 printf("libreal: sdpplin: '%s'\n", buf); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
272 } |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
273 #endif |
9922 | 274 |
275 handled=0; | |
276 | |
277 if (filter(data, "m=", &buf)) { | |
18095
5327871ea0e5
missing free in case sdpplin_parse_stream returns invalid stream.
reimar
parents:
15932
diff
changeset
|
278 sdpplin_stream_t *stream=sdpplin_parse_stream(&data); |
9922 | 279 #ifdef LOG |
280 printf("got data for stream id %u\n", stream->stream_id); | |
281 #endif | |
15930
f59fdc0d0d14
Do some sanity checks before writing stream information
rtognimp
parents:
15797
diff
changeset
|
282 if (desc->stream && (stream->stream_id >= 0) && (stream->stream_id < desc->stream_count)) |
9922 | 283 desc->stream[stream->stream_id]=stream; |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
284 else if (desc->stream) |
18095
5327871ea0e5
missing free in case sdpplin_parse_stream returns invalid stream.
reimar
parents:
15932
diff
changeset
|
285 { |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
286 mp_msg(MSGT_OPEN, MSGL_ERR, "sdpplin: bad stream_id %d (must be >= 0, < %d). Broken sdp?\n", |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
287 stream->stream_id, desc->stream_count); |
18095
5327871ea0e5
missing free in case sdpplin_parse_stream returns invalid stream.
reimar
parents:
15932
diff
changeset
|
288 free(stream); |
19093
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
289 } else { |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
290 mp_msg(MSGT_OPEN, MSGL_V, "sdpplin: got 'm=', but 'a=StreamCount' is still unknown.\n"); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
291 if (stream->stream_id == 0) { |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
292 desc->stream_count=1; |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
293 desc->stream=malloc(sizeof(sdpplin_stream_t*)); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
294 desc->stream[0]=stream; |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
295 } else { |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
296 mp_msg(MSGT_OPEN, MSGL_ERR, "sdpplin: got 'm=', but 'a=StreamCount' is still unknown and stream_id != 0. Broken sdp?\n"); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
297 free(stream); |
aca5ce3701e9
Assume that missing streamcount means one stream, and missing mimetype
rtogni
parents:
19070
diff
changeset
|
298 } |
18095
5327871ea0e5
missing free in case sdpplin_parse_stream returns invalid stream.
reimar
parents:
15932
diff
changeset
|
299 } |
9922 | 300 continue; |
301 } | |
302 | |
303 if(filter(data,"a=Title:buffer;",&buf)) { | |
304 decoded=b64_decode(buf, decoded, &len); | |
305 desc->title=strdup(decoded); | |
306 handled=1; | |
307 data=nl(data); | |
308 } | |
309 | |
310 if(filter(data,"a=Author:buffer;",&buf)) { | |
311 decoded=b64_decode(buf, decoded, &len); | |
312 desc->author=strdup(decoded); | |
313 handled=1; | |
314 data=nl(data); | |
315 } | |
316 | |
317 if(filter(data,"a=Copyright:buffer;",&buf)) { | |
318 decoded=b64_decode(buf, decoded, &len); | |
319 desc->copyright=strdup(decoded); | |
320 handled=1; | |
321 data=nl(data); | |
322 } | |
323 | |
324 if(filter(data,"a=Abstract:buffer;",&buf)) { | |
325 decoded=b64_decode(buf, decoded, &len); | |
326 desc->abstract=strdup(decoded); | |
327 handled=1; | |
328 data=nl(data); | |
329 } | |
330 | |
331 if(filter(data,"a=StreamCount:integer;",&buf)) { | |
15930
f59fdc0d0d14
Do some sanity checks before writing stream information
rtognimp
parents:
15797
diff
changeset
|
332 desc->stream_count=(unsigned int)atoi(buf); |
9922 | 333 desc->stream=malloc(sizeof(sdpplin_stream_t*)*desc->stream_count); |
334 handled=1; | |
335 data=nl(data); | |
336 } | |
337 | |
338 if(filter(data,"a=Flags:integer;",&buf)) { | |
339 desc->flags=atoi(buf); | |
340 handled=1; | |
341 data=nl(data); | |
342 } | |
343 | |
344 if(!handled) { | |
345 #ifdef LOG | |
346 int len=strchr(data,'\n')-data; | |
347 buf = xbuffer_copyin(buf, 0, data, len+1); | |
348 buf[len]=0; | |
349 printf("libreal: sdpplin: not handled: '%s'\n", buf); | |
350 #endif | |
351 data=nl(data); | |
352 } | |
353 } | |
354 | |
355 xbuffer_free(buf); | |
356 xbuffer_free(decoded); | |
357 | |
358 return desc; | |
359 } | |
360 | |
361 void sdpplin_free(sdpplin_t *description) { | |
362 | |
21788 | 363 int i; |
364 | |
365 if (!description) | |
366 return; | |
367 | |
368 for (i = 0; i < description->stream_count; i++) { | |
369 if (description->stream[i]) { | |
370 if (description->stream[i]->stream_name) | |
371 free(description->stream[i]->stream_name); | |
372 if (description->stream[i]->mime_type) | |
373 free(description->stream[i]->mime_type); | |
374 if (description->stream[i]->mlti_data) | |
375 free(description->stream[i]->mlti_data); | |
376 if (description->stream[i]->asm_rule_book) | |
377 free(description->stream[i]->asm_rule_book); | |
21790
7ea888a4b348
More free() that were forgotten in r21806 memleak fix
rtogni
parents:
21788
diff
changeset
|
378 free(description->stream[i]); |
21788 | 379 } |
380 } | |
381 | |
21790
7ea888a4b348
More free() that were forgotten in r21806 memleak fix
rtogni
parents:
21788
diff
changeset
|
382 if(description->stream_count) |
7ea888a4b348
More free() that were forgotten in r21806 memleak fix
rtogni
parents:
21788
diff
changeset
|
383 free(description->stream); |
21788 | 384 if (description->title) |
385 free(description->title); | |
386 if (description->author) | |
387 free(description->author); | |
388 if (description->copyright) | |
389 free(description->copyright); | |
390 if (description->abstract) | |
391 free(description->abstract); | |
392 | |
9922 | 393 free(description); |
394 } | |
395 |