1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 #include "rfc3640_media_info_parser.h"
19 #include "oscl_string_utils.h"
20 #include "oscl_string_containers.h"
21 #include "sdp_error.h"
22
23 SDP_ERROR_CODE
parseMediaInfo(const char * buff,const int index,SDPInfo * sdp,payloadVector payload_vec,bool isSipSdp,int alt_id,bool alt_def_id)24 SDPRFC3640MediaInfoParser::parseMediaInfo(const char *buff, const int index, SDPInfo *sdp, payloadVector payload_vec, bool isSipSdp, int alt_id, bool alt_def_id)
25 {
26
27 const char *current_start = buff; //Pointer to the beginning of the media text
28 const char *end = buff + index; //Pointer to the end of the media text
29 const char *line_start_ptr, *line_end_ptr;
30 int VOLLength = 0;
31 int fmtp_cnt = 0 ;
32 bool sizelength_found_in_fmtp = false;
33 bool indexlength_found_in_fmtp = false;
34 bool indexDeltaLength_found_in_fmtp = false;
35 SDPAllocDestructDealloc<uint8> SDP_alloc;
36 int strmType = 5;
37 OsclMemoryFragment modeMemFrag = {NULL, 0};
38 int decLength = 0;
39
40
41 while (get_next_line(current_start, end,
42 line_start_ptr, line_end_ptr))
43 {
44 if ((!oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) && (alt_def_id == false))
45 {
46 line_start_ptr += oscl_strlen("a=alt:");
47 for (; *line_start_ptr != ':'; line_start_ptr++);
48 line_start_ptr = line_start_ptr + 1;
49 }
50 if (!oscl_strncmp(line_start_ptr, "a=fmtp:", oscl_strlen("a=fmtp:")))
51 {
52 char *tmp_start_line, *tmp_end_line;
53 fmtp_cnt++ ;
54
55 tmp_start_line = (char *)line_start_ptr + oscl_strlen("a=fmtp:");
56 tmp_start_line = (char *)skip_whitespace(tmp_start_line, line_end_ptr);
57 if (tmp_start_line >= line_end_ptr)
58 {
59 break;
60 }
61 tmp_end_line = (char *)skip_to_whitespace(tmp_start_line, line_end_ptr);
62 if (tmp_end_line < tmp_start_line)
63 {
64 break;
65 }
66 tmp_start_line = tmp_end_line + 1;
67 tmp_start_line = (char *)skip_whitespace(tmp_start_line, line_end_ptr);
68 if (tmp_start_line >= line_end_ptr)
69 {
70 break;
71 }
72 int ii = 0;
73 const char *temp = tmp_start_line;
74 for (ii = 0; ii < (line_end_ptr - tmp_start_line) ; ii++)
75 {
76 if ((tmp_start_line[ii] == ';') || (ii == (line_end_ptr - tmp_start_line - 1)))
77 {
78 tmp_end_line = tmp_start_line + ii;
79 if ((line_end_ptr - tmp_start_line - 1) == ii)
80 {
81 tmp_end_line++;
82 }
83 if (!oscl_strncmp(temp, "config=", oscl_strlen("config=")))
84 {
85 uint32 currentLength;
86 temp += oscl_strlen("config=");
87 temp = skip_whitespace(temp, line_end_ptr);
88 if (temp >= line_end_ptr)
89 {
90 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - no data in config= field"));
91 return SDP_BAD_MEDIA_FMTP;
92 }
93 currentLength = (int)(tmp_end_line - temp) / 2;
94
95 if (decLength < (int) currentLength)
96
97 decLength = currentLength;
98 }
99
100 if (!oscl_CIstrncmp(temp, "streamtype=", oscl_strlen("streamtype=")))
101 {
102 temp += oscl_strlen("streamtype=");
103 temp = skip_whitespace(temp, line_end_ptr);
104 if (temp >= line_end_ptr)
105 {
106 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad StreamType field"));
107 return SDP_BAD_MEDIA_FMTP;
108 }
109 uint32 type;
110 if (PV_atoi(temp, 'd', (tmp_end_line - temp), type) == false)
111 {
112 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad StreamType field"));
113 return SDP_BAD_MEDIA_FMTP;
114 }
115 else
116 strmType = type;
117 }
118 if (!oscl_strncmp(temp, "mode=", oscl_strlen("mode=")))
119 {
120 temp += oscl_strlen("mode=");
121 temp = skip_whitespace(temp, line_end_ptr);
122 if (temp >= line_end_ptr)
123 {
124 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad mode field"));
125 return SDP_BAD_MEDIA_FMTP;
126 }
127 modeMemFrag.ptr = (void*)temp;
128 modeMemFrag.len = (tmp_end_line - temp);
129 }
130
131 if (tmp_end_line != line_end_ptr) temp = tmp_end_line + 1;
132 temp = skip_whitespace(temp, line_end_ptr);
133 if (temp >= line_end_ptr)
134 {
135 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format"));
136 return SDP_BAD_MEDIA_FMTP;
137 }
138
139 }
140 }
141 }
142
143
144 current_start = line_end_ptr + 1;
145 }
146
147 if (fmtp_cnt == 0 && isSipSdp == false)
148 {
149 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - No fmtp line found"));
150 return SDP_BAD_MEDIA_FORMAT;
151 }
152
153 if (NULL == modeMemFrag.ptr)
154 {
155 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - No mode field"));
156 return SDP_BAD_MEDIA_FMTP;
157 }
158
159 if (VOLLength < 0)
160 {
161 VOLLength = 0;
162 }
163
164 bool altMedia = false;
165 if (!alt_id || (alt_def_id == true))
166 altMedia = false;
167 else
168 altMedia = true;
169
170 void *memory = sdp->alloc(sizeof(rfc3640_mediaInfo), altMedia);
171 if (NULL == memory)
172 {
173 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - memory allocation failure"));
174 return SDP_NO_MEMORY;
175 }
176 else
177 {
178 rfc3640_mediaInfo *m3640media = OSCL_PLACEMENT_NEW(memory, rfc3640_mediaInfo());
179
180 m3640media->setMediaInfoID(sdp->getMediaObjectIndex());
181 m3640media->setStreamType(strmType);
182 m3640media->setModeType(modeMemFrag);
183
184 // Allocate memory to the payload specific objects
185 for (uint32 ii = 0; ii < payload_vec.size(); ii++)
186 {
187 void* mem = m3640media->alloc(sizeof(RFC3640PayloadSpecificInfoType));
188 if (mem == NULL)
189 {
190 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Memory allocation failure"));
191 return SDP_NO_MEMORY;
192 }
193 else
194 {
195 RFC3640PayloadSpecificInfoType* payload = OSCL_PLACEMENT_NEW(mem, RFC3640PayloadSpecificInfoType(payload_vec[ii]));
196 (void) payload;
197 }
198 }
199
200
201 if (alt_id && !alt_def_id)
202 {
203 sdp->copyFmDefMedia(m3640media);
204 //empty alternate & default track ID vectors.
205 m3640media->resetAlternateTrackId();
206 m3640media->resetDependentTrackId();
207 }
208
209 SDP_ERROR_CODE status = baseMediaInfoParser(buff, m3640media, index, alt_id, alt_def_id, isSipSdp);
210 if (status != SDP_SUCCESS)
211 {
212 return status;
213 }
214
215 current_start = buff;
216
217
218 while (get_next_line(current_start, end,
219 line_start_ptr, line_end_ptr))
220 {
221 switch (*line_start_ptr)
222 {
223 case 'a':
224 {
225 if ((!oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) && (alt_def_id == false))
226 {
227 line_start_ptr += oscl_strlen("a=alt:");
228 for (; *line_start_ptr != ':'; line_start_ptr++);
229 line_start_ptr = line_start_ptr + 1;
230 }
231 if (!oscl_strncmp(line_start_ptr, "a=fmtp:", oscl_strlen("a=fmtp:")))
232 {
233 const char *tmp_start_line, *tmp_end_line;
234 tmp_start_line = line_start_ptr + oscl_strlen("a=fmtp:");
235 tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
236 if (tmp_start_line >= line_end_ptr)
237 {
238 break;
239 }
240 tmp_end_line = skip_to_whitespace(tmp_start_line, line_end_ptr);
241 if (tmp_end_line < tmp_start_line)
242 {
243 break;
244 }
245 uint32 payloadNumber;
246 if (PV_atoi(tmp_start_line, 'd', (tmp_end_line - tmp_start_line), payloadNumber) == false)
247 {
248 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad payload number"));
249 return SDP_BAD_MEDIA_FMTP;
250 }
251 else
252 {
253 int p;
254 if (!m3640media->lookupPayloadNumber(payloadNumber, p))
255 {
256 fmtp_cnt--;
257 break;
258 }
259 }
260
261 RFC3640PayloadSpecificInfoType* payloadPtr =
262 (RFC3640PayloadSpecificInfoType*)m3640media->getPayloadSpecificInfoTypePtr(payloadNumber);
263 if (payloadPtr == NULL)
264 {
265 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - payload pointer not found for payload"));
266 return SDP_PAYLOAD_MISMATCH;
267 }
268
269 PVMF_SDP_PARSER_LOGINFO((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - processing payload number : %d", payloadNumber));
270
271 tmp_start_line = tmp_end_line + 1;
272 tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
273 if (tmp_start_line >= line_end_ptr)
274 {
275 break;
276 }
277 int ii = 0;
278 const char *temp = tmp_start_line;
279 for (ii = 0; ii < (line_end_ptr - tmp_start_line) ; ii++)
280 {
281 if ((tmp_start_line[ii] == ';') || (ii == (line_end_ptr - tmp_start_line - 1)))
282 {
283 tmp_end_line = tmp_start_line + ii;
284 if (ii == (line_end_ptr - tmp_start_line - 1))
285 {
286 tmp_end_line += 1;
287 }
288 if (!oscl_CIstrncmp(temp, "profile-level-id=", oscl_strlen("profile-level-id=")))
289 {
290 temp += oscl_strlen("profile-level-id=");
291 temp = skip_whitespace(temp, line_end_ptr);
292 if (temp > line_end_ptr)
293 {
294 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad profile-level-id field"));
295 return SDP_BAD_MEDIA_FMTP;
296 }
297 uint32 pl;
298 if (PV_atoi(temp, 'd', tmp_end_line - temp , pl) == true)
299 payloadPtr->setProfileLevelID(pl);
300
301 }
302 if (!oscl_CIstrncmp(temp, "sizelength=", oscl_strlen("SizeLength=")))
303 {
304 temp += oscl_strlen("SizeLength=");
305 temp = skip_whitespace(temp, tmp_end_line);
306 sizelength_found_in_fmtp = true;
307 if (temp > tmp_end_line)
308 {
309 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad sizelength field"));
310 return SDP_BAD_MEDIA_FMTP;
311 }
312 uint32 length;
313 if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true)
314 payloadPtr->setSizeLength(length);
315 }
316 if (!oscl_CIstrncmp(temp, "indexlength=", oscl_strlen("IndexLength=")))
317 {
318 temp += oscl_strlen("IndexLength=");
319 temp = skip_whitespace(temp, tmp_end_line);
320 indexlength_found_in_fmtp = true;
321 if (temp > tmp_end_line)
322 {
323 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad indexlength field"));
324 return SDP_BAD_MEDIA_FMTP;
325 }
326 uint32 length;
327 if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true)
328 payloadPtr->setIndexLength(length);
329 }
330 if (!oscl_CIstrncmp(temp, "indexdeltalength=", oscl_strlen("IndexDeltaLength=")))
331 {
332 temp += oscl_strlen("IndexDeltaLength=");
333 temp = skip_whitespace(temp, tmp_end_line);
334 indexDeltaLength_found_in_fmtp = true;
335 if (temp > tmp_end_line)
336 {
337 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad indexDeltaLength field"));
338 return SDP_BAD_MEDIA_FMTP;
339 }
340 uint32 length;
341 if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true)
342 payloadPtr->setIndexDeltaLength(length);
343 }
344 if (!oscl_CIstrncmp(temp, "CTSDeltaLength=", oscl_strlen("CTSDeltaLength=")))
345 {
346 temp += oscl_strlen("CTSDeltaLength=");
347 temp = skip_whitespace(temp, tmp_end_line);
348 indexDeltaLength_found_in_fmtp = true;
349 if (temp > tmp_end_line)
350 {
351 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad CTSDeltaLength field"));
352 return SDP_BAD_MEDIA_FMTP;
353 }
354 uint32 length;
355 if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true)
356 payloadPtr->setCTSDeltaLength(length);
357 }
358 if (!oscl_CIstrncmp(temp, "DTSDeltaLength=", oscl_strlen("DTSDeltaLength=")))
359 {
360 temp += oscl_strlen("DTSDeltaLength=");
361 temp = skip_whitespace(temp, tmp_end_line);
362 indexDeltaLength_found_in_fmtp = true;
363 if (temp > tmp_end_line)
364 {
365 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad DTSDeltaLength field"));
366 return SDP_BAD_MEDIA_FMTP;
367 }
368 uint32 length;
369 if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true)
370 payloadPtr->setDTSDeltaLength(length);
371 }
372 if (!oscl_CIstrncmp(temp, "constantDuration=", oscl_strlen("ConstantDuration=")))
373 {
374 temp += oscl_strlen("ConstantDuration=");
375 temp = skip_whitespace(temp, tmp_end_line);
376 indexDeltaLength_found_in_fmtp = true;
377 if (temp > tmp_end_line)
378 {
379 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad constantDuration field"));
380 return SDP_BAD_MEDIA_FMTP;
381 }
382 uint32 length;
383 if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true)
384 payloadPtr->setConstantDuration(length);
385 }
386 if (!oscl_CIstrncmp(temp, "maxDisplacement=", oscl_strlen("MaxDisplacement=")))
387 {
388 temp += oscl_strlen("MaxDisplacement=");
389 temp = skip_whitespace(temp, tmp_end_line);
390 indexDeltaLength_found_in_fmtp = true;
391 if (temp > tmp_end_line)
392 {
393 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad maxDisplacement field"));
394 return SDP_BAD_MEDIA_FMTP;
395 }
396 uint32 length;
397 if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true)
398 payloadPtr->setMaxDisplacement(length);
399 }
400 if (!oscl_CIstrncmp(temp, "de-interleaveBufferSize=", oscl_strlen("de-interleaveBufferSize=")))
401 {
402 temp += oscl_strlen("de-interleaveBufferSize=");
403 temp = skip_whitespace(temp, tmp_end_line);
404 indexDeltaLength_found_in_fmtp = true;
405 if (temp > tmp_end_line)
406 {
407 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad de-interleaveBufferSize= field"));
408 return SDP_BAD_MEDIA_FMTP;
409 }
410 uint32 length;
411 if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true)
412 payloadPtr->setDeInterleaveBufferSize(length);
413 }
414 if (!oscl_strncmp(temp, "config=", oscl_strlen("config=")))
415 {
416
417 uint8 *mptr = SDP_alloc.allocate(decLength);
418 OsclRefCounterSA< SDPAllocDestructDealloc<uint8> > *refcnt = new OsclRefCounterSA< SDPAllocDestructDealloc<uint8> >(mptr);
419 OsclSharedPtr<uint8> decInfo(mptr, refcnt);
420
421 temp += oscl_strlen("config=");
422 temp = skip_whitespace(temp, line_end_ptr);
423 if (temp >= line_end_ptr)
424 {
425 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect for config= field"));
426 return SDP_BAD_MEDIA_FMTP;
427 }
428 decLength = (int)(tmp_end_line - temp) / 2;
429 int idx = 0;
430 for (idx = 0; idx < decLength; idx++)
431 {
432 uint32 val;
433 if (PV_atoi((temp + 2*idx), 'x', 2, val) == false)
434 {
435 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect for config= field"));
436 return SDP_BAD_MEDIA_FMTP;
437 }
438
439 *(decInfo + idx) = (uint8) val;
440 }
441
442 if (payloadPtr)
443 {
444 payloadPtr->setDecoderSpecificInfo(decInfo);
445 payloadPtr->setDecoderSpecificInfoSize(decLength);
446 }
447 else
448 {
449 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect for payload"));
450 return SDP_PAYLOAD_MISMATCH;
451 }
452 }
453 if (!oscl_strncmp(temp, "decode_buf=", oscl_strlen("decode_buf=")))
454 {
455 temp += oscl_strlen("decode_buf=");
456 temp = skip_whitespace(temp, tmp_end_line);
457 if (temp > tmp_end_line)
458 {
459 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad decode_buf field"));
460 return SDP_BAD_MEDIA_FMTP;
461 }
462 uint32 dec;
463 if (PV_atoi(temp, 'd', tmp_end_line - temp, dec) == true)
464 payloadPtr->setMaxBufferSize(dec);
465 }
466 if (tmp_end_line != line_end_ptr) temp = tmp_end_line + 1;
467 temp = skip_whitespace(temp, line_end_ptr);
468 if (temp >= line_end_ptr)
469 {
470 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format"));
471 return SDP_BAD_MEDIA_FMTP;
472 }
473 }
474 }
475 }
476
477 }
478 break;
479 default:
480 break;
481 }
482 current_start = line_end_ptr;
483 }
484
485 if (!(indexDeltaLength_found_in_fmtp && sizelength_found_in_fmtp && indexlength_found_in_fmtp))
486 {
487 PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Required info missing"));
488 return SDP_MISSING_MEDIA_DESCRIPTION;
489
490 }
491 sessionDescription *session = sdp->getSessionInfo();
492
493 const char *altGroupBW = session->getAltGroupBW();
494 int length = session->getAltGroupBWLength();
495
496 if (length > 0)
497 {
498 status = setDependentMediaId(altGroupBW, length, m3640media, alt_id);
499 if (status != SDP_SUCCESS)
500 return SDP_BAD_MEDIA_ALT_ID;
501 }
502
503 const char *altGroupLANG = session->getAltGroupLANG();
504 length = session->getAltGroupLANGLength();
505
506 if (length > 0)
507 {
508 status = setDependentMediaId(altGroupLANG, length, m3640media, alt_id);
509 if (status != SDP_SUCCESS)
510 return SDP_BAD_MEDIA_ALT_ID;
511 }
512
513 return SDP_SUCCESS;
514 }
515
516 }
517
518