diff --git a/packager/media/formats/webvtt/webvtt_media_parser.cc b/packager/media/formats/webvtt/webvtt_media_parser.cc index a18b6c12e3..615f03036a 100644 --- a/packager/media/formats/webvtt/webvtt_media_parser.cc +++ b/packager/media/formats/webvtt/webvtt_media_parser.cc @@ -93,14 +93,14 @@ bool ParseTimingAndSettingsLine(const std::string& line, } const std::string& start_time_str = entries[0]; - if (!WebVttTimestampParse(start_time_str, start_time)) { + if (!WebVttTimestampToMs(start_time_str, start_time)) { LOG(ERROR) << "Failed to parse " << start_time_str << " in " << line; return false; } const std::string& end_time_str = entries[2]; uint64_t end_time = 0; - if (!WebVttTimestampParse(end_time_str, &end_time)) { + if (!WebVttTimestampToMs(end_time_str, &end_time)) { LOG(ERROR) << "Failed to parse " << end_time_str << " in " << line; return false; } diff --git a/packager/media/formats/webvtt/webvtt_timestamp.cc b/packager/media/formats/webvtt/webvtt_timestamp.cc index 2f2810e2cf..0ef67aa2e8 100644 --- a/packager/media/formats/webvtt/webvtt_timestamp.cc +++ b/packager/media/formats/webvtt/webvtt_timestamp.cc @@ -7,9 +7,11 @@ #include "packager/media/formats/webvtt/webvtt_timestamp.h" #include +#include #include "packager/base/logging.h" #include "packager/base/strings/string_number_conversions.h" +#include "packager/base/strings/stringprintf.h" namespace shaka { namespace media { @@ -22,22 +24,17 @@ bool GetTotalMilliseconds(uint64_t hours, uint64_t* out) { DCHECK(out); if (minutes > 59 || seconds > 59 || ms > 999) { - VLOG(1) << "Hours:" << hours - << " Minutes:" << minutes - << " Seconds:" << seconds - << " MS:" << ms + VLOG(1) << "Hours:" << hours << " Minutes:" << minutes + << " Seconds:" << seconds << " MS:" << ms << " shoud have never made it to GetTotalMilliseconds"; return false; } - *out = 60 * 60 * 1000 * hours + - 60 * 1000 * minutes + - 1000 * seconds + - ms; + *out = 60 * 60 * 1000 * hours + 60 * 1000 * minutes + 1000 * seconds + ms; return true; } } // namespace -bool WebVttTimestampParse(const base::StringPiece& source, uint64_t* out) { +bool WebVttTimestampToMs(const base::StringPiece& source, uint64_t* out) { DCHECK(out); if (source.length() < 9) { @@ -54,13 +51,12 @@ bool WebVttTimestampParse(const base::StringPiece& source, uint64_t* out) { uint64_t seconds = 0; uint64_t ms = 0; - const bool has_hours = minutes_begin >= 3 && - source[minutes_begin-1] == ':' && - base::StringToUint64(source.substr(0, minutes_begin-1), &hours); + const bool has_hours = + minutes_begin >= 3 && source[minutes_begin - 1] == ':' && + base::StringToUint64(source.substr(0, minutes_begin - 1), &hours); - if ((minutes_begin == 0 || has_hours) && - source[seconds_begin-1] == ':' && - source[milliseconds_begin-1] == '.' && + if ((minutes_begin == 0 || has_hours) && source[seconds_begin - 1] == ':' && + source[milliseconds_begin - 1] == '.' && base::StringToUint64(source.substr(minutes_begin, 2), &minutes) && base::StringToUint64(source.substr(seconds_begin, 2), &seconds) && base::StringToUint64(source.substr(milliseconds_begin, 3), &ms)) { @@ -70,5 +66,21 @@ bool WebVttTimestampParse(const base::StringPiece& source, uint64_t* out) { LOG(WARNING) << "Timestamp '" << source << "' is mal-formed"; return false; } + +std::string MsToWebVttTimestamp(uint64_t ms) { + uint64_t remaining = ms; + + uint64_t only_ms = remaining % 1000; + remaining /= 1000; + uint64_t only_seconds = remaining % 60; + remaining /= 60; + uint64_t only_minutes = remaining % 60; + remaining /= 60; + uint64_t only_hours = remaining; + + return base::StringPrintf("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64 + ".%03" PRIu64, + only_hours, only_minutes, only_seconds, only_ms); +} } // namespace media } // namespace shaka diff --git a/packager/media/formats/webvtt/webvtt_timestamp.h b/packager/media/formats/webvtt/webvtt_timestamp.h index 3bdc65f434..088ab290a5 100644 --- a/packager/media/formats/webvtt/webvtt_timestamp.h +++ b/packager/media/formats/webvtt/webvtt_timestamp.h @@ -18,7 +18,10 @@ namespace media { // Parse a timestamp into milliseconds using the two patterns defined by WebVtt: // LONG : ##:##:##.### (long can have 2 or more hour digits) // SHORT : ##:##:### -bool WebVttTimestampParse(const base::StringPiece& source, uint64_t* out); +bool WebVttTimestampToMs(const base::StringPiece& source, uint64_t* out); + +// Create a long form timestamp encoded as a string. +std::string MsToWebVttTimestamp(uint64_t ms); } // namespace media } // namespace shaka diff --git a/packager/media/formats/webvtt/webvtt_timestamp_unittest.cc b/packager/media/formats/webvtt/webvtt_timestamp_unittest.cc index 5cb855df51..9f5ab09075 100644 --- a/packager/media/formats/webvtt/webvtt_timestamp_unittest.cc +++ b/packager/media/formats/webvtt/webvtt_timestamp_unittest.cc @@ -13,84 +13,119 @@ namespace media { TEST(WebVttTimestampTest, TooShort) { uint64_t ms; - EXPECT_FALSE(WebVttTimestampParse("00.000", &ms)); + EXPECT_FALSE(WebVttTimestampToMs("00.000", &ms)); } TEST(WebVttTimestampTest, RightLengthButMeaningless) { uint64_t ms; - EXPECT_FALSE(WebVttTimestampParse("ABCDEFGHI", &ms)); + EXPECT_FALSE(WebVttTimestampToMs("ABCDEFGHI", &ms)); } TEST(WebVttTimestampTest, ParseHours) { uint64_t ms; - EXPECT_TRUE(WebVttTimestampParse("12:00:00.000", &ms)); + EXPECT_TRUE(WebVttTimestampToMs("12:00:00.000", &ms)); EXPECT_EQ(43200000u, ms); } TEST(WebVttTimestampTest, ParseLongHours) { uint64_t ms; - EXPECT_TRUE(WebVttTimestampParse("120:00:00.000", &ms)); + EXPECT_TRUE(WebVttTimestampToMs("120:00:00.000", &ms)); EXPECT_EQ(432000000u, ms); } TEST(WebVttTimestampTest, ParseMinutes) { uint64_t ms; - EXPECT_TRUE(WebVttTimestampParse("00:12:00.000", &ms)); + EXPECT_TRUE(WebVttTimestampToMs("00:12:00.000", &ms)); EXPECT_EQ(720000u, ms); } TEST(WebVttTimestampTest, ParseSeconds) { uint64_t ms; - EXPECT_TRUE(WebVttTimestampParse("00:00:12.000", &ms)); + EXPECT_TRUE(WebVttTimestampToMs("00:00:12.000", &ms)); EXPECT_EQ(12000u, ms); } TEST(WebVttTimestampTest, ParseMs) { uint64_t ms; - EXPECT_TRUE(WebVttTimestampParse("00:00:00.123", &ms)); + EXPECT_TRUE(WebVttTimestampToMs("00:00:00.123", &ms)); EXPECT_EQ(123u, ms); } TEST(WebVttTimestampTest, ParseNoHours) { uint64_t ms; - EXPECT_TRUE(WebVttTimestampParse("12:00.000", &ms)); + EXPECT_TRUE(WebVttTimestampToMs("12:00.000", &ms)); EXPECT_EQ(720000u, ms); } TEST(WebVttTimestampTest, FailWithShortHours) { uint64_t ms; - EXPECT_FALSE(WebVttTimestampParse("1:00:00.000", &ms)); + EXPECT_FALSE(WebVttTimestampToMs("1:00:00.000", &ms)); } TEST(WebVttTimestampTest, FailWithShortMinutes) { uint64_t ms; - EXPECT_FALSE(WebVttTimestampParse("00:1:00.000", &ms)); + EXPECT_FALSE(WebVttTimestampToMs("00:1:00.000", &ms)); } TEST(WebVttTimestampTest, FailWithShortSeconds) { uint64_t ms; - EXPECT_FALSE(WebVttTimestampParse("00:1.000", &ms)); + EXPECT_FALSE(WebVttTimestampToMs("00:1.000", &ms)); } TEST(WebVttTimestampTest, FailWithShortMs) { uint64_t ms; - EXPECT_FALSE(WebVttTimestampParse("00:00.01", &ms)); + EXPECT_FALSE(WebVttTimestampToMs("00:00.01", &ms)); } TEST(WebVttTimestampTest, FailWithNonDigit) { uint64_t ms; - EXPECT_FALSE(WebVttTimestampParse("00:0A:00.000", &ms)); + EXPECT_FALSE(WebVttTimestampToMs("00:0A:00.000", &ms)); } TEST(WebVttTimestampTest, FailWithInvalidMinutes) { uint64_t ms; - EXPECT_FALSE(WebVttTimestampParse("00:79:00.000", &ms)); + EXPECT_FALSE(WebVttTimestampToMs("00:79:00.000", &ms)); } TEST(WebVttTimestampTest, FailWithInvalidSeconds) { uint64_t ms; - EXPECT_FALSE(WebVttTimestampParse("00:00:79.000", &ms)); + EXPECT_FALSE(WebVttTimestampToMs("00:00:79.000", &ms)); } +TEST(WebVttTimestampTest, CreatesMilliseconds) { + EXPECT_EQ("00:00:00.123", MsToWebVttTimestamp(123)); +} + +TEST(WebVttTimestampTest, CreatesMillisecondsShort) { + EXPECT_EQ("00:00:00.012", MsToWebVttTimestamp(12)); +} + +TEST(WebVttTimestampTest, CreateSeconds) { + EXPECT_EQ("00:00:12.000", MsToWebVttTimestamp(12000)); +} + +TEST(WebVttTimestampTest, CreateSecondsShort) { + EXPECT_EQ("00:00:01.000", MsToWebVttTimestamp(1000)); +} + +TEST(WebVttTimestampTest, CreateMinutes) { + EXPECT_EQ("00:12:00.000", MsToWebVttTimestamp(720000)); +} + +TEST(WebVttTimestampTest, CreateMinutesShort) { + EXPECT_EQ("00:01:00.000", MsToWebVttTimestamp(60000)); +} + +TEST(WebVttTimestampTest, CreateHours) { + EXPECT_EQ("12:00:00.000", MsToWebVttTimestamp(43200000)); +} + +TEST(WebVttTimestampTest, CreateHoursShort) { + EXPECT_EQ("01:00:00.000", MsToWebVttTimestamp(3600000)); +} + +TEST(WebVttTimestampTest, CreateHoursLong) { + EXPECT_EQ("123:00:00.000", MsToWebVttTimestamp(442800000)); +} } // namespace media } // namespace shaka