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