double WebVTTParser::collectTimeStamp(const String& line, unsigned* position) { // 4.8.10.13.3 Collect a WebVTT timestamp. // 1-4 - Initial checks, let most significant units be minutes. enum Mode { minutes, hours }; Mode mode = minutes; if (*position >= line.length() || !isASCIIDigit(line[*position])) return malformedTime; // 5-6 - Collect a sequence of characters that are 0-9. String digits1 = collectDigits(line, position); int value1 = digits1.toInt(); // 7 - If not 2 characters or value is greater than 59, interpret as hours. if (digits1.length() != 2 || value1 > 59) mode = hours; // 8-12 - Collect the next sequence of 0-9 after ':' (must be 2 chars). if (*position >= line.length() || line[(*position)++] != ':') return malformedTime; if (*position >= line.length() || !isASCIIDigit(line[(*position)])) return malformedTime; String digits2 = collectDigits(line, position); int value2 = digits2.toInt(); if (digits2.length() != 2) return malformedTime; // 13 - Detect whether this timestamp includes hours. int value3; if (mode == hours || (*position < line.length() && line[*position] == ':')) { if (*position >= line.length() || line[(*position)++] != ':') return malformedTime; if (*position >= line.length() || !isASCIIDigit(line[*position])) return malformedTime; String digits3 = collectDigits(line, position); if (digits3.length() != 2) return malformedTime; value3 = digits3.toInt(); } else { value3 = value2; value2 = value1; value1 = 0; } // 14-19 - Collect next sequence of 0-9 after '.' (must be 3 chars). if (*position >= line.length() || line[(*position)++] != '.') return malformedTime; if (*position >= line.length() || !isASCIIDigit(line[*position])) return malformedTime; String digits4 = collectDigits(line, position); if (digits4.length() != 3) return malformedTime; int value4 = digits4.toInt(); if (value2 > 59 || value3 > 59) return malformedTime; // 20-21 - Calculate result. return (value1 * secondsPerHour) + (value2 * secondsPerMinute) + value3 + (value4 * secondsPerMillisecond); }
bool MediaFragmentURIParser::parseNPTTime(const LChar* timeString, unsigned length, unsigned& offset, double& time) { enum Mode { minutes, hours }; Mode mode = minutes; if (offset >= length || !isASCIIDigit(timeString[offset])) return false; // http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec/#npttimedef // Normal Play Time can either be specified as seconds, with an optional // fractional part to indicate miliseconds, or as colon-separated hours, // minutes and seconds (again with an optional fraction). Minutes and // seconds must be specified as exactly two digits, hours and fractional // seconds can be any number of digits. The hours, minutes and seconds // specification for NPT is a convenience only, it does not signal frame // accuracy. The specification of the "npt:" identifier is optional since // NPT is the default time scheme. This specification builds on the RTSP // specification of NPT RFC 2326. // // ; defined in RFC 2326 // npt-sec = 1*DIGIT [ "." *DIGIT ] ; definitions taken // npt-hhmmss = npt-hh ":" npt-mm ":" npt-ss [ "." *DIGIT] ; from RFC 2326 // npt-mmss = npt-mm ":" npt-ss [ "." *DIGIT] // npt-hh = 1*DIGIT ; any positive number // npt-mm = 2DIGIT ; 0-59 // npt-ss = 2DIGIT ; 0-59 String digits1 = collectDigits(timeString, length, offset); int value1 = digits1.toInt(); if (offset >= length || timeString[offset] == ',') { time = value1; return true; } double fraction = 0; if (timeString[offset] == '.') { if (offset == length) return true; String digits = collectFraction(timeString, length, offset); fraction = digits.toDouble(); time = value1 + fraction; return true; } if (digits1.length() < 2) return false; if (digits1.length() > 2) mode = hours; // Collect the next sequence of 0-9 after ':' if (offset >= length || timeString[offset++] != ':') return false; if (offset >= length || !isASCIIDigit(timeString[(offset)])) return false; String digits2 = collectDigits(timeString, length, offset); int value2 = digits2.toInt(); if (digits2.length() != 2) return false; // Detect whether this timestamp includes hours. int value3; if (mode == hours || (offset < length && timeString[offset] == ':')) { if (offset >= length || timeString[offset++] != ':') return false; if (offset >= length || !isASCIIDigit(timeString[offset])) return false; String digits3 = collectDigits(timeString, length, offset); if (digits3.length() != 2) return false; value3 = digits3.toInt(); } else { value3 = value2; value2 = value1; value1 = 0; } if (offset < length && timeString[offset] == '.') fraction = collectFraction(timeString, length, offset).toDouble(); time = (value1 * secondsPerHour) + (value2 * secondsPerMinute) + value3 + fraction; return true; }
SWITCH_DECLARE(int) CoreSession::collectDigits(int abs_timeout) { return collectDigits(0, abs_timeout); }