Home | History | Annotate | Download | only in src
      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