Skip to content

Commit

Permalink
Stop truncating parsed times to <10h
Browse files Browse the repository at this point in the history
All current renderers and muxers have no issues with longer timestamps.
However, classic VSFilter keeping track of time with a 32-bit int,
leads to a more meaningful limit at 596h, so enforce that instead.

Since the stringification code for SRT and ASS (but not SMPTE) relied on
hours being single digit, replace them with a simple format string.

GUI inputs are still limited to <10h, but at least
pre-existing timestamps no longer get mangled.
  • Loading branch information
TheOneric committed Jan 7, 2024
1 parent 6af7c6b commit 444b49c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 27 deletions.
52 changes: 26 additions & 26 deletions libaegisub/ass/time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,21 @@

#include <algorithm>

// classic VSFilter internally uses a signed 32-bit int to denote milliseconds.
// To avoid this limit to < 596h (-6 to avoid rounding up to 596h in centisecond precision)
static const int MAX_TIME = 596 * 60 * 60 * 1000 - 6;

static void decompose_time(int ms_time, int& h, int& m, int& s, int& ms) {
h = ms_time / 3600000;
ms_time -= h * 3600000;
m = ms_time / 60000;
ms_time -= m * 60000;
s = ms_time / 1000;
ms = ms_time - s * 1000;
}

namespace agi {
Time::Time(int time) : time(util::mid(0, time, 10 * 60 * 60 * 1000 - 6)) { }
Time::Time(int time) : time(util::mid(0, time, MAX_TIME)) { }

Time::Time(std::string const& text) {
int after_decimal = -1;
Expand Down Expand Up @@ -56,38 +69,25 @@ Time::Time(std::string const& text) {
time = (time * 60 + current) * 1000;

// Limit to the valid range
time = util::mid(0, time, 10 * 60 * 60 * 1000 - 6);
time = util::mid(0, time, MAX_TIME);
}

std::string Time::GetAssFormatted(bool msPrecision) const {
int ass_time = msPrecision ? time : int(*this);
std::string ret(10 + msPrecision, ':');
ret[0] = '0' + ass_time / 3600000;
ret[2] = '0' + (ass_time % (60 * 60 * 1000)) / (60 * 1000 * 10);
ret[3] = '0' + (ass_time % (10 * 60 * 1000)) / (60 * 1000);
ret[5] = '0' + (ass_time % (60 * 1000)) / (1000 * 10);
ret[6] = '0' + (ass_time % (10 * 1000)) / 1000;
ret[7] = '.';
ret[8] = '0' + (ass_time % 1000) / 100;
ret[9] = '0' + (ass_time % 100) / 10;
if (msPrecision)
ret[10] = '0' + ass_time % 10;
return ret;
int h, m, s, ms;

decompose_time(ass_time, h, m, s, ms);

if (!msPrecision)
return format("%d:%02d:%02d.%02d", h, m, s, ms / 10);
else
return format("%d:%02d:%02d.%03d", h, m, s, ms);
}

std::string Time::GetSrtFormatted() const {
std::string ret(12, ':');
ret[0] = '0';
ret[1] = '0' + time / 3600000;
ret[3] = '0' + (time % (60 * 60 * 1000)) / (60 * 1000 * 10);
ret[4] = '0' + (time % (10 * 60 * 1000)) / (60 * 1000);
ret[6] = '0' + (time % (60 * 1000)) / (1000 * 10);
ret[7] = '0' + (time % (10 * 1000)) / 1000;
ret[8] = ',';
ret[9] = '0' + (time % 1000) / 100;
ret[10] = '0' + (time % 100) / 10;
ret[11] = '0' + time % 10;
return ret;
int h, m, s, ms;
decompose_time(time, h, m, s, ms);
return format("%02d:%02d:%02d,%03d", h, m, s, ms);
}

SmpteFormatter::SmpteFormatter(vfr::Framerate fps, char sep)
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ using agi::Time;

TEST(lagi_time, out_of_range_times) {
EXPECT_EQ(0, (int)Time(-1));
EXPECT_EQ(10 * 60 * 60 * 1000 - 10, (int)Time(10 * 60 * 60 * 1000));
EXPECT_EQ(596 * 60 * 60 * 1000 - 10, (int)Time(596 * 60 * 60 * 1000));
}

TEST(lagi_time, rounds_to_cs) {
Expand Down

0 comments on commit 444b49c

Please sign in to comment.