forked from mia/Aegisub
Reject vfr timecodes which are all identical
This commit is contained in:
parent
1835d5e2d8
commit
584284aa79
3 changed files with 31 additions and 32 deletions
|
@ -38,9 +38,11 @@ using namespace agi::vfr;
|
|||
/// @param timecodes List of timecodes to check
|
||||
void validate_timecodes(std::vector<int> const& timecodes) {
|
||||
if (timecodes.size() <= 1)
|
||||
throw TooFewTimecodes("Must have at least two timecodes to do anything useful");
|
||||
throw InvalidFramerate("Must have at least two timecodes to do anything useful");
|
||||
if (!is_sorted(timecodes.begin(), timecodes.end()))
|
||||
throw UnorderedTimecodes("Timecodes are out of order");
|
||||
throw InvalidFramerate("Timecodes are out of order");
|
||||
if (timecodes.front() == timecodes.back())
|
||||
throw InvalidFramerate("Timecodes are all identical");
|
||||
}
|
||||
|
||||
/// @brief Shift timecodes so that frame 0 starts at time 0
|
||||
|
@ -71,15 +73,15 @@ TimecodeRange v1_parse_line(std::string const& str) {
|
|||
if (ss.fail() || comma1 != ',' || comma2 != ',' || !ss.eof())
|
||||
throw MalformedLine(str);
|
||||
if (range.start < 0 || range.end < 0)
|
||||
throw UnorderedTimecodes("Cannot specify frame rate for negative frames.");
|
||||
throw InvalidFramerate("Cannot specify frame rate for negative frames.");
|
||||
if (range.end < range.start)
|
||||
throw UnorderedTimecodes("End frame must be greater than or equal to start frame");
|
||||
throw InvalidFramerate("End frame must be greater than or equal to start frame");
|
||||
if (range.fps <= 0.)
|
||||
throw BadFPS("FPS must be greater than zero");
|
||||
throw InvalidFramerate("FPS must be greater than zero");
|
||||
if (range.fps > 1000.)
|
||||
// This is our limitation, not mkvmerge's
|
||||
// mkvmerge uses nanoseconds internally
|
||||
throw BadFPS("FPS must be at most 1000");
|
||||
throw InvalidFramerate("FPS must be at most 1000");
|
||||
return range;
|
||||
}
|
||||
|
||||
|
@ -91,8 +93,8 @@ TimecodeRange v1_parse_line(std::string const& str) {
|
|||
/// @return Assumed fps times one million
|
||||
int64_t v1_parse(line_iterator<std::string> file, std::string line, std::vector<int> &timecodes, int64_t &last) {
|
||||
double fps = atof(line.substr(7).c_str());
|
||||
if (fps <= 0.) throw BadFPS("Assumed FPS must be greater than zero");
|
||||
if (fps > 1000.) throw BadFPS("Assumed FPS must not be greater than 1000");
|
||||
if (fps <= 0.) throw InvalidFramerate("Assumed FPS must be greater than zero");
|
||||
if (fps > 1000.) throw InvalidFramerate("Assumed FPS must not be greater than 1000");
|
||||
|
||||
std::vector<TimecodeRange> ranges;
|
||||
for (auto const& line : file) {
|
||||
|
@ -111,7 +113,7 @@ int64_t v1_parse(line_iterator<std::string> file, std::string line, std::vector<
|
|||
if (frame > range.start) {
|
||||
// mkvmerge allows overlapping timecode ranges, but does completely
|
||||
// broken things with them
|
||||
throw UnorderedTimecodes("Override ranges must not overlap");
|
||||
throw InvalidFramerate("Override ranges must not overlap");
|
||||
}
|
||||
for (; frame < range.start; ++frame) {
|
||||
timecodes.push_back(int(time + .5));
|
||||
|
@ -133,8 +135,8 @@ Framerate::Framerate(double fps)
|
|||
: denominator(default_denominator)
|
||||
, numerator(int64_t(fps * denominator))
|
||||
{
|
||||
if (fps < 0.) throw BadFPS("FPS must be greater than zero");
|
||||
if (fps > 1000.) throw BadFPS("FPS must not be greater than 1000");
|
||||
if (fps < 0.) throw InvalidFramerate("FPS must be greater than zero");
|
||||
if (fps > 1000.) throw InvalidFramerate("FPS must not be greater than 1000");
|
||||
timecodes.push_back(0);
|
||||
}
|
||||
|
||||
|
@ -144,8 +146,8 @@ Framerate::Framerate(int64_t numerator, int64_t denominator, bool drop)
|
|||
, drop(drop && numerator % denominator != 0)
|
||||
{
|
||||
if (numerator <= 0 || denominator <= 0)
|
||||
throw BadFPS("Numerator and denominator must both be greater than zero");
|
||||
if (numerator / denominator > 1000) throw BadFPS("FPS must not be greater than 1000");
|
||||
throw InvalidFramerate("Numerator and denominator must both be greater than zero");
|
||||
if (numerator / denominator > 1000) throw InvalidFramerate("FPS must not be greater than 1000");
|
||||
timecodes.push_back(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,15 +41,11 @@ enum Time {
|
|||
|
||||
DEFINE_EXCEPTION(Error, Exception);
|
||||
/// FPS specified is not a valid frame rate
|
||||
DEFINE_EXCEPTION(BadFPS, Error);
|
||||
DEFINE_EXCEPTION(InvalidFramerate, Error);
|
||||
/// Unknown timecode file format
|
||||
DEFINE_EXCEPTION(UnknownFormat, Error);
|
||||
/// Invalid line encountered in a timecode file
|
||||
DEFINE_EXCEPTION(MalformedLine, Error);
|
||||
/// Timecode file or vector has too few timecodes to be usable
|
||||
DEFINE_EXCEPTION(TooFewTimecodes, Error);
|
||||
/// Timecode file or vector has timecodes that are not monotonically increasing
|
||||
DEFINE_EXCEPTION(UnorderedTimecodes, Error);
|
||||
|
||||
/// @class Framerate
|
||||
/// @brief Class for managing everything related to converting frames to times
|
||||
|
|
|
@ -43,14 +43,15 @@ TEST(lagi_vfr, constructors_good) {
|
|||
}
|
||||
|
||||
TEST(lagi_vfr, constructors_bad_cfr) {
|
||||
EXPECT_THROW(Framerate(-1.), BadFPS);
|
||||
EXPECT_THROW(Framerate(1000.1), BadFPS);
|
||||
EXPECT_THROW(Framerate(-1.), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate(1000.1), InvalidFramerate);
|
||||
}
|
||||
|
||||
TEST(lagi_vfr, constructors_bad_timecodes) {
|
||||
EXPECT_THROW(Framerate(std::initializer_list<int>{}), TooFewTimecodes);
|
||||
EXPECT_THROW(Framerate({ 0 }), TooFewTimecodes);
|
||||
EXPECT_THROW(Framerate({ 10, 0 }), UnorderedTimecodes);
|
||||
EXPECT_THROW(Framerate(std::initializer_list<int>{}), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate({0}), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate({10, 0}), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate({0, 0}), InvalidFramerate);
|
||||
}
|
||||
|
||||
TEST(lagi_vfr, constructors_bad_v1) {
|
||||
|
@ -58,18 +59,18 @@ TEST(lagi_vfr, constructors_bad_v1) {
|
|||
EXPECT_THROW(Framerate("data/vfr/in/v1_too_few_parts.txt"), MalformedLine);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_too_many_parts.txt"), MalformedLine);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_float_frame_number.txt"), MalformedLine);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_start_end_overlap.txt"), UnorderedTimecodes);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_fully_contained.txt"), UnorderedTimecodes);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_assume_over_1000.txt"), BadFPS);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_override_over_1000.txt"), BadFPS);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_override_zero.txt"), BadFPS);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_negative_start_of_range.txt"), UnorderedTimecodes);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_end_less_than_start.txt"), UnorderedTimecodes);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_start_end_overlap.txt"), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_fully_contained.txt"), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_assume_over_1000.txt"), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_override_over_1000.txt"), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_override_zero.txt"), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_negative_start_of_range.txt"), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v1_end_less_than_start.txt"), InvalidFramerate);
|
||||
}
|
||||
|
||||
TEST(lagi_vfr, constructors_bad_v2) {
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v2_empty.txt"), TooFewTimecodes);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v2_out_of_order.txt"), UnorderedTimecodes);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v2_empty.txt"), InvalidFramerate);
|
||||
EXPECT_THROW(Framerate("data/vfr/in/v2_out_of_order.txt"), InvalidFramerate);
|
||||
|
||||
EXPECT_THROW(Framerate("data/vfr/in/empty.txt"), UnknownFormat);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue