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 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     19 
     20 //               R T S P _ T I M E _ F O R M A T S
     21 //     ( T I M E / R A N G E   R E P R E S E N T A T I O N S )
     22 
     23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     24 #ifndef RTSP_TIME_FORMAT_H
     25 #define RTSP_TIME_FORMAT_H
     26 
     27 // - - Inclusion - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     28 #ifndef OSCL_BASE_H_INCLUDED
     29 #include "oscl_base.h"
     30 #endif
     31 
     32 #ifndef OSCL_INT64_UTILS_H_INCLUDED
     33 #include "oscl_int64_utils.h"
     34 #endif
     35 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     36 #ifndef OSCL_MEM_BASIC_FUNCTIONS_H
     37 #include "oscl_mem_basic_functions.h"
     38 #endif
     39 
     40 
     41 
     42 // SMPTE time format allows two decimal digits for each field of the format
     43 // The basic format is  HH:MM:SS where HH = hours, MM = minutes, SS = seconds
     44 // from the beginning of the presentation.  It can optionally contain frame-level
     45 // with the format HH:MM:SS:FF.ff where FF is the frame number and ff is the
     46 // fractional part of the frame (i.e., subframe).
     47 
     48 struct SmpteTimeFormat
     49 {
     50     uint8 hours;
     51     uint8 minutes;
     52     uint8 seconds;
     53     uint8 frames;
     54     uint8 subframes;
     55 };
     56 
     57 // NPT (normal play time) format is represents the time offset from the beginning
     58 // of the presentation either in seconds (including fractional seconds) or
     59 // hours+minutes+secs (including fractional seconds).  Unlike the SMPTE time format,
     60 // the number of digits in the hours representation is arbitrary.  When in the seconds-only
     61 // format, the number of digits for that field is also arbitrary.  We will allow
     62 // 32 bits to hold these arbitrary length fields.  The format is one of
     63 //                "now" | sec+[.frac_sec*] | H+:MM:SS[.frac_sec*]
     64 // where "+" means one or more digits, "*" means zero or more digits, and "[ ]"  means the
     65 // field is optional and may not appear.
     66 
     67 struct NptSecFormat
     68 {
     69     uint32 sec;
     70     uint32 milli_sec;   //added as a sub for floating counterpart.
     71 //  float frac_sec;
     72 };
     73 
     74 struct NptHHMMSSFormat
     75 {
     76     uint32 hours;
     77     uint8 min;
     78     uint8 sec;
     79     float frac_sec;
     80 };
     81 
     82 struct NptTimeFormat
     83 {
     84     enum NptFormatType { NOW, NPT_SEC, NPT_HHMMSS};
     85 
     86     NptFormatType npt_format;
     87     union
     88     {
     89         NptSecFormat npt_sec;
     90         NptHHMMSSFormat npt_hhmmss;
     91     };
     92 
     93 };
     94 
     95 struct PVNSPlaylistTimeFormat
     96 {
     97 //  mbchar iPlaylistUrl[1024];
     98     uint32 iClipIndex;
     99     uint32 sec;
    100     uint32 milli_sec;
    101 };
    102 
    103 // Abs time format represents the absolute time value.  The this represented as
    104 // YYYYMMDD"T"HHMMSS[.frac_sec*]"Z" where YYYY is the four digit year, MM is the two digit
    105 // month, DD is the two-digit day, "T" is just the T character, HH is the two-digit hour,
    106 // MM is the two-digit minute, SS is the two-digit second, and finally "Z" is simply the Z character.
    107 // The time value is based on the UTC (GMT) time coordinates.
    108 
    109 struct AbsTimeFormat
    110 {
    111     uint16 year;
    112     uint8 month;
    113     uint8 day;
    114     uint8 hours;
    115     uint8 min;
    116     uint8 sec;
    117     float frac_sec;
    118 };
    119 
    120 struct RtspRangeType
    121 {
    122     enum
    123     {
    124         PlaylistUrlLen = 1024
    125     };
    126 
    127     RtspRangeType(): format(UNKNOWN_RANGE), start_is_set(false), end_is_set(false)
    128     {
    129         oscl_memset(iPlaylistUrl, 0, (PlaylistUrlLen * sizeof(mbchar)));
    130     }
    131     enum RtspRangeFormat { NPT_RANGE, SMPTE_RANGE, SMPTE_25_RANGE,
    132                            SMPTE_30_RANGE,
    133                            ABS_RANGE,
    134 //#ifdef RTSP_PLAYLIST_SUPPORT
    135                            PLAYLIST_TIME_RANGE,
    136 //#endif //#ifdef RTSP_PLAYLIST_SUPPORT
    137                            UNKNOWN_RANGE, INVALID_RANGE
    138                          };
    139     RtspRangeFormat format;
    140     bool start_is_set;
    141     union
    142     {
    143         SmpteTimeFormat smpte_start;
    144         NptTimeFormat npt_start;
    145         AbsTimeFormat abs_start;
    146         PVNSPlaylistTimeFormat  playlist_start;
    147     };
    148 
    149     bool end_is_set;
    150     union
    151     {
    152         SmpteTimeFormat smpte_end;
    153         NptTimeFormat npt_end;
    154         AbsTimeFormat abs_end;
    155         PVNSPlaylistTimeFormat  playlist_end;
    156     };
    157 
    158 //#ifdef RTSP_PLAYLIST_SUPPORT
    159     mbchar iPlaylistUrl[PlaylistUrlLen];
    160 //#endif //#ifdef RTSP_PLAYLIST_SUPPORT
    161     /***********************************************************************************/
    162     /*Function : int32 convertToMillisec(int32 &startTime, int32 &stopTime)                  */
    163     /*                                                                                 */
    164     /*                                                                                 */
    165     /*Parameters : int32 &startTime - Output                                             */
    166     /*             int32 &stopTime - Output                                              */
    167     /*                                                                                 */
    168     /*Return values : 0 - if conversion was successful.                                */
    169     /*                -1 - if conversion failed.                                       */
    170     /*                                                                                 */
    171     /*Description : This utility function converts time in different formats to time   */
    172     /*in milliseconds. In case of formats that don't fit in 32 bits after conversion,  */
    173     /*the function returns an error code. The caller of the function can use the return*/
    174     /*code to decide whether to call the "calculateDelta" utility function.            */
    175     /***********************************************************************************/
    176     int32 convertToMilliSec(int32 &startTime, int32 &stopTime)
    177     {
    178         const int32 MILLISEC_IN_HOUR = 3600000;
    179         const int32 MILLISEC_IN_MIN = 60000;
    180         const int32 MILLISEC_IN_SEC = 1000;
    181         switch (format)
    182         {
    183             case RtspRangeType::NPT_RANGE:
    184             {
    185                 if (start_is_set)
    186                 {
    187                     switch (npt_start.npt_format)
    188                     {
    189                         case NptTimeFormat::NOW:
    190                         {
    191                             startTime = 0;
    192                         }
    193                         break;
    194                         case NptTimeFormat::NPT_SEC:
    195                         {
    196                             startTime = (int32)(MILLISEC_IN_SEC * (npt_start.npt_sec.sec) +
    197                                                 npt_start.npt_sec.milli_sec);
    198                         }
    199                         break;
    200                         case NptTimeFormat::NPT_HHMMSS:
    201                         {
    202                             startTime = MILLISEC_IN_HOUR * npt_start.npt_hhmmss.hours +
    203                                         MILLISEC_IN_MIN * npt_start.npt_hhmmss.min +
    204                                         MILLISEC_IN_SEC * npt_start.npt_hhmmss.sec +
    205                                         (int32)(MILLISEC_IN_SEC * npt_start.npt_hhmmss.frac_sec);
    206                         }
    207                         break;
    208                     }
    209                 }
    210                 else
    211                 {
    212                     startTime = 0;
    213                 }
    214                 if (end_is_set)
    215                 {
    216                     switch (npt_end.npt_format)
    217                     {
    218                         case NptTimeFormat::NOW:
    219                         {
    220                             stopTime = 0;
    221                         }
    222                         break;
    223                         case NptTimeFormat::NPT_SEC:
    224                         {
    225                             stopTime = (int32)(MILLISEC_IN_SEC * (npt_end.npt_sec.sec) +
    226                                                npt_end.npt_sec.milli_sec);
    227                         }
    228                         break;
    229                         case NptTimeFormat::NPT_HHMMSS:
    230                         {
    231                             stopTime = MILLISEC_IN_HOUR * npt_end.npt_hhmmss.hours +
    232                                        MILLISEC_IN_MIN * npt_end.npt_hhmmss.min +
    233                                        MILLISEC_IN_SEC * npt_end.npt_hhmmss.sec +
    234                                        (int32)(MILLISEC_IN_SEC * npt_end.npt_hhmmss.frac_sec);
    235                         }
    236                         break;
    237                     }
    238                 }
    239                 else
    240                 {
    241                     stopTime = 0;
    242                 }
    243             }
    244             break;
    245             case RtspRangeType::SMPTE_RANGE:
    246             case RtspRangeType::SMPTE_25_RANGE:
    247             case RtspRangeType::SMPTE_30_RANGE:
    248             {
    249                 if (start_is_set)
    250                 {
    251                     startTime = MILLISEC_IN_HOUR * smpte_start.hours +
    252                                 MILLISEC_IN_MIN * smpte_start.minutes +
    253                                 MILLISEC_IN_SEC * smpte_start.seconds;
    254                 }
    255                 else
    256                 {
    257                     startTime = 0;
    258                 }
    259                 if (end_is_set)
    260                 {
    261                     stopTime = MILLISEC_IN_HOUR * smpte_end.hours +
    262                                MILLISEC_IN_MIN * smpte_end.minutes +
    263                                MILLISEC_IN_SEC * smpte_end.seconds;
    264                 }
    265                 else
    266                 {
    267                     stopTime = 0;
    268                 }
    269             }
    270             break;
    271             case RtspRangeType::ABS_RANGE:
    272             {
    273                 if (start_is_set && end_is_set)
    274                 {
    275                     startTime = 0;
    276                     uint64 delta = calculateDelta();
    277                     /*
    278                      *We return valid start and stop times(in millisec) if we see that the delta
    279                      *between the start and stop times fits in 32 bits.
    280                      */
    281                     if (delta < (uint64)0xffffffff)
    282                     {
    283                         startTime = 0;
    284 
    285                         stopTime = Oscl_Int64_Utils::get_uint64_lower32(delta);
    286 
    287                     }
    288                     else
    289                     {
    290                         startTime = 0;
    291                         stopTime = 0;
    292                         return -1;
    293                     }
    294                 }
    295                 else
    296                 {
    297                     return -1;
    298                 }
    299             }
    300             break;
    301             case RtspRangeType::UNKNOWN_RANGE:
    302             case RtspRangeType::INVALID_RANGE:
    303             {
    304                 startTime = 0;
    305                 stopTime = 0;
    306                 return -1;
    307             }
    308 
    309             default:
    310             {
    311                 startTime = 0;
    312                 stopTime = 0;
    313                 return -1;
    314             }
    315         }
    316         return 0;
    317     }
    318 
    319     uint64 calculateDelta()
    320     {
    321         const int32 DAYS_IN_YEAR = 365;
    322         const int32 DAYS_IN_LEAP_YEAR = 366;
    323         const int32 HOURS_IN_DAY = 24;
    324         const int32 MILLISEC_IN_HOUR = 3600000;
    325         const int32 MILLISEC_IN_MIN = 60000;
    326         const int32 MILLISEC_IN_SEC = 1000;
    327 
    328         int32 daysOfYear[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
    329         int32 daysOfLeapYear[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
    330         uint64 delta = 0;
    331         uint64 startTime = 0;
    332         uint64 stopTime = 0;
    333 
    334         /*
    335          *Let's calculate the start time first. We need to find the number of days in the
    336          *year first.
    337          */
    338         if (start_is_set && end_is_set)
    339         {
    340             int32 numberOfDays = 0;
    341             bool leap = leapYear(abs_start.year);
    342             if (!leap)
    343             {
    344                 numberOfDays = daysOfYear[abs_start.month-1];
    345             }
    346             else
    347             {
    348                 numberOfDays = daysOfLeapYear[abs_start.month-1];
    349             }
    350             numberOfDays += abs_start.day - 1;
    351             startTime = numberOfDays * HOURS_IN_DAY;
    352             startTime += (uint32)abs_start.hours;
    353             startTime *= MILLISEC_IN_HOUR;
    354             startTime += abs_start.min * MILLISEC_IN_MIN +
    355                          abs_start.sec * MILLISEC_IN_SEC +
    356                          (int32)(abs_start.frac_sec * MILLISEC_IN_SEC);
    357             /*
    358              *Now, let's calculate the stop time. We use the start time's year as the reference
    359              *year.
    360              */
    361             numberOfDays = 0;
    362             for (int32 ii = abs_start.year; ii < abs_end.year; ii++)
    363             {
    364                 if (leapYear(ii))
    365                     numberOfDays += DAYS_IN_LEAP_YEAR;
    366                 else
    367                     numberOfDays += DAYS_IN_YEAR;
    368             }
    369             leap = leapYear(abs_end.year);
    370             if (!leap)
    371             {
    372                 numberOfDays = daysOfYear[abs_end.month-1];
    373             }
    374             else
    375             {
    376                 numberOfDays = daysOfLeapYear[abs_end.month-1];
    377             }
    378 
    379             numberOfDays += abs_end.day - 1;
    380             stopTime = numberOfDays * HOURS_IN_DAY;
    381             stopTime += (uint32)abs_end.hours;
    382             stopTime *= MILLISEC_IN_HOUR;
    383             stopTime += abs_end.min * MILLISEC_IN_MIN +
    384                         abs_end.sec * MILLISEC_IN_SEC +
    385                         (int32)(abs_end.frac_sec * MILLISEC_IN_SEC);
    386 
    387             delta = stopTime - startTime;
    388         }
    389         else
    390         {
    391             return delta;
    392         }
    393         return delta;
    394     }
    395 
    396     bool leapYear(int32 year)
    397     {
    398         if (year % 4 != 0)
    399             return false;
    400         else if (year % 400 == 0)
    401             return true;
    402         else if (year % 100 == 0)
    403             return false;
    404         else
    405             return true;
    406     }
    407 };
    408 #endif
    409