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 "oscl_mem_basic_functions.h" 19 #include "oscl_snprintf.h" 20 #include "oscl_string_utils.h" 21 #include "oscl_str_ptr_len.h" 22 #include "oscl_string.h" 23 #include "rtsp_time_formats.h" 24 #include "rtsp_range_utils.h" 25 26 27 #include "oscl_dll.h" 28 OSCL_DLL_ENTRY_POINT_DEFAULT() 29 30 31 // don't make the max int size less than 6 -- it is 32 // used to size certain arrays below that need at least 6 characters 33 static const int MAX_RANGE_INT_SIZE = 10; 34 35 // keep the next two constants in sync. The max range float 36 // size should be the number of digits plus the decimal point 37 static const int MAX_RANGE_FLOAT_SIZE = 7; 38 static const char RANGE_FLOAT_FORMAT[] = "%0.6f"; 39 40 OSCL_EXPORT_REF const char * parse_range_integer(const char *start, const char *end, 41 int max_digits, char *sep, uint32& value) 42 { 43 const char *sptr, *eptr; 44 const char *endpoint; 45 46 if (max_digits > 0 && ((end - start) > max_digits)) 47 { 48 endpoint = start + max_digits; 49 } 50 else 51 { 52 endpoint = end; 53 } 54 55 sptr = start; 56 57 if (sep) 58 { 59 for (eptr = sptr; eptr < endpoint && 60 *eptr != *sep ; ++eptr); 61 } 62 else 63 { 64 eptr = endpoint; 65 } 66 67 // get the hours 68 uint32 tmp; 69 if (PV_atoi(sptr, 'd', eptr - sptr, tmp) == false) 70 { 71 return NULL; 72 } 73 74 value = tmp; 75 return eptr; 76 77 } 78 79 OSCL_EXPORT_REF bool parse_smpte_format(const char* start_ptr, const char *end_ptr, 80 RtspRangeType::RtspRangeFormat format, 81 SmpteTimeFormat& smpte_range) 82 { 83 84 // get required HH:MM:SS values 85 const char *sptr; 86 87 sptr = start_ptr; 88 uint32 tmp; 89 char sep; 90 91 sep = ':'; 92 sptr = parse_range_integer(sptr, end_ptr, 93 2, &sep, tmp); 94 95 if (!sptr || *sptr != ':') 96 { 97 return false; 98 } 99 100 smpte_range.hours = (uint8)tmp; 101 102 // get the minutes 103 sptr = parse_range_integer(sptr + 1, end_ptr, 104 2, &sep, tmp); 105 106 if (!sptr || *sptr != ':') 107 { 108 return false; 109 } 110 111 if (tmp > 59) 112 { 113 return false; 114 } 115 116 smpte_range.minutes = (uint8)tmp; 117 118 // get the seconds 119 sptr = parse_range_integer(sptr + 1, end_ptr, 120 2, &sep, tmp); 121 122 if (!sptr) 123 { 124 return false; 125 } 126 127 if (tmp > 59) 128 { 129 return false; 130 } 131 132 smpte_range.seconds = (uint8)tmp; 133 134 // now see if there there are any optional fields 135 if (*sptr == ':') 136 { 137 // get the number of frames 138 sep = '.'; 139 sptr = parse_range_integer(sptr + 1, end_ptr, 140 2, &sep, tmp); 141 142 if (!sptr) 143 { 144 return false; 145 } 146 147 if (format == RtspRangeType::SMPTE_25_RANGE && 148 tmp > 25) 149 { 150 return false; 151 } 152 else if (tmp > 30) 153 { 154 return false; 155 } 156 157 smpte_range.frames = (uint8)tmp; 158 159 // now check for optional subframes 160 if (*sptr == '.') 161 { 162 // get the number of subframes 163 sptr = parse_range_integer(sptr + 1, end_ptr, 164 2, NULL, tmp); 165 166 if (!sptr) 167 { 168 return false; 169 } 170 171 if (tmp > 99) 172 { 173 return false; 174 } 175 176 smpte_range.subframes = (uint8)tmp; 177 } 178 else 179 { 180 smpte_range.subframes = 0; 181 } 182 183 } 184 else 185 { 186 smpte_range.frames = 0; 187 smpte_range.subframes = 0; 188 } 189 190 return true; 191 } 192 193 OSCL_EXPORT_REF bool parse_npt_format(const char* start_ptr, const char *end_ptr, 194 NptTimeFormat& npt_range) 195 { 196 197 // get required HH:MM:SS values 198 const char *sptr, *eptr; 199 uint32 tmp; 200 201 sptr = start_ptr; 202 203 StrPtrLen now_str("now"); 204 if (!oscl_strncmp(sptr, now_str.c_str(), now_str.length())) 205 { 206 // this is the "now" keyword 207 npt_range.npt_format = NptTimeFormat::NOW; 208 return true; 209 } 210 211 // see if the format contains a ':' separator character 212 for (eptr = sptr; eptr < end_ptr && *eptr != ':'; ++eptr); 213 214 if (*eptr == ':') 215 { 216 // this is the npt-hhmmss format 217 218 char sep = ':'; 219 // get the number of hours 220 sptr = parse_range_integer(sptr, eptr, 221 0, &sep, tmp); 222 223 if (!sptr) 224 { 225 return false; 226 } 227 228 npt_range.npt_format = NptTimeFormat::NPT_HHMMSS; 229 npt_range.npt_hhmmss.hours = tmp; 230 231 232 // get the number of minutes 233 sptr = parse_range_integer(sptr + 1, end_ptr, 234 2, &sep, tmp); 235 236 if (!sptr || *sptr != ':') 237 { 238 return false; 239 } 240 241 if (tmp > 59) 242 { 243 return false; 244 } 245 246 npt_range.npt_hhmmss.min = (uint8)tmp; 247 248 249 sep = '.'; 250 // get the number of seconds 251 sptr = parse_range_integer(sptr + 1, end_ptr, 252 2, &sep, tmp); 253 254 if (!sptr) 255 { 256 return false; 257 } 258 259 if (tmp > 59) 260 { 261 return false; 262 } 263 264 npt_range.npt_hhmmss.sec = (uint8)tmp; 265 266 npt_range.npt_hhmmss.frac_sec = 0; 267 // determine if the fractional seconds exists 268 if (*sptr == '.') 269 { 270 // get the fractional seconds 271 const int MAX_TMP_BUFSIZE = 12; 272 char tmpbuf[MAX_TMP_BUFSIZE]; 273 int copy_size; 274 275 eptr = skip_to_whitespace(sptr, end_ptr); 276 277 copy_size = eptr - sptr; 278 if (copy_size > MAX_TMP_BUFSIZE - 1) 279 { 280 copy_size = MAX_TMP_BUFSIZE - 1; 281 } 282 283 oscl_strncpy(tmpbuf, sptr, copy_size); 284 285 tmpbuf[copy_size] = '\0'; 286 287 if (!PV_atof(tmpbuf, npt_range.npt_hhmmss.frac_sec)) 288 return false; 289 290 } 291 292 } // end if the format is NPT_HHMMSS 293 294 else 295 { 296 297 char sep = '.'; 298 // this is the NPT_SEC format 299 npt_range.npt_format = NptTimeFormat::NPT_SEC; 300 301 // get the number of seconds 302 sptr = parse_range_integer(sptr, eptr, 303 0, &sep, tmp); 304 305 if (!sptr) 306 { 307 return false; 308 } 309 310 npt_range.npt_sec.sec = tmp; 311 312 npt_range.npt_sec.milli_sec = 0; 313 if (*sptr == '.') 314 { 315 // there is an optional fractional seconds field 316 317 // get the fractional seconds 318 const int MAX_TMP_BUFSIZE = 12; 319 char tmpbuf[MAX_TMP_BUFSIZE]; 320 int copy_size; 321 322 eptr = skip_to_whitespace(sptr, end_ptr); 323 324 copy_size = eptr - sptr; 325 326 if (copy_size > MAX_TMP_BUFSIZE - 1) 327 { 328 copy_size = MAX_TMP_BUFSIZE - 1; 329 } 330 331 oscl_strncpy(tmpbuf, sptr, copy_size); 332 333 334 tmpbuf[copy_size] = '\0'; 335 336 OsclFloat tmp_fnum; 337 if (!PV_atof(tmpbuf, tmp_fnum)) 338 return false; 339 npt_range.npt_sec.milli_sec = (uint32)(1000.0 * tmp_fnum + 0.5); 340 } 341 342 } // end if the format is NPT_SEC 343 344 return true; 345 } 346 347 348 OSCL_EXPORT_REF bool parse_abs_format(const char* start_ptr, const char *end_ptr, 349 AbsTimeFormat& abs_range) 350 { 351 352 // get format YYYYMMDDT 353 const char *sptr, *eptr; 354 char sep; 355 uint32 tmp; 356 357 sptr = start_ptr; 358 359 // check if the ninth character is a "T" 360 eptr = sptr + 8; 361 362 sep = 'T'; 363 if (eptr >= end_ptr || *eptr != sep) 364 { 365 return false; 366 } 367 368 sptr = parse_range_integer(sptr, eptr, 369 4, &sep, tmp); 370 371 if (! sptr || tmp > 9999) 372 { 373 return false; 374 } 375 376 abs_range.year = (uint16)tmp; 377 378 // get the month 379 sptr = parse_range_integer(sptr, eptr, 380 2, &sep, tmp); 381 382 if (! sptr || tmp == 0 || tmp > 12) 383 { 384 return false; 385 } 386 387 abs_range.month = (uint8)tmp; 388 389 // get the day 390 sptr = parse_range_integer(sptr, eptr, 391 2, &sep, tmp); 392 393 if (! sptr || tmp == 0 || tmp > 31) 394 { 395 return false; 396 } 397 398 abs_range.day = (uint8)tmp; 399 400 401 sptr = eptr + 1; 402 eptr = sptr + 6; 403 404 if (eptr >= end_ptr || (*eptr != 'Z' && *eptr != '.')) 405 { 406 return false; 407 } 408 409 // get the hours 410 sptr = parse_range_integer(sptr, eptr, 411 2, NULL, tmp); 412 413 if (! sptr || tmp > 23) 414 { 415 return false; 416 } 417 418 abs_range.hours = (uint8)tmp; 419 420 // get the minutes 421 sptr = parse_range_integer(sptr, eptr, 422 2, NULL, tmp); 423 424 if (! sptr || tmp > 59) 425 { 426 return false; 427 } 428 429 abs_range.min = (uint8)tmp; 430 431 // get the number of seconds 432 sptr = parse_range_integer(sptr, eptr, 433 2, NULL, tmp); 434 435 if (! sptr || tmp > 59) 436 { 437 return false; 438 } 439 440 abs_range.sec = (uint8)tmp; 441 442 abs_range.frac_sec = 0; 443 444 if (*eptr == '.') 445 { 446 // get the fractional seconds 447 // get the fractional seconds 448 const int MAX_TMP_BUFSIZE = 12; 449 char tmpbuf[MAX_TMP_BUFSIZE]; 450 int copy_size; 451 452 sptr = eptr; 453 454 for (eptr = sptr; eptr < end_ptr && *eptr != 'Z'; 455 ++eptr); 456 457 if (*eptr != 'Z') 458 { 459 return false; 460 } 461 462 copy_size = eptr - sptr; 463 if (copy_size > MAX_TMP_BUFSIZE - 1) 464 { 465 copy_size = MAX_TMP_BUFSIZE - 1; 466 } 467 468 oscl_strncpy(tmpbuf, sptr, copy_size); 469 470 tmpbuf[copy_size] = '\0'; 471 472 if (!PV_atof(tmpbuf, abs_range.frac_sec)) 473 return false; 474 475 } 476 477 return true; 478 } 479 480 481 OSCL_EXPORT_REF bool parseRtspRange(const char *rangeString, int length, RtspRangeType& range) 482 { 483 const char *end = rangeString + length; 484 485 const char* sptr, *eptr; 486 487 // initialize range to invalid format 488 range.format = RtspRangeType::INVALID_RANGE; 489 490 // find the first word before the "=" 491 sptr = skip_whitespace_and_line_term(rangeString, end); 492 if (sptr >= end) 493 { 494 return false; 495 } 496 497 for (eptr = sptr; eptr < end && 498 (*eptr != '=' && *eptr != ':' && *eptr != ' ' && *eptr != '\t'); 499 ++eptr); 500 501 502 StrPtrLen smpte_type("smpte"); 503 StrPtrLen smpte25_type("smpte-25"); 504 StrPtrLen smpte30_type("smpte-30-drop"); 505 StrPtrLen npt_type("npt"); 506 StrPtrLen abs_type("clock"); 507 //#ifdef RTSP_PLAYLIST_SUPPORT 508 StrPtrLen playlist_play_time_type("playlist_play_time"); 509 //#endif //#ifdef RTSP_PLAYLIST_SUPPORT 510 511 if (!oscl_strncmp(sptr, smpte_type.c_str(), eptr - sptr) || 512 !oscl_strncmp(sptr, smpte25_type.c_str(), eptr - sptr) || 513 !oscl_strncmp(sptr, smpte30_type.c_str(), eptr - sptr)) 514 { 515 // Parsing one of the SMPTE time formats 516 517 // save the exact format temporarily 518 RtspRangeType::RtspRangeFormat tmp_format; 519 if (!oscl_strncmp(sptr, smpte30_type.c_str(), smpte30_type.length())) 520 { 521 tmp_format = RtspRangeType::SMPTE_30_RANGE; 522 } 523 else if (!oscl_strncmp(sptr, smpte25_type.c_str(), smpte25_type.length())) 524 { 525 tmp_format = RtspRangeType::SMPTE_25_RANGE; 526 } 527 else 528 { 529 tmp_format = RtspRangeType::SMPTE_RANGE; 530 } 531 532 // skip ahead to beyond the "=" 533 if (*eptr != '=') 534 { 535 for (; eptr < end && *eptr != '='; ++eptr); 536 } 537 538 sptr = skip_whitespace(eptr + 1, end); 539 if (sptr >= end) 540 { 541 return false; 542 } 543 544 // find the start/end separator 545 for (eptr = sptr; eptr < end && 546 (*eptr != '-'); ++eptr); 547 548 if (*eptr != '-') 549 { 550 return false; 551 } 552 553 range.start_is_set = false; 554 if (eptr > sptr) 555 { 556 // there is a start time 557 558 if (parse_smpte_format(sptr, eptr, tmp_format, range.smpte_start) == false) 559 { 560 return false; 561 } 562 563 // now set the appropriate flags 564 range.start_is_set = true; 565 } 566 567 // see if there is a stop time 568 sptr = skip_whitespace_and_line_term(eptr + 1, end); 569 range.end_is_set = false; 570 if (sptr < end) 571 { 572 // there is a stop time specification 573 eptr = skip_to_whitespace(sptr, end); 574 575 if (parse_smpte_format(sptr, eptr, tmp_format, range.smpte_end) 576 == false) 577 { 578 return false; 579 } 580 581 // now set the appropriate flags 582 range.end_is_set = true; 583 } 584 585 // now set the appropriate range format 586 range.format = tmp_format; 587 588 } // end if this is an SMPTE time format 589 590 else if (!oscl_strncmp(sptr, npt_type.c_str(), eptr - sptr)) 591 { 592 593 // skip ahead to beyond the "=" or ":" 594 if (*eptr != '=') 595 { 596 for (; eptr < end && *eptr != '=' && *eptr != ':'; ++eptr); 597 } 598 599 sptr = skip_whitespace(eptr + 1, end); 600 if (sptr >= end) 601 { 602 return false; 603 } 604 605 // find the start/end separator 606 for (eptr = sptr; eptr < end && 607 (*eptr != '-'); ++eptr); 608 609 if (*eptr != '-') 610 { 611 return false; 612 } 613 614 range.start_is_set = false; 615 if (eptr > sptr) 616 { 617 // there is a start time 618 if (parse_npt_format(sptr, eptr, range.npt_start) == false) 619 { 620 return false; 621 } 622 623 // now set the appropriate flags 624 range.start_is_set = true; 625 626 } 627 628 // see if there is a stop time 629 range.end_is_set = false; 630 sptr = skip_whitespace_and_line_term(eptr + 1, end); 631 if (sptr < end) 632 { 633 // there is a stop time specification 634 eptr = skip_to_whitespace(sptr, end); 635 636 if (parse_npt_format(sptr, eptr, range.npt_end) 637 == false) 638 { 639 return false; 640 } 641 642 // now set the appropriate flags 643 range.end_is_set = true; 644 } 645 646 // now set the appropriate range format 647 range.format = RtspRangeType::NPT_RANGE; 648 649 } // end if this is an NPT time format 650 651 else if (!oscl_strncmp(sptr, abs_type.c_str(), eptr - sptr)) 652 { 653 654 655 // skip ahead to beyond the "=" 656 if (*eptr != '=') 657 { 658 for (; eptr < end && *eptr != '='; ++eptr); 659 } 660 661 sptr = skip_whitespace(eptr + 1, end); 662 if (sptr >= end) 663 { 664 return false; 665 } 666 667 // find the start/end separator 668 for (eptr = sptr; eptr < end && 669 (*eptr != '-'); ++eptr); 670 671 if (*eptr != '-') 672 { 673 return false; 674 } 675 676 range.start_is_set = false; 677 if (eptr > sptr) 678 { 679 // there is a start time 680 if (parse_abs_format(sptr, eptr, range.abs_start) == false) 681 { 682 return false; 683 } 684 685 // now set the appropriate flags 686 range.start_is_set = true; 687 688 } 689 690 // see if there is a stop time 691 sptr = skip_whitespace_and_line_term(eptr + 1, end); 692 range.end_is_set = true; 693 if (sptr < end) 694 { 695 // there is a stop time specification 696 eptr = skip_to_whitespace(sptr, end); 697 698 if (parse_abs_format(sptr, eptr, range.abs_end) 699 == false) 700 { 701 return false; 702 } 703 704 // now set the appropriate flags 705 range.end_is_set = true; 706 } 707 708 // now set the appropriate range format 709 range.format = RtspRangeType::ABS_RANGE; 710 711 } // end if this is an ABS time format 712 //#ifdef RTSP_PLAYLIST_SUPPORT 713 // for Range:playlist_play_time=<URN,clipIndex,clipOffset> 714 //playlist_play_time=</public/playlist/va_playlists/test.ply,3,0.0>;npt=194.81542 715 else if (!oscl_strncmp(sptr, playlist_play_time_type.c_str(), eptr - sptr)) 716 { 717 // store the whole string since we may not need the parsed version of things 718 //oscl_memcpy(range.iPlaylistPlayStr,rangeString,length); 719 //range.iPlaylistPlayStr[length] = '\0'; 720 721 range.format = RtspRangeType::PLAYLIST_TIME_RANGE; 722 range.start_is_set = range.end_is_set = false; 723 724 // now set the appropriate flags 725 range.start_is_set = true; 726 727 // skip ahead to beyond the "=" 728 if (*eptr != '=') 729 { 730 for (; eptr < end && *eptr != '='; ++eptr); 731 } 732 733 sptr = skip_whitespace(eptr + 1, end); 734 if (sptr >= end) 735 { 736 return false; 737 } 738 739 // next should be the opening "<" 740 // skip ahead to beyond the "<" 741 if (*eptr != '<') 742 { 743 for (; eptr < end && *eptr != '<'; ++eptr); 744 } 745 746 sptr = skip_whitespace(eptr + 1, end); 747 if (sptr >= end) 748 { 749 return false; 750 } 751 752 // find the comma separator 753 for (eptr = sptr; eptr < end && 754 (*eptr != ','); ++eptr); 755 756 if (*eptr != ',') 757 { 758 return false; 759 } 760 761 // first the urn 762 if (eptr > sptr) 763 { 764 // there is a urn 765 if (oscl_memcpy(range.iPlaylistUrl, sptr, eptr - sptr) == false) 766 { 767 return false; 768 } 769 //range.iUrn[(eptr-sptr)+1] = '\0'; 770 range.iPlaylistUrl[eptr-sptr] = '\0'; 771 } 772 773 // now the clipIndex 774 sptr = skip_whitespace(eptr + 1, end); 775 if (sptr >= end) 776 { 777 return false; 778 } 779 780 // find the next comma separator 781 for (eptr = sptr; eptr < end && 782 (*eptr != ','); ++eptr); 783 784 if (*eptr != ',') 785 { 786 return false; 787 } 788 789 // now the clipIndex 790 if (eptr > sptr) 791 { 792 // there is a clipIndex 793 uint32 tmp; 794 if (PV_atoi(sptr, 'd', eptr - sptr, tmp) == false) 795 { 796 return false; 797 } 798 range.playlist_start.iClipIndex = (int32)tmp; 799 } 800 801 // now the clipOffset 802 sptr = skip_whitespace(eptr + 1, end); 803 if (sptr >= end) 804 { 805 return false; 806 } 807 808 // find the final '>' separator or the final possible '.' in offset 809 //<sec>.<frac> 810 for (eptr = sptr; eptr < end && 811 (*eptr != '>') && (*eptr != '.'); ++eptr); 812 813 if (eptr >= end) 814 { 815 return false; 816 } 817 818 // @todo ignore the factional part for now 819 // now the clipOffset 820 if (eptr > sptr) 821 { 822 // there is a clipOffset 823 uint32 tmp; 824 if (PV_atoi(sptr, 'd', eptr - sptr, tmp) == false) 825 { 826 return false; 827 } 828 range.playlist_start.sec = (int32)tmp; 829 830 { 831 range.playlist_start.milli_sec = 0; 832 if (*eptr == '.') 833 { 834 // there is an optional fractional seconds field 835 836 // get the fractional seconds 837 const int MAX_TMP_BUFSIZE = 12; 838 char tmpbuf[MAX_TMP_BUFSIZE]; 839 int copy_size; 840 841 eptr = skip_to_whitespace(sptr, end); 842 843 copy_size = eptr - sptr; 844 845 if (copy_size > MAX_TMP_BUFSIZE - 1) 846 { 847 copy_size = MAX_TMP_BUFSIZE - 1; 848 } 849 850 oscl_strncpy(tmpbuf, sptr, copy_size); 851 852 853 tmpbuf[copy_size] = '\0'; 854 855 OsclFloat tmp_fnum; 856 if (!PV_atof(tmpbuf, tmp_fnum)) 857 return false; 858 range.playlist_start.milli_sec = (uint32)(1000.0 * tmp_fnum + 0.5); 859 } 860 } 861 } 862 } // end if this is a playlist_play_time format, for response to playlist_play commands 863 //#endif //#ifdef RTSP_PLAYLIST_SUPPORT 864 else 865 { 866 /*Unsupported time format*/ 867 range.format = RtspRangeType::UNKNOWN_RANGE; 868 range.start_is_set = false; 869 range.end_is_set = false; 870 return false; 871 } 872 873 return true; 874 } 875 876 OSCL_EXPORT_REF int estimate_SDP_string_len(const NptTimeFormat& npt_range) 877 { 878 int total_len = 0; 879 880 881 switch (npt_range.npt_format) 882 { 883 case NptTimeFormat::NOW: 884 total_len += 3; // enough for "now" 885 break; 886 887 case NptTimeFormat::NPT_SEC: 888 // compute the size for the sec field 889 if (npt_range.npt_sec.sec < 1000) 890 { 891 total_len += 3; // enough for at most 3 digits 892 } 893 else if (npt_range.npt_sec.sec < 1000000) 894 { 895 total_len += 6; // enough for 6 digits 896 } 897 else 898 { 899 total_len += 10; // enough for MAX_INT of uint32 900 } 901 902 if (npt_range.npt_sec.milli_sec > 0.0) 903 { 904 total_len += MAX_RANGE_FLOAT_SIZE; // includes "." and all digits 905 } 906 break; 907 908 case NptTimeFormat::NPT_HHMMSS: 909 if (npt_range.npt_hhmmss.hours < 1000) 910 { 911 total_len += 3; // enough for at most 3 digits 912 } 913 else if (npt_range.npt_hhmmss.hours < 1000000) 914 { 915 total_len += 6; // enough for 6 digits 916 } 917 else 918 { 919 total_len += 10; // enough for MAX_INT of uint32 920 } 921 922 total_len += 6; // enough for ":MM:SS" 923 924 if (npt_range.npt_hhmmss.frac_sec > 0.0) 925 { 926 total_len += MAX_RANGE_FLOAT_SIZE; // includes "." and all digits 927 } 928 break; 929 } 930 931 return total_len; 932 } 933 934 935 OSCL_EXPORT_REF int estimate_SDP_string_len(const RtspRangeType& range) 936 { 937 // this function computes the string size necessary for 938 // holding the SDP string representation of the range 939 940 int total_len = 0; 941 942 total_len += 8 ; // this the length of the "a=range:" string 943 944 switch (range.format) 945 { 946 947 case RtspRangeType::NPT_RANGE: 948 total_len += 4; // this is the length of the "npt=" string 949 950 if (range.start_is_set) 951 { 952 total_len += estimate_SDP_string_len(range.npt_start); 953 } 954 else if (!range.end_is_set) 955 { 956 // return 0 in this case 957 return 0; 958 } 959 960 total_len += 1; // enough for "-" 961 962 if (range.end_is_set) 963 { 964 total_len += estimate_SDP_string_len(range.npt_end); 965 } 966 967 total_len += 2; // enough for CRLF at the end of the line 968 969 break; 970 971 972 case RtspRangeType::SMPTE_RANGE: 973 case RtspRangeType::SMPTE_25_RANGE: 974 case RtspRangeType::SMPTE_30_RANGE: 975 if (range.format == RtspRangeType::SMPTE_30_RANGE) 976 { 977 total_len += 14; // this is the length of the "smpte-30-drop=" string 978 } 979 else if (range.format == RtspRangeType::SMPTE_25_RANGE) 980 { 981 total_len += 9; // this is the length of the "smpte-25=" string 982 } 983 else 984 { 985 total_len += 6; // this is enough for "smpte=" 986 } 987 988 if (range.start_is_set) 989 { 990 total_len += 8; // enough for "XX:YY:ZZ" 991 if (range.smpte_start.frames || range.smpte_start.subframes) 992 { 993 total_len += 3; // enough for ":FF" 994 if (range.smpte_start.subframes) 995 { 996 total_len += 3; // enough for ".SS" 997 } 998 } 999 } 1000 else if (!range.end_is_set) 1001 { 1002 // return 0 in this case 1003 return 0; 1004 } 1005 1006 total_len += 1; // enough for "-" 1007 1008 if (range.end_is_set) 1009 { 1010 total_len += 8; // enough for "XX:YY:ZZ" 1011 if (range.smpte_end.frames || range.smpte_end.subframes) 1012 { 1013 total_len += 3; // enough for ":FF" 1014 if (range.smpte_end.subframes) 1015 { 1016 total_len += 3; // enough for ".SS" 1017 } 1018 } 1019 } 1020 1021 total_len += 2; // enough for CRLF at the end of the line 1022 1023 break; 1024 1025 case RtspRangeType::ABS_RANGE: 1026 1027 total_len += 6; // this is the length of the "clock=" string 1028 1029 if (range.start_is_set) 1030 { 1031 total_len += 15; // enough for "YYYYMMDDTHHMMSS" 1032 if (range.abs_start.frac_sec > 0.0) 1033 { 1034 total_len += MAX_RANGE_FLOAT_SIZE; // includes "." and all digits 1035 } 1036 total_len += 1; // enough for the "Z" 1037 } 1038 else if (!range.end_is_set) 1039 { 1040 // return 0 in this case 1041 return 0; 1042 } 1043 1044 total_len += 1; // enough for "-" 1045 1046 if (range.end_is_set) 1047 { 1048 total_len += 15; // enough for "YYYYMMDDTHHMMSS" 1049 if (range.abs_end.frac_sec > 0.0) 1050 { 1051 total_len += MAX_RANGE_FLOAT_SIZE; // includes "." and all digits 1052 } 1053 total_len += 1; // enough for the "Z" 1054 } 1055 1056 total_len += 2; // enough for CRLF at the end of the line 1057 1058 break; 1059 1060 1061 default: 1062 return 0; 1063 break; 1064 } 1065 1066 return total_len; 1067 } 1068 1069 1070 1071 OSCL_EXPORT_REF bool compose_range_string(char *str, unsigned int max_len, 1072 const NptTimeFormat& npt_range, 1073 int& len_used) 1074 { 1075 len_used = 0; 1076 int length; 1077 1078 1079 switch (npt_range.npt_format) 1080 { 1081 case NptTimeFormat::NOW: 1082 { 1083 StrPtrLen now_str("now"); 1084 if ((int)max_len < now_str.length()) 1085 { 1086 return false; 1087 } 1088 oscl_memcpy(str, now_str.c_str(), now_str.length()); 1089 str += now_str.length(); 1090 len_used += now_str.length(); 1091 max_len -= now_str.length(); 1092 break; 1093 } 1094 1095 case NptTimeFormat::NPT_SEC: 1096 { 1097 char tmpstr[MAX_RANGE_INT_SIZE + 1]; 1098 length = oscl_snprintf(tmpstr, MAX_RANGE_INT_SIZE + 1, "%d", 1099 npt_range.npt_sec.sec); 1100 if (length < 0 || length > MAX_RANGE_INT_SIZE) 1101 { 1102 return false; 1103 } 1104 if (length > (int) max_len) 1105 { 1106 return false; 1107 } 1108 oscl_memcpy(str, tmpstr, length); 1109 str += length; 1110 len_used += length; 1111 max_len -= length; 1112 if (npt_range.npt_sec.milli_sec > 0.0) 1113 { 1114 if (npt_range.npt_sec.milli_sec >= 1.0) 1115 { 1116 return false; 1117 } 1118 char tmp[MAX_RANGE_FLOAT_SIZE + 2]; 1119 length = oscl_snprintf(tmp, MAX_RANGE_FLOAT_SIZE + 2, RANGE_FLOAT_FORMAT, 1120 npt_range.npt_sec.milli_sec); 1121 if (length < 0 || length > MAX_RANGE_FLOAT_SIZE + 1) 1122 { 1123 return false; 1124 } 1125 if (length > (int)max_len || tmp[1] != '.') 1126 { 1127 return false; 1128 } 1129 1130 oscl_memcpy(str, tmp + 1, length - 1); 1131 str += length - 1; 1132 len_used += length - 1; 1133 max_len -= (length - 1); 1134 } 1135 1136 break; 1137 } 1138 1139 case NptTimeFormat::NPT_HHMMSS: 1140 { 1141 char tmpstr[MAX_RANGE_INT_SIZE + 1]; 1142 length = oscl_snprintf(tmpstr, MAX_RANGE_INT_SIZE + 1, "%d", 1143 npt_range.npt_hhmmss.hours); 1144 if (length < 0 || length >= MAX_RANGE_INT_SIZE) 1145 { 1146 return false; 1147 } 1148 if (length > (int) max_len) 1149 { 1150 return false; 1151 } 1152 oscl_memcpy(str, tmpstr, length); 1153 str += length; 1154 len_used += length; 1155 max_len -= length; 1156 1157 if (max_len < 6) 1158 { 1159 return false; 1160 } 1161 1162 length = oscl_snprintf(tmpstr, MAX_RANGE_INT_SIZE + 1, ":%02d:%02d", 1163 npt_range.npt_hhmmss.min, npt_range.npt_hhmmss.sec); 1164 if (length != 6) 1165 { 1166 return false; 1167 } 1168 1169 oscl_memcpy(str, tmpstr, length); 1170 str += length; 1171 len_used += length; 1172 max_len -= length; 1173 1174 1175 if (npt_range.npt_hhmmss.frac_sec > 0.0) 1176 { 1177 if (npt_range.npt_hhmmss.frac_sec >= 1.0) 1178 { 1179 return false; 1180 } 1181 char tmp[MAX_RANGE_FLOAT_SIZE + 2]; 1182 length = oscl_snprintf(tmp, MAX_RANGE_FLOAT_SIZE + 2, RANGE_FLOAT_FORMAT, 1183 npt_range.npt_hhmmss.frac_sec); 1184 if (length < 0 || length > MAX_RANGE_FLOAT_SIZE + 1) 1185 { 1186 return false; 1187 } 1188 if (length > (int) max_len || tmp[1] != '.') 1189 { 1190 return false; 1191 } 1192 1193 oscl_memcpy(str, tmp + 1, length - 1); 1194 str += length - 1; 1195 len_used += length - 1; 1196 max_len -= (length - 1); 1197 } 1198 1199 break; 1200 } 1201 1202 } 1203 1204 return true; 1205 1206 } 1207 1208 1209 OSCL_EXPORT_REF bool compose_range_string(char *str, unsigned int max_len, 1210 const SmpteTimeFormat& smpte_range, 1211 int& len_used) 1212 { 1213 len_used = 0; 1214 int length; 1215 1216 1217 char tmp[10]; 1218 1219 if (max_len < 8) 1220 { 1221 return false; 1222 } 1223 1224 length = oscl_snprintf(tmp, 9, "%02d:%02d:%02d", smpte_range.hours, 1225 smpte_range.minutes, smpte_range.seconds); 1226 1227 if (length != 8) 1228 { 1229 return false; 1230 } 1231 1232 oscl_memcpy(str, tmp , length); 1233 str += length; 1234 len_used += length; 1235 max_len -= length; 1236 1237 if (smpte_range.frames) 1238 { 1239 if (max_len < 3) 1240 { 1241 return 0; 1242 } 1243 length = oscl_snprintf(tmp, 4, ":%02d", smpte_range.frames); 1244 if (length != 3) 1245 { 1246 return false; 1247 } 1248 1249 oscl_memcpy(str, tmp , length); 1250 str += length; 1251 len_used += length; 1252 max_len -= length; 1253 } 1254 1255 if (smpte_range.subframes) 1256 { 1257 if (max_len < 3) 1258 { 1259 return 0; 1260 } 1261 length = oscl_snprintf(tmp, 4, ".%02d", smpte_range.subframes); 1262 if (length != 3) 1263 { 1264 return false; 1265 } 1266 1267 oscl_memcpy(str, tmp , length); 1268 str += length; 1269 len_used += length; 1270 max_len -= length; 1271 } 1272 1273 return true; 1274 1275 } 1276 1277 1278 OSCL_EXPORT_REF bool compose_range_string(char *str, unsigned int max_len, 1279 const AbsTimeFormat& abs_range, 1280 int& len_used) 1281 { 1282 len_used = 0; 1283 int length; 1284 1285 1286 char tmp[17]; 1287 1288 if (max_len < 16) 1289 { 1290 return false; 1291 } 1292 1293 length = oscl_snprintf(tmp, 17, "%04d%02d%02dT%02d%02d%02d", 1294 abs_range.year, abs_range.month, abs_range.day, 1295 abs_range.hours, abs_range.min, abs_range.sec); 1296 1297 if (length != 15) 1298 { 1299 return false; 1300 } 1301 1302 oscl_memcpy(str, tmp , length); 1303 str += length; 1304 len_used += length; 1305 max_len -= length; 1306 1307 if (abs_range.frac_sec > 0.0) 1308 { 1309 if (abs_range.frac_sec >= 1.0) 1310 { 1311 return false; 1312 } 1313 char tmpstr[MAX_RANGE_FLOAT_SIZE + 2]; 1314 length = oscl_snprintf(tmpstr, MAX_RANGE_FLOAT_SIZE + 2, RANGE_FLOAT_FORMAT, 1315 abs_range.frac_sec); 1316 if (length < 0 || length > MAX_RANGE_FLOAT_SIZE + 1) 1317 { 1318 return false; 1319 } 1320 if (length > (int)max_len || tmp[1] != '.') 1321 { 1322 return false; 1323 } 1324 1325 oscl_memcpy(str, tmp + 1, length - 1); 1326 str += length - 1; 1327 len_used += length - 1; 1328 max_len -= (length - 1); 1329 } 1330 1331 if (max_len < 1) 1332 { 1333 return false; 1334 } 1335 1336 *str = 'Z'; 1337 len_used++; 1338 1339 return true; 1340 1341 } 1342 1343 1344 OSCL_EXPORT_REF bool compose_range_string(char *str, unsigned int max_len, const RtspRangeType& range, 1345 int& len_used) 1346 { 1347 len_used = 0; 1348 int length; 1349 1350 if (!range.start_is_set && !range.end_is_set) 1351 { 1352 return false; 1353 } 1354 1355 switch (range.format) 1356 { 1357 case RtspRangeType::NPT_RANGE: 1358 { 1359 StrPtrLen npt_str("npt="); 1360 1361 if (max_len < (unsigned int)npt_str.length()) 1362 { 1363 return false; 1364 } 1365 1366 oscl_memcpy(str, npt_str.c_str(), npt_str.length()); 1367 1368 str += npt_str.length(); 1369 max_len -= npt_str.length(); 1370 len_used += npt_str.length(); 1371 1372 if (range.start_is_set) 1373 { 1374 if (compose_range_string(str, max_len, range.npt_start, 1375 length) != true) 1376 { 1377 return false; 1378 } 1379 1380 len_used += length; 1381 max_len -= length; 1382 str += length; 1383 } 1384 1385 if (max_len < 1) 1386 { 1387 return false; 1388 } 1389 1390 *str++ = '-'; 1391 --max_len; 1392 ++len_used; 1393 1394 if (range.end_is_set) 1395 { 1396 if (compose_range_string(str, max_len, range.npt_end, 1397 length) != true) 1398 { 1399 return false; 1400 } 1401 1402 len_used += length; 1403 max_len -= length; 1404 str += length; 1405 } 1406 1407 break; 1408 } 1409 1410 case RtspRangeType::SMPTE_RANGE: 1411 case RtspRangeType::SMPTE_25_RANGE: 1412 case RtspRangeType::SMPTE_30_RANGE: 1413 { 1414 StrPtrLen smpte30_str("smpte-30-drop="); 1415 StrPtrLen smpte25_str("smpte-25="); 1416 StrPtrLen smpte_str("smpte="); 1417 1418 if (range.format == RtspRangeType::SMPTE_30_RANGE) 1419 { 1420 if (max_len < (unsigned int)smpte30_str.length()) 1421 { 1422 return false; 1423 } 1424 oscl_memcpy(str, smpte30_str.c_str(), smpte30_str.length()); 1425 1426 str += smpte30_str.length(); 1427 max_len -= smpte30_str.length(); 1428 len_used += smpte30_str.length(); 1429 1430 } 1431 else if (range.format == RtspRangeType::SMPTE_25_RANGE) 1432 { 1433 if (max_len < (unsigned int)smpte25_str.length()) 1434 { 1435 return false; 1436 } 1437 1438 oscl_memcpy(str, smpte25_str.c_str(), smpte25_str.length()); 1439 1440 str += smpte25_str.length(); 1441 max_len -= smpte25_str.length(); 1442 len_used += smpte25_str.length(); 1443 } 1444 else 1445 { 1446 if (max_len < (unsigned int)smpte_str.length()) 1447 { 1448 return false; 1449 } 1450 1451 oscl_memcpy(str, smpte_str.c_str(), smpte_str.length()); 1452 str += smpte_str.length(); 1453 max_len -= smpte_str.length(); 1454 len_used += smpte_str.length(); 1455 1456 } 1457 1458 if (range.start_is_set) 1459 { 1460 if (compose_range_string(str, max_len, range.smpte_start, 1461 length) != true) 1462 { 1463 return false; 1464 } 1465 1466 len_used += length; 1467 max_len -= length; 1468 str += length; 1469 } 1470 1471 if (max_len < 1) 1472 { 1473 return false; 1474 } 1475 1476 *str++ = '-'; 1477 --max_len; 1478 ++len_used; 1479 1480 1481 if (range.end_is_set) 1482 { 1483 if (compose_range_string(str, max_len, range.smpte_end, 1484 length) != true) 1485 { 1486 return false; 1487 } 1488 1489 len_used += length; 1490 max_len -= length; 1491 str += length; 1492 } 1493 1494 break; 1495 } 1496 1497 case RtspRangeType::ABS_RANGE: 1498 { 1499 StrPtrLen abs_str("clock="); 1500 1501 if (max_len < (unsigned int)abs_str.length()) 1502 { 1503 return false; 1504 } 1505 1506 oscl_memcpy(str, abs_str.c_str(), abs_str.length()); 1507 1508 str += abs_str.length(); 1509 max_len -= abs_str.length(); 1510 len_used += abs_str.length(); 1511 1512 if (range.start_is_set) 1513 { 1514 if (compose_range_string(str, max_len, range.abs_start, 1515 length) != true) 1516 { 1517 return false; 1518 } 1519 1520 len_used += length; 1521 max_len -= length; 1522 str += length; 1523 } 1524 1525 if (max_len < 1) 1526 { 1527 return false; 1528 } 1529 1530 *str++ = '-'; 1531 --max_len; 1532 ++len_used; 1533 1534 1535 if (range.end_is_set) 1536 { 1537 if (compose_range_string(str, max_len, range.abs_end, 1538 length) != true) 1539 { 1540 return false; 1541 } 1542 1543 len_used += length; 1544 max_len -= length; 1545 str += length; 1546 } 1547 1548 break; 1549 } 1550 1551 default: 1552 return false; 1553 } 1554 1555 if (max_len < 2) 1556 { 1557 // can't add line terminator 1558 return false; 1559 } 1560 1561 // add the line terminator 1562 *str++ = '\r'; 1563 *str++ = '\n'; 1564 len_used += 2; 1565 1566 1567 return true; 1568 1569 } 1570 1571 1572 1573 1574 OSCL_EXPORT_REF bool compose_SDP_string(char *str, unsigned int max_len, 1575 const RtspRangeType& range, 1576 int& len_used) 1577 { 1578 len_used = 0; 1579 1580 // first verify that there is something to do 1581 if (range.format == RtspRangeType::UNKNOWN_RANGE || 1582 range.format == RtspRangeType::INVALID_RANGE) 1583 { 1584 // nothing to output but it is not an error 1585 return true; 1586 } 1587 1588 const char *range_str = "a=range:"; 1589 int length = oscl_strlen(range_str); 1590 // output the "a=range:" string 1591 if ((int)max_len < length) 1592 { 1593 return false; 1594 } 1595 1596 oscl_memcpy(str, range_str, length); 1597 1598 str += length; 1599 len_used += length; 1600 max_len -= length; 1601 1602 if (compose_range_string(str, max_len, range, length) != true) 1603 { 1604 len_used += length; 1605 return false; 1606 } 1607 1608 len_used += length; 1609 1610 return true; 1611 } 1612 1613 1614 1615 OSCL_EXPORT_REF bool compose_RTSP_string(char *str, unsigned int max_len, 1616 const RtspRangeType& range, 1617 int& len_used) 1618 { 1619 len_used = 0; 1620 1621 // first verify that there is something to do 1622 if (range.format == RtspRangeType::UNKNOWN_RANGE || 1623 range.format == RtspRangeType::INVALID_RANGE) 1624 { 1625 // nothing to output but it is not an error 1626 return true; 1627 } 1628 1629 const char *range_str = "Range: "; 1630 int length = oscl_strlen(range_str); 1631 // output the "Range: " string 1632 if ((int)max_len < length) 1633 { 1634 return false; 1635 } 1636 1637 oscl_memcpy(str, range_str, length); 1638 1639 str += length; 1640 len_used += length; 1641 max_len -= length; 1642 1643 if (compose_range_string(str, max_len, range, length) != true) 1644 { 1645 len_used += length; 1646 return false; 1647 } 1648 1649 len_used += length; 1650 1651 return true; 1652 } 1653 1654 1655 1656 1657