• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RtspRangeTypeRtspRangeType127     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     /***********************************************************************************/
convertToMilliSecRtspRangeType176     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 
calculateDeltaRtspRangeType319     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 
leapYearRtspRangeType396     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