@@ -49,13 +49,13 @@ namespace adm {
4949 }
5050
5151 Time parseTimecode (const std::string& timecode) {
52- const static std::regex commonFormat (" ( \\ d{2}):(\\ d{2}):(\\ d{2}).(\\ d+ )" );
52+ const static std::regex commonFormat (R"( (-?)(\ d{2}):(\d{2}):(\d{2}).(\d+) )" );
5353 const static std::regex fractionalFormat (
54- " ( \\ d{2}):(\\ d{2}):(\\ d{2}).(\\ d+)S(\\ d+ )" );
54+ R"( (-?)(\ d{2}):(\d{2}):(\d{2}).(\d+)S(\d+) )" );
5555
5656 std::smatch timecodeMatch;
5757 if (std::regex_match (timecode, timecodeMatch, commonFormat)) {
58- const std::string& ns_str = timecodeMatch[4 ];
58+ const std::string& ns_str = timecodeMatch[5 ];
5959
6060 // parse number of nanoseconds as if it always had 9 digits
6161 int64_t ns = 0 ;
@@ -64,18 +64,22 @@ namespace adm {
6464 if (i < ns_str.size ()) ns += place_value * (ns_str[i] - ' 0' );
6565 place_value *= 10 ;
6666 }
67+ auto isPositive = timecodeMatch[1 ].str ().empty ();
6768
68- return std::chrono::hours (stoi (timecodeMatch[1 ])) +
69- std::chrono::minutes (stoi (timecodeMatch[2 ])) +
70- std::chrono::seconds (stoi (timecodeMatch[3 ])) +
71- std::chrono::nanoseconds (ns);
69+ return (isPositive ? 1 : -1 ) *
70+ (std::chrono::hours (stoi (timecodeMatch[2 ])) +
71+ std::chrono::minutes (stoi (timecodeMatch[3 ])) +
72+ std::chrono::seconds (stoi (timecodeMatch[4 ])) +
73+ std::chrono::nanoseconds (ns));
7274 } else if (std::regex_match (timecode, timecodeMatch, fractionalFormat)) {
73- int64_t seconds = 3600 * stoi (timecodeMatch[1 ]) +
74- 60 * stoi (timecodeMatch[2 ]) +
75- 1 * stoi (timecodeMatch[3 ]);
75+ auto isPositive = timecodeMatch[1 ].str ().empty ();
76+ int64_t seconds =
77+ 3600 * stoi (timecodeMatch[2 ]) +
78+ 60 * stoi (timecodeMatch[3 ]) +
79+ 1 * stoi (timecodeMatch[4 ]);
7680
77- int64_t numerator = stoi (timecodeMatch[4 ]);
78- int64_t denominator = stoi (timecodeMatch[5 ]);
81+ int64_t numerator = stoi (timecodeMatch[5 ]);
82+ int64_t denominator = stoi (timecodeMatch[6 ]);
7983
8084 if (denominator == 0 ) {
8185 std::stringstream errorString;
@@ -84,7 +88,7 @@ namespace adm {
8488 throw std::runtime_error (errorString.str ());
8589 }
8690
87- return FractionalTime{seconds * denominator + numerator, denominator};
91+ return FractionalTime{(isPositive ? 1 : - 1 ) * ( seconds * denominator + numerator) , denominator};
8892 } else {
8993 std::stringstream errorString;
9094 errorString << " invalid timecode: " << timecode;
@@ -95,18 +99,23 @@ namespace adm {
9599 struct FormatTimeVisitor : public boost ::static_visitor<std::string> {
96100 std::string operator ()(const std::chrono::nanoseconds& time) const {
97101 std::stringstream ss;
102+ auto formatTime = time;
103+ if (formatTime.count () < 0 ) {
104+ formatTime = -formatTime;
105+ ss << ' -' ;
106+ }
98107 ss << std::setw (2 ) << std::setfill (' 0' )
99- << std::chrono::duration_cast<std::chrono::hours>(time ).count ();
108+ << std::chrono::duration_cast<std::chrono::hours>(formatTime ).count ();
100109 ss << " :" ;
101110 ss << std::setw (2 ) << std::setfill (' 0' )
102- << std::chrono::duration_cast<std::chrono::minutes>(time ).count () % 60 ;
111+ << std::chrono::duration_cast<std::chrono::minutes>(formatTime ).count () % 60 ;
103112 ss << " :" ;
104113 ss << std::setw (2 ) << std::setfill (' 0' )
105- << std::chrono::duration_cast<std::chrono::seconds>(time ).count () % 60 ;
114+ << std::chrono::duration_cast<std::chrono::seconds>(formatTime ).count () % 60 ;
106115 ss << " ." ;
107116
108117 {
109- auto ns = time .count () % 1000000000 ;
118+ auto ns = formatTime .count () % 1000000000 ;
110119 // drop trailing zero digits, while keeping at least 5 to satisfy BS.2076-2
111120 int precision = 9 ;
112121 while (ns % 10 == 0 && precision > 5 ) {
@@ -120,18 +129,24 @@ namespace adm {
120129 }
121130
122131 std::string operator ()(const FractionalTime& time) const {
123- int64_t whole_seconds = time.numerator () / time.denominator ();
132+ auto absNum = abs (time.numerator ());
133+ auto absDenom = abs (time.denominator ());
134+ int64_t whole_seconds = absNum / absDenom;
124135 int64_t frac_numerator =
125- time. numerator () - whole_seconds * time. denominator () ;
136+ absNum - whole_seconds * absDenom ;
126137
127138 std::stringstream ss;
139+ double floating = static_cast <double >(time.numerator ()) / time.denominator ();
140+ if (std::signbit (floating)) {
141+ ss << " -" ;
142+ }
128143 ss << std::setw (2 ) << std::setfill (' 0' ) << whole_seconds / 3600 ;
129144 ss << " :" ;
130145 ss << std::setw (2 ) << std::setfill (' 0' ) << (whole_seconds / 60 ) % 60 ;
131146 ss << " :" ;
132147 ss << std::setw (2 ) << std::setfill (' 0' ) << whole_seconds % 60 ;
133148 ss << " ." ;
134- ss << frac_numerator << " S" << time. denominator () ;
149+ ss << frac_numerator << " S" << absDenom ;
135150 return ss.str ();
136151 }
137152 };
0 commit comments