Shaka Packager SDK
webvtt_timestamp.cc
1 // Copyright 2017 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/media/formats/webvtt/webvtt_timestamp.h"
8 
9 #include <ctype.h>
10 #include <inttypes.h>
11 
12 #include "packager/base/logging.h"
13 #include "packager/base/strings/string_number_conversions.h"
14 #include "packager/base/strings/stringprintf.h"
15 
16 namespace shaka {
17 namespace media {
18 namespace {
19 
20 bool GetTotalMilliseconds(uint64_t hours,
21  uint64_t minutes,
22  uint64_t seconds,
23  uint64_t ms,
24  uint64_t* out) {
25  DCHECK(out);
26  if (minutes > 59 || seconds > 59 || ms > 999) {
27  VLOG(1) << "Hours:" << hours << " Minutes:" << minutes
28  << " Seconds:" << seconds << " MS:" << ms
29  << " shoud have never made it to GetTotalMilliseconds";
30  return false;
31  }
32  *out = 60 * 60 * 1000 * hours + 60 * 1000 * minutes + 1000 * seconds + ms;
33  return true;
34 }
35 } // namespace
36 
37 bool WebVttTimestampToMs(const base::StringPiece& source, uint64_t* out) {
38  DCHECK(out);
39 
40  if (source.length() < 9) {
41  LOG(WARNING) << "Timestamp '" << source << "' is mal-formed";
42  return false;
43  }
44 
45  const size_t minutes_begin = source.length() - 9;
46  const size_t seconds_begin = source.length() - 6;
47  const size_t milliseconds_begin = source.length() - 3;
48 
49  uint64_t hours = 0;
50  uint64_t minutes = 0;
51  uint64_t seconds = 0;
52  uint64_t ms = 0;
53 
54  const bool has_hours =
55  minutes_begin >= 3 && source[minutes_begin - 1] == ':' &&
56  base::StringToUint64(source.substr(0, minutes_begin - 1), &hours);
57 
58  if ((minutes_begin == 0 || has_hours) && source[seconds_begin - 1] == ':' &&
59  source[milliseconds_begin - 1] == '.' &&
60  base::StringToUint64(source.substr(minutes_begin, 2), &minutes) &&
61  base::StringToUint64(source.substr(seconds_begin, 2), &seconds) &&
62  base::StringToUint64(source.substr(milliseconds_begin, 3), &ms)) {
63  return GetTotalMilliseconds(hours, minutes, seconds, ms, out);
64  }
65 
66  LOG(WARNING) << "Timestamp '" << source << "' is mal-formed";
67  return false;
68 }
69 
70 std::string MsToWebVttTimestamp(uint64_t ms) {
71  uint64_t remaining = ms;
72 
73  uint64_t only_ms = remaining % 1000;
74  remaining /= 1000;
75  uint64_t only_seconds = remaining % 60;
76  remaining /= 60;
77  uint64_t only_minutes = remaining % 60;
78  remaining /= 60;
79  uint64_t only_hours = remaining;
80 
81  return base::StringPrintf("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64
82  ".%03" PRIu64,
83  only_hours, only_minutes, only_seconds, only_ms);
84 }
85 } // namespace media
86 } // namespace shaka
All the methods that are virtual are virtual for mocking.