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