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 "base_media_info_parser.h" 19 #include "oscl_string_utils.h" 20 #include "oscl_string_containers.h" 21 #include "rtsp_range_utils.h" 22 23 24 /* Function to allocate temporary buffer, OSCL_TRY() put here to avoid */ 25 /* compiler warnings */ 26 static void newTmpBuf(uint32 len, char** buf) 27 { 28 int32 err; 29 *buf = NULL; 30 31 OSCL_TRY(err, *buf = OSCL_ARRAY_NEW(char, len)); 32 33 if (err != OsclErrNone) 34 { 35 *buf = NULL; 36 } 37 } 38 39 SDP_ERROR_CODE 40 SDPBaseMediaInfoParser::baseMediaInfoParser(const char* buff, 41 mediaInfo* mediaStr, 42 const int index, 43 const int alt_id, 44 bool alt_def_id, 45 bool isSipSdp) 46 { 47 const char *current_start = buff; //Pointer to the beginning of the media text 48 const char *end = buff + index; //Pointer to the end of the media text 49 const char *line_start_ptr, *line_end_ptr; 50 51 52 bool a_range_found = false; 53 54 bool a_rtpmap_found = false; 55 bool a_control_found = false; 56 bool a_control_set = false; 57 58 OsclMemoryFragment memFrag; 59 60 while (get_next_line(current_start, end, 61 line_start_ptr, line_end_ptr)) 62 { 63 if ((!alt_def_id && !alt_id) || (alt_def_id) || 64 ((!alt_def_id) && !oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:")))) 65 { 66 if (!alt_def_id && !oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) 67 { 68 line_start_ptr += oscl_strlen("a=alt:"); 69 const char *end1 = line_start_ptr; 70 for (; *end1 != ':'; end1++); 71 uint32 id; 72 if (!PV_atoi(line_start_ptr, 'd' , end1 - line_start_ptr, id)) 73 return SDP_BAD_MEDIA_ALT_ID; 74 if ((int)id != alt_id) 75 { 76 //check if id is already present 77 Oscl_Vector<int, SDPParserAlloc> alt_track = mediaStr->getalternateTrackId(); 78 bool found = false; 79 80 for (int ss = 0; ss < (int)alt_track.size(); ss++) 81 { 82 if (alt_track[ss] == (int)id) 83 found = true; 84 } 85 86 if (!found) 87 mediaStr->setalternateTrackId(id); 88 89 current_start = line_end_ptr; 90 continue; 91 } 92 93 line_start_ptr = end1 + 1; 94 line_start_ptr = skip_whitespace(line_start_ptr, line_end_ptr); 95 96 } 97 98 switch (*line_start_ptr) 99 { 100 case 'm': 101 { 102 if (*(line_start_ptr + 1) != '=') 103 { 104 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format")); 105 return SDP_BAD_MEDIA_FORMAT; 106 } 107 108 // parse through each field 109 const char *sptr, *eptr; 110 111 //line_start_ptr+2 since we need to start looking beyond the '=' sign 112 113 //get the media type (audio, video, application) 114 sptr = skip_whitespace(line_start_ptr + 2, line_end_ptr); 115 if (sptr >= line_end_ptr) 116 { 117 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for media type")); 118 return SDP_BAD_MEDIA_FORMAT; 119 } 120 121 eptr = skip_to_whitespace(sptr, line_end_ptr); 122 if (eptr <= sptr) 123 { 124 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format")); 125 return SDP_BAD_MEDIA_FORMAT; 126 } 127 128 memFrag.ptr = (void*)sptr; 129 memFrag.len = (eptr - sptr); 130 131 mediaStr->setType(memFrag); 132 133 //get the suggested port number 134 sptr = skip_whitespace(eptr, line_end_ptr); 135 if (sptr >= line_end_ptr) 136 { 137 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for suggested port")); 138 return SDP_BAD_MEDIA_FORMAT; 139 } 140 141 eptr = skip_to_whitespace(sptr, line_end_ptr); 142 if (eptr <= sptr) 143 { 144 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format")); 145 return SDP_BAD_MEDIA_FORMAT; 146 } 147 148 uint32 suggestedPort; 149 150 OSCL_HeapString<SDPParserAlloc> restOfLine(sptr, eptr - sptr); 151 const char *slash = oscl_strstr(restOfLine.get_cstr(), "/"); 152 if (slash) 153 { 154 if (PV_atoi(restOfLine.get_cstr(), 'd', (slash - restOfLine.get_cstr()), suggestedPort) == true) 155 { 156 mediaStr->setSuggestedPort(suggestedPort); 157 // There must be number of ports info after the slash 158 uint32 numOfPorts; 159 const char *ports = oscl_strstr(sptr, "/"); 160 ports++; 161 if (ports == NULL) 162 { 163 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for ports info")); 164 return SDP_BAD_MEDIA_FORMAT; 165 } 166 if (PV_atoi(ports, 'd', (eptr - ports), numOfPorts) == true) 167 { 168 mediaStr->setNumOfPorts(numOfPorts); 169 } 170 else 171 { 172 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for ports info")); 173 return SDP_BAD_MEDIA_FORMAT; 174 } 175 } 176 else 177 { 178 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for ports info")); 179 return SDP_BAD_MEDIA_FORMAT; 180 } 181 } 182 else 183 { 184 if (PV_atoi(sptr, 'd', (eptr - sptr), suggestedPort) == true) 185 { 186 mediaStr->setSuggestedPort(suggestedPort); 187 } 188 else 189 { 190 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for ports info")); 191 return SDP_BAD_MEDIA_FORMAT; 192 } 193 } 194 //get the transport profile 195 sptr = skip_whitespace(eptr, line_end_ptr); 196 if (sptr >= line_end_ptr) 197 { 198 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for tranport profile")); 199 return SDP_BAD_MEDIA_FORMAT; 200 } 201 202 eptr = skip_to_whitespace(sptr, line_end_ptr); 203 if (eptr <= sptr) 204 { 205 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for tranport profile")); 206 return SDP_BAD_MEDIA_FORMAT; 207 } 208 209 memFrag.ptr = (void*)sptr; 210 memFrag.len = (eptr - sptr); 211 212 if (oscl_strncmp(sptr, "RTP/AVP", (eptr - sptr)) && oscl_strncmp(sptr, "RTP/AVPF", (eptr - sptr)) && oscl_strncmp(sptr, "RTP/SAVP", (eptr - sptr))) 213 { 214 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for tranport profile")); 215 return SDP_BAD_MEDIA_FORMAT; 216 } 217 else if ((suggestedPort % 2)) // port number should be even 218 { 219 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format - port number is not even")); 220 return SDP_BAD_MEDIA_FORMAT; 221 } 222 223 mediaStr->setTransportProfile(memFrag); 224 225 //get the payload number 226 sptr = skip_whitespace(eptr, line_end_ptr); 227 if (sptr >= line_end_ptr) 228 { 229 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for payload number")); 230 return SDP_BAD_MEDIA_FORMAT; 231 } 232 233 while (eptr < line_end_ptr) 234 { 235 eptr = skip_to_whitespace(sptr, line_end_ptr); 236 if (eptr <= sptr) 237 { 238 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for payload number")); 239 return SDP_BAD_MEDIA_FORMAT; 240 } 241 242 uint32 payloadNumber; ; 243 if (PV_atoi(sptr, 'd', (eptr - sptr), payloadNumber) == true) 244 { 245 // Parse the payload number info only and see if there 246 // is any payload number in static range if yes rtpmap 247 // field may not be present for this 248 for (uint32 ii = 0; ii < mediaStr->getPayloadSpecificInfoVector().size(); ii++) 249 { 250 if (payloadNumber == mediaStr->getPayloadSpecificInfoVector()[ii]->getPayloadNumber()) 251 { 252 // check if (FIRST_STATIC_PAYLOAD <= payloadNumber <= LAST_STATIC_PAYLOAD) 253 // since payloadNumber is unsigned and FIRST_STATIC_PAYLOAD == 0, only the upper 254 // boundary needs to be checked. Adding the lower boundary causes compiler warning. 255 if (payloadNumber <= LAST_STATIC_PAYLOAD) 256 a_rtpmap_found = true; 257 } 258 } 259 } 260 else 261 { 262 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad m= line format for payload number")); 263 return SDP_BAD_MEDIA_FORMAT; 264 } 265 266 sptr = skip_whitespace(eptr, line_end_ptr); 267 eptr = sptr; 268 } 269 // No rtpmap will come if port is 0 in sip sdp 270 if (isSipSdp && suggestedPort == 0) 271 { 272 a_rtpmap_found = true; 273 } 274 275 } 276 break; 277 case 'a': 278 { 279 if (*(line_start_ptr + 1) != '=') 280 { 281 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a= line format - '=' missing")); 282 return SDP_BAD_MEDIA_FORMAT; 283 } 284 285 // parse through each field 286 const char *sptr1, *eptr1; 287 if (!oscl_strncmp(line_start_ptr, "a=rtpmap:", oscl_strlen("a=rtpmap:"))) 288 { 289 //get the payload number 290 sptr1 = line_start_ptr + oscl_strlen("a=rtpmap:"); 291 sptr1 = skip_whitespace(sptr1, line_end_ptr); 292 293 a_rtpmap_found = true; 294 295 if (sptr1 >= line_end_ptr) 296 { 297 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtpmap line format")); 298 return SDP_BAD_MEDIA_RTP_MAP; 299 } 300 eptr1 = skip_to_whitespace(sptr1, line_end_ptr); 301 if (eptr1 <= sptr1) 302 { 303 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtpmap line format")); 304 return SDP_BAD_MEDIA_RTP_MAP; 305 } 306 uint32 payloadNumber; 307 if (PV_atoi(sptr1, 'd', (eptr1 - sptr1), payloadNumber) == true) 308 { 309 int p; 310 if (!mediaStr->lookupPayloadNumber(payloadNumber, p)) 311 { 312 break; 313 } 314 } 315 else 316 { 317 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtpmap line format for payload number")); 318 return SDP_BAD_MEDIA_RTP_MAP; 319 } 320 321 // payloadNumber is present in the mediaInfo. get the payload 322 // Specific pointer corresponding to this payload 323 PayloadSpecificInfoTypeBase* payloadPtr = 324 mediaStr->getPayloadSpecificInfoTypePtr(payloadNumber); 325 if (payloadPtr == NULL) 326 { 327 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Unable to get payload pointer for the payload")); 328 return SDP_PAYLOAD_MISMATCH; 329 } 330 PVMF_SDP_PARSER_LOGINFO((0, "SDPBaseMediaInfoParser::parseMediaInfo - processing payload number : %d", payloadNumber)); 331 332 //get the MIME type and sample rate 333 sptr1 = skip_whitespace(eptr1, line_end_ptr); 334 if (sptr1 >= line_end_ptr) 335 { 336 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtpmap line format for MIME Type & Sample rate")); 337 return SDP_BAD_MEDIA_RTP_MAP; 338 } 339 340 eptr1 = skip_to_whitespace(sptr1, line_end_ptr); 341 if (eptr1 <= sptr1) 342 { 343 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtpmap line format")); 344 return SDP_BAD_MEDIA_RTP_MAP; 345 } 346 //int ii = 0; 347 const char *tmp_end_ptr = NULL; 348 /* 349 for( ii = 0; ii < (eptr1-sptr1); ii++ ) 350 { 351 if(sptr1[ii] == '/') 352 { 353 tmp_end_ptr = sptr1 + ii; 354 break; 355 } 356 } 357 */ 358 const char SDP_FWD_SLASH[] = "/"; 359 tmp_end_ptr = oscl_strstr(sptr1, SDP_FWD_SLASH); 360 if (tmp_end_ptr == NULL) 361 { 362 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtpmap line format - nothing after '/' ")); 363 return SDP_BAD_MEDIA_RTP_MAP; 364 } 365 //The below mentioned code converts the non standard MIME type to standard MIME type. 366 //For eg. earlier we have MIME type "AMR" and according to standard it should be 367 //like "audio/AMR". so tho whole logic implements the same. 368 uint32 tempBufLen = 0; 369 char *tmpBuf = NULL; 370 const char SDP_NULL[] = "\0"; 371 372 tempBufLen = oscl_strlen(mediaStr->getType()) + (tmp_end_ptr - sptr1) + 2; 373 374 // "OSCL_TRY(err, OSCL_ARRAY_NEW(char, tempBufLen)" is in separate function to avoid warnings 375 newTmpBuf(tempBufLen, &tmpBuf); 376 if (NULL == tmpBuf) 377 { 378 return SDP_NO_MEMORY; 379 } 380 381 oscl_strncpy(tmpBuf, mediaStr->getType(), (oscl_strlen(mediaStr->getType()) + 1)); 382 oscl_strcat(tmpBuf, SDP_FWD_SLASH); 383 oscl_strncat(tmpBuf, sptr1, (tmp_end_ptr - sptr1)); 384 oscl_strcat(tmpBuf, SDP_NULL); 385 386 387 memFrag.ptr = (void*)tmpBuf; 388 memFrag.len = oscl_strlen(tmpBuf); 389 390 mediaStr->setMIMEType(memFrag); 391 OSCL_ARRAY_DELETE(tmpBuf); 392 tmpBuf = NULL; 393 //Till here 394 tmp_end_ptr++; 395 if (tmp_end_ptr >= eptr1) 396 { 397 return SDP_BAD_MEDIA_RTP_MAP; 398 } 399 tmp_end_ptr = skip_whitespace(tmp_end_ptr, eptr1); 400 if (tmp_end_ptr >= eptr1) 401 { 402 return SDP_BAD_MEDIA_RTP_MAP; 403 } 404 405 OSCL_HeapString<SDPParserAlloc> restOfLine(tmp_end_ptr, eptr1 - tmp_end_ptr); 406 const char *another_slash = oscl_strstr(restOfLine.get_cstr(), SDP_FWD_SLASH); 407 408 uint32 sampleRate; 409 if (another_slash) 410 { 411 if (PV_atoi(restOfLine.get_cstr(), 'd', (another_slash - restOfLine.get_cstr()), sampleRate) == true) 412 { 413 payloadPtr->setSampleRate(sampleRate); 414 // There must be channel numbers after the 2nd forward slash 415 uint32 channels; 416 tmp_end_ptr = oscl_strstr(tmp_end_ptr, SDP_FWD_SLASH); 417 if (tmp_end_ptr == NULL) 418 { 419 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtpmap line format for channel info")); 420 return SDP_BAD_MEDIA_RTP_MAP; 421 } 422 tmp_end_ptr++; 423 if (PV_atoi(tmp_end_ptr, 'd', (eptr1 - tmp_end_ptr), channels) == true) 424 { 425 payloadPtr->setNoOfChannels(channels); 426 } 427 else 428 { 429 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtpmap line format for channel info")); 430 return SDP_BAD_MEDIA_RTP_MAP; 431 } 432 } 433 else 434 { 435 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtpmap line format for channel info")); 436 return SDP_BAD_MEDIA_RTP_MAP; 437 } 438 } 439 else 440 { 441 if (PV_atoi(tmp_end_ptr, 'd', (eptr1 - tmp_end_ptr), sampleRate) == true) 442 { 443 payloadPtr->setSampleRate(sampleRate); 444 } 445 else 446 { 447 return SDP_BAD_MEDIA_RTP_MAP; 448 } 449 } 450 } 451 if (!oscl_strncmp(line_start_ptr, "a=control:", oscl_strlen("a=control:"))) 452 { 453 sptr1 = line_start_ptr + oscl_strlen("a=control:"); 454 sptr1 = skip_whitespace(sptr1, line_end_ptr); 455 a_control_found = true; 456 if (sptr1 >= line_end_ptr) 457 { 458 return SDP_BAD_MEDIA_CONTROL_FIELD; 459 } 460 461 memFrag.ptr = (void*)sptr1; 462 memFrag.len = (line_end_ptr - sptr1); 463 mediaStr->setControlURL(memFrag); 464 465 for (int ii = 0; ii < (line_end_ptr - sptr1); ii++) 466 { 467 if (sptr1[ii] == '=') 468 { 469 uint32 trackID; 470 sptr1 = skip_whitespace((sptr1 + ii + 1), line_end_ptr); 471 if (sptr1 >= line_end_ptr) 472 { 473 break; 474 } 475 476 if ((PV_atoi(sptr1, 'd', 1, trackID) == true)) 477 { 478 mediaStr->setControlTrackID(trackID); 479 } 480 break; 481 } 482 } 483 } 484 if (!oscl_strncmp(line_start_ptr, "a=range:", oscl_strlen("a=range:"))) 485 { 486 sptr1 = line_start_ptr + oscl_strlen("a=range:"); 487 sptr1 = skip_whitespace(sptr1, line_end_ptr); 488 489 a_range_found = true; 490 491 if (sptr1 >= line_end_ptr) 492 { 493 return SDP_BAD_MEDIA_RANGE_FIELD; 494 } 495 parseRtspRange(sptr1, line_end_ptr - sptr1, *(mediaStr->getRtspRange())); 496 } 497 if (!oscl_strncmp(line_start_ptr, "a=depends_on:", oscl_strlen("a=depends_on:"))) 498 { 499 sptr1 = line_start_ptr + oscl_strlen("a=depends_on:"); 500 memFrag.ptr = (void*)sptr1; 501 memFrag.len = (line_end_ptr - sptr1); 502 mediaStr->setDependsonURL(memFrag); 503 504 for (int ii = 0; ii < (line_end_ptr - sptr1); ii++) 505 { 506 if (sptr1[ii] == '=') 507 { 508 uint32 trackID; 509 sptr1 = skip_whitespace((sptr1 + ii + 1), line_end_ptr); 510 if (sptr1 >= line_end_ptr) 511 { 512 break; 513 } 514 515 if ((PV_atoi(sptr1, 'd', 1, trackID) == true)) 516 { 517 mediaStr->setDependsOnTrackID(trackID); 518 } 519 break; 520 } 521 } 522 } 523 524 //Random access denied added for 3rd party content random positioning - 01/08/02 525 StrPtrLen random_access("a=random_access_denied"); 526 if (!oscl_strncmp(line_start_ptr, random_access.c_str(), random_access.length())) 527 { 528 mediaStr->setRandomAccessDenied(true); 529 } 530 531 StrPtrLen qoe_metrics("a=3GPP-QoE-Metrics:"); 532 if (!oscl_strncmp(line_start_ptr, qoe_metrics.c_str(), qoe_metrics.length())) 533 { 534 const char *sptr; 535 sptr = line_start_ptr + qoe_metrics.length(); 536 QoEMetricsType qMetrics; 537 oscl_memset(qMetrics.name, 0, 7); 538 qMetrics.rateFmt = QoEMetricsType::VAL; 539 qMetrics.rateVal = 0; 540 qMetrics.paramFmt = QoEMetricsType::IDIGIT; 541 qMetrics.paramExtIdigit = 0; 542 543 if (!parseQoEMetrics(sptr, line_end_ptr, qMetrics)) 544 { 545 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=3GPP-QoE-Metrics: line format")); 546 return SDP_BAD_MEDIA_FORMAT; 547 } 548 mediaStr->setQoEMetrics(qMetrics); 549 550 551 } 552 StrPtrLen predec("a=X-predecbufsize:"); 553 if (!oscl_strncmp(line_start_ptr, predec.c_str(), predec.length())) 554 { 555 const char *sptr; 556 sptr = line_start_ptr + predec.length(); 557 uint32 size; 558 if (!PV_atoi(sptr, 'd', (line_end_ptr - sptr), size)) 559 { 560 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=X-predecbufsize: line format")); 561 return SDP_BAD_MEDIA_FORMAT; 562 } 563 mediaStr->setPreDecBuffSize(size); 564 } 565 566 StrPtrLen initpredec("a=X-initpredecbufperiod:"); 567 if (!oscl_strncmp(line_start_ptr, initpredec.c_str(), initpredec.length())) 568 { 569 const char *sptr; 570 sptr = line_start_ptr + initpredec.length(); 571 uint32 period; 572 if (!PV_atoi(sptr, 'd', (line_end_ptr - sptr), period)) 573 { 574 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=X-initpredecbufperiod: line format")); 575 return SDP_BAD_MEDIA_FORMAT; 576 } 577 mediaStr->setInitPreDecBuffPeriod(period); 578 } 579 580 StrPtrLen initpostdec("a=X-initpostdecbufperiod:"); 581 if (!oscl_strncmp(line_start_ptr, initpostdec.c_str(), initpostdec.length())) 582 { 583 const char *sptr; 584 sptr = line_start_ptr + initpostdec.length(); 585 uint32 period; 586 if (!PV_atoi(sptr, 'd', (line_end_ptr - sptr), period)) 587 { 588 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=X-initpostdecbufperiod: line format")); 589 return SDP_BAD_MEDIA_FORMAT; 590 } 591 mediaStr->setInitPostDecBuffPeriod(period); 592 } 593 594 StrPtrLen decbyterate("a=X-decbyterate:"); 595 if (!oscl_strncmp(line_start_ptr, decbyterate.c_str(), 596 decbyterate.length())) 597 { 598 const char *sptr; 599 sptr = line_start_ptr + decbyterate.length(); 600 uint32 rate; 601 if (!PV_atoi(sptr, 'd', (line_end_ptr - sptr), rate)) 602 { 603 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=X-decbyterate: line format")); 604 return SDP_BAD_MEDIA_FORMAT; 605 } 606 mediaStr->setDecByteRate(rate); 607 } 608 609 StrPtrLen adapt_supp("a=3GPP-Adaptation-Support:"); 610 if (!oscl_strncmp(line_start_ptr, adapt_supp.c_str(), 611 adapt_supp.length())) 612 { 613 const char *sptr = line_start_ptr + adapt_supp.length(); 614 sptr = skip_whitespace_and_line_term(sptr, line_end_ptr); 615 uint32 frequency; 616 if (!PV_atoi(sptr, 'd', line_end_ptr - sptr, frequency)) 617 { 618 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=3GPP-Adaptation-Support: line format - frequency not correct")); 619 return SDP_BAD_MEDIA_FORMAT; 620 } 621 mediaStr->setReportFrequency(frequency); 622 } 623 624 StrPtrLen asset_info("a=3GPP-Asset-Information:"); 625 if (!oscl_strncmp(line_start_ptr, asset_info.c_str(), 626 asset_info.length())) 627 { 628 const char *sptr = line_start_ptr + asset_info.length(); 629 AssetInfoType assetInfo; 630 if (!parseAssetInfo(sptr, line_end_ptr, assetInfo)) 631 { 632 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=3GPP-Asset-Information: line format")); 633 return SDP_BAD_SESSION_FORMAT; 634 } 635 636 mediaStr->setAssetInfo(assetInfo); 637 638 } 639 StrPtrLen srtp("a=3GPP-SRTP-Config:"); 640 if (!oscl_strncmp(line_start_ptr, srtp.c_str(), 641 srtp.length())) 642 { 643 const char *sptr = line_start_ptr + srtp.length(); 644 const char *eptr; 645 sptr = skip_whitespace(sptr, line_end_ptr); 646 eptr = skip_to_whitespace(sptr, line_end_ptr); 647 memFrag.ptr = (void *)sptr; 648 memFrag.len = eptr - sptr; 649 650 mediaStr->setSRTPintg_nonce(memFrag); 651 652 eptr = eptr + 1; 653 sptr = eptr; 654 if (sptr >= line_end_ptr) 655 { 656 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=3GPP-SRTP-Config: line format")); 657 return SDP_BAD_MEDIA_FORMAT; 658 } 659 eptr = skip_to_whitespace(eptr, line_end_ptr); 660 if (eptr >= line_end_ptr) 661 { 662 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=3GPP-SRTP-Config: line format")); 663 return SDP_BAD_MEDIA_FORMAT; 664 } 665 666 memFrag.ptr = (void *)sptr; 667 memFrag.len = eptr - sptr; 668 mediaStr->setSRTPkey_salt(memFrag); 669 670 eptr = eptr + 1; 671 sptr = eptr; 672 673 if (!oscl_strncmp(sptr, "auth-tag-len=", oscl_strlen("auth-tag-len="))) 674 { 675 sptr = sptr + oscl_strlen("auth-tag-len="); 676 uint32 length; 677 if (!PV_atoi(sptr, 'd', 2, length)) 678 { 679 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=3GPP-SRTP-Config: line format for auth-tag-len= field")); 680 return SDP_BAD_MEDIA_FORMAT; 681 } 682 if ((length != 32) && (length != 80)) 683 { 684 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=3GPP-SRTP-Config: line format for auth-tag-len= field")); 685 return SDP_BAD_MEDIA_FORMAT; 686 } 687 else 688 mediaStr->setSRTPauth_tag_len(length); 689 690 } 691 else 692 { 693 memFrag.ptr = (void *)sptr; 694 memFrag.len = line_end_ptr - sptr; 695 696 mediaStr->setSRTPparam_ext(memFrag); 697 698 699 } 700 701 702 } 703 StrPtrLen rtcp_fb("a=rtcp-fb:"); 704 if (!oscl_strncmp(line_start_ptr, rtcp_fb.c_str(), rtcp_fb.length())) 705 { 706 const char *sptr = line_start_ptr + rtcp_fb.length(); 707 const char *eptr = skip_to_whitespace(sptr, line_end_ptr); 708 709 if (eptr >= line_end_ptr) 710 { 711 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtcp-fb: line format")); 712 return SDP_BAD_MEDIA_FORMAT; 713 } 714 715 memFrag.ptr = (void *)sptr; 716 memFrag.len = eptr - sptr; 717 mediaStr->setrtcp_fb_pt(memFrag); 718 719 sptr = skip_whitespace(eptr, line_end_ptr); 720 eptr = skip_to_whitespace(sptr, line_end_ptr); 721 722 memFrag.ptr = (void *)sptr; 723 memFrag.len = eptr - sptr; 724 mediaStr->setrtcp_fb_val(memFrag); 725 726 if (eptr >= line_end_ptr) 727 break; 728 729 if (!oscl_strncmp(sptr, "trr-int", eptr - sptr)) 730 { 731 sptr = skip_whitespace(eptr, line_end_ptr); 732 eptr = skip_to_line_term(sptr, line_end_ptr); 733 uint32 trr; 734 if (!PV_atoi(sptr, 'd', eptr - sptr, trr)) 735 { 736 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=rtcp-fb: line format for trr-int field")); 737 return SDP_BAD_MEDIA_FORMAT; 738 } 739 740 mediaStr->setrtcp_fb_trr_val(trr); 741 } 742 else 743 { 744 sptr = skip_whitespace(eptr, line_end_ptr); 745 eptr = skip_to_line_term(sptr, line_end_ptr); 746 memFrag.ptr = (void *)sptr; 747 memFrag.len = eptr - sptr; 748 mediaStr->setrtcp_fb_val_param(memFrag); 749 750 } 751 752 753 } 754 if (!oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) 755 { 756 line_start_ptr += oscl_strlen("a=alt:"); 757 const char *end1 = line_start_ptr; 758 for (; *end1 != ':'; end1++); 759 uint32 id; 760 if (!PV_atoi(line_start_ptr, 'd' , end1 - line_start_ptr, id)) 761 { 762 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad ID in a=alt: line format")); 763 return SDP_BAD_MEDIA_ALT_ID; 764 } 765 766 //check if id is already present 767 Oscl_Vector<int, SDPParserAlloc> alt_track = mediaStr->getalternateTrackId(); 768 bool found = false; 769 for (int ss = 0; ss < (int)alt_track.size(); ss++) 770 { 771 if (alt_track[ss] == (int)id) 772 found = true; 773 } 774 if (!found) 775 mediaStr->setalternateTrackId(id); 776 } 777 if (!oscl_strncmp(line_start_ptr, "a=maxprate:", oscl_strlen("a=maxprate:"))) 778 { 779 line_start_ptr += oscl_strlen("a=maxprate:"); 780 OsclFloat rate; 781 if (!PV_atof(line_start_ptr, line_end_ptr - line_start_ptr, rate)) 782 { 783 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad a=maxprate: line format for rate field")); 784 return SDP_BAD_MEDIA_FORMAT; 785 } 786 mediaStr->setMaxprate(rate); 787 } 788 if (!oscl_strncmp(line_start_ptr, "a=X-allowrecord", oscl_strlen("a=X-allowrecord"))) 789 { 790 mediaStr->setAllowRecord(true); 791 } 792 793 } 794 break; 795 case 'b': 796 { 797 if (!oscl_strncmp(line_start_ptr, "b=AS:", oscl_strlen("b=AS:"))) 798 { 799 const char *sptr; 800 sptr = line_start_ptr + oscl_strlen("b=AS:"); 801 sptr = skip_whitespace(sptr, line_end_ptr); 802 if (sptr >= line_end_ptr) 803 { 804 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad b=AS: line format")); 805 return SDP_BAD_MEDIA_FORMAT; 806 } 807 808 uint32 bitRate; 809 if (PV_atoi(sptr, 'd', (line_end_ptr - sptr), bitRate) == true) 810 { 811 mediaStr->setBitrate(1000*bitRate); 812 } 813 else 814 { 815 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad b=AS: line format - bitrate incorrect")); 816 return SDP_BAD_MEDIA_FORMAT; 817 } 818 } 819 else if (!oscl_strncmp(line_start_ptr, "b=RS:", oscl_strlen("b=RS:"))) 820 { 821 const char *sptr; 822 sptr = line_start_ptr + oscl_strlen("b=AS:"); 823 sptr = skip_whitespace(sptr, line_end_ptr); 824 if (sptr >= line_end_ptr) 825 { 826 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad b=RS: line format")); 827 return SDP_BAD_MEDIA_FORMAT; 828 } 829 830 uint32 rtcpBWSender; 831 if (PV_atoi(sptr, 'd', (line_end_ptr - sptr), rtcpBWSender) == true) 832 { 833 mediaStr->setRTCPSenderBitRate(rtcpBWSender); 834 } 835 else 836 { 837 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad b=RS: line format - Sender Bitrate incorrect")); 838 return SDP_BAD_MEDIA_FORMAT; 839 } 840 } 841 else if (!oscl_strncmp(line_start_ptr, "b=RR:", oscl_strlen("b=RR:"))) 842 { 843 const char *sptr; 844 sptr = line_start_ptr + oscl_strlen("b=AS:"); 845 sptr = skip_whitespace(sptr, line_end_ptr); 846 if (sptr >= line_end_ptr) 847 { 848 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad b=RR: line format")); 849 return SDP_BAD_MEDIA_FORMAT; 850 } 851 852 uint32 rtcpBWReceiver; 853 if (PV_atoi(sptr, 'd', (line_end_ptr - sptr), rtcpBWReceiver) == true) 854 { 855 mediaStr->setRTCPReceiverBitRate(rtcpBWReceiver); 856 } 857 else 858 { 859 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad b=RR: line format - Receiver Bit rate incorrect")); 860 return SDP_BAD_MEDIA_FORMAT; 861 } 862 } 863 else if (!oscl_strncmp(line_start_ptr, "b=TIAS:", oscl_strlen("b=TIAS:"))) 864 { 865 const char *sptr; 866 sptr = line_start_ptr + oscl_strlen("b=TIAS:"); 867 sptr = skip_whitespace(sptr, line_end_ptr); 868 if (sptr >= line_end_ptr) 869 { 870 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad b=T1AS: line format")); 871 return SDP_BAD_MEDIA_FORMAT; 872 } 873 874 uint32 bMod; 875 if (PV_atoi(sptr, 'd', (line_end_ptr - sptr), bMod) == true) 876 { 877 mediaStr->setBWtias(1000 * bMod); 878 } 879 else 880 { 881 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad b=T1AS: line format - bMod incorrect")); 882 return SDP_BAD_MEDIA_FORMAT; 883 } 884 } 885 } 886 break; 887 case 'u': 888 { 889 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - u field not supported")); 890 return SDP_BAD_MEDIA_FORMAT; 891 } 892 case 'c': 893 { 894 if (*(line_start_ptr + 1) != '=') 895 { 896 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format - '=' missing after c")); 897 return SDP_BAD_SESSION_FORMAT; 898 } 899 900 mediaStr->setCFieldStatus(true); 901 902 // parse through each field 903 const char *sptr, *eptr; 904 905 // get the connection network type 906 sptr = skip_whitespace(line_start_ptr + 2, line_end_ptr); 907 if (sptr >= line_end_ptr) 908 { 909 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format - connection network type missing")); 910 return SDP_BAD_SESSION_FORMAT; 911 } 912 913 eptr = skip_to_whitespace(sptr, line_end_ptr); 914 if (eptr <= sptr) 915 { 916 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format - part after connection network type missing")); 917 return SDP_BAD_SESSION_FORMAT; 918 } 919 920 memFrag.ptr = (void*)sptr; 921 memFrag.len = (eptr - sptr); 922 mediaStr->setCNetworkType(memFrag); 923 924 // get the address type 925 sptr = skip_whitespace(eptr, line_end_ptr); 926 if (sptr >= line_end_ptr) 927 { 928 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format - address type missing")); 929 return SDP_BAD_SESSION_FORMAT; 930 } 931 932 eptr = skip_to_whitespace(sptr, line_end_ptr); 933 if (eptr <= sptr) 934 { 935 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format - part after address type missing")); 936 return SDP_BAD_SESSION_FORMAT; 937 } 938 memFrag.ptr = (void*)sptr; 939 memFrag.len = (eptr - sptr); 940 mediaStr->setCAddressType(memFrag); 941 942 // get the address 943 sptr = skip_whitespace(eptr, line_end_ptr); 944 if (sptr >= line_end_ptr) 945 { 946 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format - address missing")); 947 return SDP_BAD_SESSION_FORMAT; 948 } 949 950 eptr = skip_to_whitespace(sptr, line_end_ptr); 951 if (eptr < sptr) 952 { 953 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format - part after address missing")); 954 return SDP_BAD_SESSION_FORMAT; 955 } 956 memFrag.ptr = (void*)sptr; 957 memFrag.len = (eptr - sptr); 958 mediaStr->setCAddress(memFrag); 959 uint32 len = OSCL_MIN((uint32)(eptr - sptr), oscl_strlen("IP4")); 960 if (oscl_strncmp(sptr, "IP4", len) == 0) 961 { 962 uint32 address; 963 const char *addrend = sptr; 964 for (; *addrend != '.'; ++addrend); 965 966 if (!PV_atoi(sptr, 'd', addrend - sptr, address)) 967 { 968 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format")); 969 return SDP_BAD_SESSION_FORMAT; 970 } 971 972 if (address >= 224 && address <= 239) //multicast address look for TTL 973 { 974 for (; (*sptr != '/') && (sptr < eptr); ++sptr); 975 if (sptr == eptr) 976 { 977 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format")); 978 return SDP_BAD_SESSION_FORMAT; // no TTL found in multicast address. 979 } 980 else 981 { 982 uint32 ttl; 983 sptr = sptr + 1; 984 if (!PV_atoi(sptr, 'd', eptr - sptr, ttl)) 985 { 986 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format")); 987 return SDP_BAD_SESSION_FORMAT; 988 } 989 if (!(ttl <= 255)) 990 { 991 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format")); 992 return SDP_BAD_SESSION_FORMAT; // ttl out of range. 993 } 994 995 } 996 997 } 998 else // unicast address 999 { 1000 for (; (*sptr != '/') && (sptr < eptr); ++sptr); 1001 if (!oscl_strncmp(sptr, "/", 1)) 1002 { 1003 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format")); 1004 return SDP_BAD_SESSION_FORMAT; //unicast address can not have TTL. 1005 } 1006 } 1007 1008 if (eptr < line_end_ptr) 1009 { 1010 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad c= line format")); 1011 return SDP_BAD_SESSION_FORMAT; 1012 } 1013 } 1014 //use "len" here since "IP4" and "IP6" have same lengths 1015 else if (oscl_strncmp(sptr, "IP6", len) == 0) 1016 { 1017 //TBD 1018 } 1019 break; 1020 } 1021 1022 default: 1023 { 1024 //skip a line we don't understand 1025 } 1026 break; 1027 } 1028 } 1029 current_start = line_end_ptr; 1030 } 1031 1032 mediaStr->setmediaTrackId(alt_id); 1033 1034 if (!alt_def_id && alt_id) 1035 { 1036 uint32 defaultId; 1037 getAltDefaultId(buff, buff + index, defaultId); 1038 if (defaultId != 0) 1039 mediaStr->setalternateTrackId(defaultId); 1040 else 1041 return SDP_BAD_MEDIA_ALT_ID; 1042 } 1043 1044 if (!a_control_found) 1045 { 1046 uint32 addr; 1047 connectionInfo ci; 1048 mediaStr->getConnectionInformation(&ci); 1049 PV_atoi(ci.connectionAddress.get_cstr(), 'd', addr); 1050 //224.0.0.0 through 239.255.255.255 represent class D network addresses 1051 //reserved for multicasting, which indicate a DVB connection 1052 if (addr >= 224 && addr <= 239) 1053 { 1054 uint32 id = mediaStr->getMediaInfoID(); 1055 mediaStr->setControlTrackID(id); 1056 a_control_set = true; 1057 } 1058 } 1059 1060 /* 1061 * cannot assume that range is always going to be set at media level 1062 */ 1063 if ((isSipSdp && a_rtpmap_found) || (!alt_def_id && alt_id)) 1064 return SDP_SUCCESS; 1065 else if ((a_rtpmap_found && a_control_found) || (!alt_def_id && alt_id) || (a_control_set)) 1066 return SDP_SUCCESS; 1067 else 1068 { 1069 PVMF_SDP_PARSER_LOGERROR((0, "SDPBaseMediaInfoParser::parseMediaInfo - Bad Media - no rtpmap and control present")); 1070 return SDP_BAD_MEDIA_FORMAT; 1071 } 1072 } 1073 1074 1075 SDP_ERROR_CODE SDPBaseMediaInfoParser::getAltDefaultId(const char* start, const char *end, uint32 &defaultId) 1076 { 1077 const char *current_start = start; 1078 const char *line_start_ptr, *line_end_ptr; 1079 defaultId = 0; 1080 while (get_next_line(current_start, end, 1081 line_start_ptr, line_end_ptr)) 1082 { 1083 switch (*line_start_ptr) 1084 { 1085 case 'a': 1086 { 1087 if (!oscl_strncmp(line_start_ptr, "a=alt-default-id:", oscl_strlen("a=alt-default-id:"))) 1088 { 1089 line_start_ptr += oscl_strlen("a=alt-default-id:"); 1090 1091 if (!PV_atoi(line_start_ptr, 'd', line_end_ptr - line_start_ptr, defaultId)) 1092 return SDP_BAD_MEDIA_ALT_ID; 1093 else 1094 return SDP_SUCCESS; 1095 1096 } 1097 } 1098 break; 1099 default: 1100 break; 1101 1102 } 1103 1104 current_start = line_end_ptr; 1105 } 1106 1107 return SDP_SUCCESS; 1108 } 1109 1110 SDP_ERROR_CODE SDPBaseMediaInfoParser::setDependentMediaId(const char *start, int length, mediaInfo *mediaPtr, int mediaId) 1111 { 1112 const char *startPtr = start; 1113 const char *endLine = start + length; 1114 1115 while (startPtr < endLine) 1116 { 1117 for (; *startPtr != '='; ++startPtr); 1118 startPtr = startPtr + 1; 1119 if (startPtr > endLine) 1120 return SDP_BAD_MEDIA_ALT_ID; 1121 const char *endPtr = startPtr; 1122 for (; (*endPtr != ';') && (endPtr != endLine); ++endPtr); 1123 1124 if (endPtr > endLine) 1125 return SDP_BAD_MEDIA_ALT_ID; 1126 1127 if (lookForMediaId(startPtr, endPtr, mediaId)) 1128 { 1129 while (startPtr < endPtr) 1130 { 1131 const char *end = startPtr; 1132 for (; (*end != ',') && (end < endPtr) ; ++end); 1133 uint32 id; 1134 if (!PV_atoi(startPtr, 'd', end - startPtr, id)) 1135 return SDP_BAD_MEDIA_ALT_ID; 1136 if ((int)id != mediaId) 1137 mediaPtr->setdependentTrackId(id); 1138 startPtr = end + 1; 1139 } 1140 } 1141 else 1142 startPtr = endPtr + 1; 1143 } 1144 1145 return SDP_SUCCESS; 1146 1147 } 1148 1149 bool SDPBaseMediaInfoParser::lookForMediaId(const char *startPtr, const char* endPtr, int mediaId) 1150 { 1151 const char *end = startPtr; 1152 1153 while (startPtr < endPtr) 1154 { 1155 for (; (*end != ',') && (end < endPtr); ++end); 1156 uint32 id; 1157 PV_atoi(startPtr, 'd' , end - startPtr, id); 1158 if ((int)id == mediaId) 1159 return true; 1160 end = end + 1; 1161 startPtr = end; 1162 } 1163 1164 return false; 1165 } 1166 1167