Mercurial > mplayer.hg
annotate libmpdemux/realrtsp/sdpplin.c @ 18831:bd70d74a994b
updated DOCS with new generic (non LIVE555 dependant) usage of -rtsp-port option
author | ben |
---|---|
date | Mon, 26 Jun 2006 21:32:59 +0000 |
parents | e16345b97dab |
children | 16990c298b7b |
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; | |
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 | |
12266 | 146 while (*data && **data && *data[0]!='m') { |
9922 | 147 |
148 handled=0; | |
149 | |
150 if(filter(*data,"a=control:streamid=",&buf)) { | |
151 desc->stream_id=atoi(buf); | |
152 handled=1; | |
153 *data=nl(*data); | |
154 } | |
155 | |
156 if(filter(*data,"a=MaxBitRate:integer;",&buf)) { | |
157 desc->max_bit_rate=atoi(buf); | |
158 if (!desc->avg_bit_rate) | |
159 desc->avg_bit_rate=desc->max_bit_rate; | |
160 handled=1; | |
161 *data=nl(*data); | |
162 } | |
163 | |
164 if(filter(*data,"a=MaxPacketSize:integer;",&buf)) { | |
165 desc->max_packet_size=atoi(buf); | |
166 if (!desc->avg_packet_size) | |
167 desc->avg_packet_size=desc->max_packet_size; | |
168 handled=1; | |
169 *data=nl(*data); | |
170 } | |
171 | |
172 if(filter(*data,"a=StartTime:integer;",&buf)) { | |
173 desc->start_time=atoi(buf); | |
174 handled=1; | |
175 *data=nl(*data); | |
176 } | |
177 | |
178 if(filter(*data,"a=Preroll:integer;",&buf)) { | |
179 desc->preroll=atoi(buf); | |
180 handled=1; | |
181 *data=nl(*data); | |
182 } | |
183 | |
184 if(filter(*data,"a=length:npt=",&buf)) { | |
185 desc->duration=(uint32_t)(atof(buf)*1000); | |
186 handled=1; | |
187 *data=nl(*data); | |
188 } | |
189 | |
190 if(filter(*data,"a=StreamName:string;",&buf)) { | |
191 desc->stream_name=strdup(buf); | |
192 desc->stream_name_size=strlen(desc->stream_name); | |
193 handled=1; | |
194 *data=nl(*data); | |
195 } | |
196 | |
197 if(filter(*data,"a=mimetype:string;",&buf)) { | |
198 desc->mime_type=strdup(buf); | |
199 desc->mime_type_size=strlen(desc->mime_type); | |
200 handled=1; | |
201 *data=nl(*data); | |
202 } | |
203 | |
204 if(filter(*data,"a=OpaqueData:buffer;",&buf)) { | |
205 decoded = b64_decode(buf, decoded, &(desc->mlti_data_size)); | |
206 desc->mlti_data=malloc(sizeof(char)*desc->mlti_data_size); | |
207 memcpy(desc->mlti_data, decoded, desc->mlti_data_size); | |
208 handled=1; | |
209 *data=nl(*data); | |
210 #ifdef LOG | |
211 printf("mlti_data_size: %i\n", desc->mlti_data_size); | |
212 #endif | |
213 } | |
214 | |
215 if(filter(*data,"a=ASMRuleBook:string;",&buf)) { | |
216 desc->asm_rule_book=strdup(buf); | |
217 handled=1; | |
218 *data=nl(*data); | |
219 } | |
220 | |
221 if(!handled) { | |
222 #ifdef LOG | |
223 int len=strchr(*data,'\n')-(*data); | |
224 buf = xbuffer_copyin(buf, 0, *data, len+1); | |
225 buf[len]=0; | |
226 printf("libreal: sdpplin: not handled: '%s'\n", buf); | |
227 #endif | |
228 *data=nl(*data); | |
229 } | |
230 } | |
231 | |
232 xbuffer_free(buf); | |
233 xbuffer_free(decoded); | |
234 | |
235 return desc; | |
236 } | |
237 | |
238 sdpplin_t *sdpplin_parse(char *data) { | |
239 | |
240 sdpplin_t *desc=calloc(1,sizeof(sdpplin_t)); | |
241 char *buf=xbuffer_init(32); | |
242 char *decoded=xbuffer_init(32); | |
243 int handled; | |
244 int len; | |
245 | |
12266 | 246 while (data && *data) { |
9922 | 247 |
248 handled=0; | |
249 | |
250 if (filter(data, "m=", &buf)) { | |
18095
5327871ea0e5
missing free in case sdpplin_parse_stream returns invalid stream.
reimar
parents:
15932
diff
changeset
|
251 sdpplin_stream_t *stream=sdpplin_parse_stream(&data); |
9922 | 252 #ifdef LOG |
253 printf("got data for stream id %u\n", stream->stream_id); | |
254 #endif | |
15930
f59fdc0d0d14
Do some sanity checks before writing stream information
rtognimp
parents:
15797
diff
changeset
|
255 if (desc->stream && (stream->stream_id >= 0) && (stream->stream_id < desc->stream_count)) |
9922 | 256 desc->stream[stream->stream_id]=stream; |
15930
f59fdc0d0d14
Do some sanity checks before writing stream information
rtognimp
parents:
15797
diff
changeset
|
257 else |
18095
5327871ea0e5
missing free in case sdpplin_parse_stream returns invalid stream.
reimar
parents:
15932
diff
changeset
|
258 { |
15930
f59fdc0d0d14
Do some sanity checks before writing stream information
rtognimp
parents:
15797
diff
changeset
|
259 mp_msg(MSGT_OPEN, MSGL_ERR, "sdpplin: got 'm=', but 'a=StreamCount' is still unknown. Broken sdp?\n"); |
18095
5327871ea0e5
missing free in case sdpplin_parse_stream returns invalid stream.
reimar
parents:
15932
diff
changeset
|
260 free(stream); |
5327871ea0e5
missing free in case sdpplin_parse_stream returns invalid stream.
reimar
parents:
15932
diff
changeset
|
261 } |
9922 | 262 continue; |
263 } | |
264 | |
265 if(filter(data,"a=Title:buffer;",&buf)) { | |
266 decoded=b64_decode(buf, decoded, &len); | |
267 desc->title=strdup(decoded); | |
268 handled=1; | |
269 data=nl(data); | |
270 } | |
271 | |
272 if(filter(data,"a=Author:buffer;",&buf)) { | |
273 decoded=b64_decode(buf, decoded, &len); | |
274 desc->author=strdup(decoded); | |
275 handled=1; | |
276 data=nl(data); | |
277 } | |
278 | |
279 if(filter(data,"a=Copyright:buffer;",&buf)) { | |
280 decoded=b64_decode(buf, decoded, &len); | |
281 desc->copyright=strdup(decoded); | |
282 handled=1; | |
283 data=nl(data); | |
284 } | |
285 | |
286 if(filter(data,"a=Abstract:buffer;",&buf)) { | |
287 decoded=b64_decode(buf, decoded, &len); | |
288 desc->abstract=strdup(decoded); | |
289 handled=1; | |
290 data=nl(data); | |
291 } | |
292 | |
293 if(filter(data,"a=StreamCount:integer;",&buf)) { | |
15930
f59fdc0d0d14
Do some sanity checks before writing stream information
rtognimp
parents:
15797
diff
changeset
|
294 desc->stream_count=(unsigned int)atoi(buf); |
9922 | 295 desc->stream=malloc(sizeof(sdpplin_stream_t*)*desc->stream_count); |
296 handled=1; | |
297 data=nl(data); | |
298 } | |
299 | |
300 if(filter(data,"a=Flags:integer;",&buf)) { | |
301 desc->flags=atoi(buf); | |
302 handled=1; | |
303 data=nl(data); | |
304 } | |
305 | |
306 if(!handled) { | |
307 #ifdef LOG | |
308 int len=strchr(data,'\n')-data; | |
309 buf = xbuffer_copyin(buf, 0, data, len+1); | |
310 buf[len]=0; | |
311 printf("libreal: sdpplin: not handled: '%s'\n", buf); | |
312 #endif | |
313 data=nl(data); | |
314 } | |
315 } | |
316 | |
317 xbuffer_free(buf); | |
318 xbuffer_free(decoded); | |
319 | |
320 return desc; | |
321 } | |
322 | |
323 void sdpplin_free(sdpplin_t *description) { | |
324 | |
325 /* TODO: free strings */ | |
326 free(description); | |
327 } | |
328 |