From 584284aa794bb684c0344b702732dfb5c405a7a7 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 15 Jul 2014 07:37:08 -0700 Subject: [PATCH] Reject vfr timecodes which are all identical --- libaegisub/common/vfr.cpp | 28 +++++++++++++++------------- libaegisub/include/libaegisub/vfr.h | 6 +----- tests/tests/vfr.cpp | 29 +++++++++++++++-------------- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/libaegisub/common/vfr.cpp b/libaegisub/common/vfr.cpp index 6b6911bb9..31480248c 100644 --- a/libaegisub/common/vfr.cpp +++ b/libaegisub/common/vfr.cpp @@ -38,9 +38,11 @@ using namespace agi::vfr; /// @param timecodes List of timecodes to check void validate_timecodes(std::vector 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 file, std::string line, std::vector &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 ranges; for (auto const& line : file) { @@ -111,7 +113,7 @@ int64_t v1_parse(line_iterator 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); } diff --git a/libaegisub/include/libaegisub/vfr.h b/libaegisub/include/libaegisub/vfr.h index 165853912..d929154fb 100644 --- a/libaegisub/include/libaegisub/vfr.h +++ b/libaegisub/include/libaegisub/vfr.h @@ -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 diff --git a/tests/tests/vfr.cpp b/tests/tests/vfr.cpp index 2664d6d1f..a9b8f3acf 100644 --- a/tests/tests/vfr.cpp +++ b/tests/tests/vfr.cpp @@ -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{}), TooFewTimecodes); - EXPECT_THROW(Framerate({ 0 }), TooFewTimecodes); - EXPECT_THROW(Framerate({ 10, 0 }), UnorderedTimecodes); + EXPECT_THROW(Framerate(std::initializer_list{}), 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); }