diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-01-13 11:31:55 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-01-13 11:31:55 +0000 |
| commit | d15ef17dccf87b633d1971c38032a2049abe3db0 (patch) | |
| tree | 3bbde3c1959bae6b0ad064972f95bd9406416fbb | |
| parent | acca8cb950de132fbc4be40e7dc7d294c6cb0a38 (diff) | |
Re-work time.
41 files changed, 661 insertions, 929 deletions
diff --git a/src/dcp/subtitle.cc b/src/dcp/subtitle.cc index ba3c278..d8bae8d 100644 --- a/src/dcp/subtitle.cc +++ b/src/dcp/subtitle.cc @@ -33,37 +33,37 @@ using boost::lexical_cast; using boost::is_any_of; using namespace sub; -dcp::Subtitle::Subtitle (boost::shared_ptr<const cxml::Node> node, bool smpte) +dcp::Subtitle::Subtitle (boost::shared_ptr<const cxml::Node> node, optional<int> tcr) { - if (smpte) { - in = smpte_time (node, "TimeIn").get (); - out = smpte_time (node, "TimeOut").get (); + if (tcr) { + in = smpte_time (node, "TimeIn", tcr.get ()).get (); + out = smpte_time (node, "TimeOut", tcr.get ()).get (); } else { in = interop_time (node, "TimeIn").get (); out = interop_time (node, "TimeOut").get (); } - if (smpte) { - fade_up_time = smpte_time (node, "FadeUpTime").get_value_or (FrameTime (0, 0, 0, 2)); - fade_down_time = smpte_time (node, "FadeDownTime").get_value_or (FrameTime (0, 0, 0, 2)); + if (tcr) { + fade_up_time = smpte_time (node, "FadeUpTime", tcr.get ()).get_value_or (Time::from_hmsf (0, 0, 0, 2, value_to_enum (tcr.get ()))); + fade_down_time = smpte_time (node, "FadeDownTime", tcr.get ()).get_value_or (Time::from_hmsf (0, 0, 0, 2, value_to_enum (tcr.get ()))); } else { - fade_up_time = interop_time (node, "FadeUpTime").get_value_or (MetricTime (0, 0, 0, 80)); - if (fade_up_time.metric() > MetricTime (0, 0, 8, 0)) { - fade_up_time = MetricTime (0, 0, 8, 0); + fade_up_time = interop_time (node, "FadeUpTime").get_value_or (Time::from_hmsm (0, 0, 0, 80)); + if (fade_up_time > Time::from_hmsm (0, 0, 8, 0)) { + fade_up_time = Time::from_hmsm (0, 0, 8, 0); } - fade_down_time = interop_time (node, "FadeDownTime").get_value_or (MetricTime (0, 0, 0, 80)); - if (fade_down_time.metric() > MetricTime (0, 0, 8, 0)) { - fade_down_time = MetricTime (0, 0, 8, 0); + fade_down_time = interop_time (node, "FadeDownTime").get_value_or (Time::from_hmsm (0, 0, 0, 80)); + if (fade_down_time > Time::from_hmsm (0, 0, 8, 0)) { + fade_down_time = Time::from_hmsm (0, 0, 8, 0); } } } -optional<FrameTime> -dcp::Subtitle::smpte_time (shared_ptr<const cxml::Node> node, string name) +optional<Time> +dcp::Subtitle::smpte_time (shared_ptr<const cxml::Node> node, string name, int tcr) { optional<string> u = node->optional_string_attribute (name); if (!u) { - return optional<FrameTime> (); + return optional<Time> (); } vector<string> b; @@ -72,24 +72,23 @@ dcp::Subtitle::smpte_time (shared_ptr<const cxml::Node> node, string name) boost::throw_exception (DCPError ("unrecognised time specification " + u.get ())); } - return FrameTime ( + return Time::from_hmsf ( raw_convert<int> (b[0]), raw_convert<int> (b[1]), raw_convert<int> (b[2]), - raw_convert<int> (b[3]) + raw_convert<int> (b[3]), + value_to_enum (tcr) ); } -optional<MetricTime> +optional<Time> dcp::Subtitle::interop_time (shared_ptr<const cxml::Node> node, string name) { optional<string> u = node->optional_string_attribute (name); if (!u) { - return optional<MetricTime> (); + return optional<Time> (); } - MetricTime t; - if (u.get().find (":") != string::npos) { /* HH:MM:SS:TTT or HH:MM:SS.sss */ vector<string> b; @@ -99,14 +98,13 @@ dcp::Subtitle::interop_time (shared_ptr<const cxml::Node> node, string name) } if (u.get().find (".") != string::npos) { - return MetricTime ( + return Time::from_hms ( raw_convert<int> (b[0]), raw_convert<int> (b[1]), - raw_convert<int> (b[2]), - raw_convert<int> ("." + b[3]) + raw_convert<double> (b[2] + "." + b[3]) ); } else { - return MetricTime ( + return Time::from_hmsm ( raw_convert<int> (b[0]), raw_convert<int> (b[1]), raw_convert<int> (b[2]), @@ -114,8 +112,6 @@ dcp::Subtitle::interop_time (shared_ptr<const cxml::Node> node, string name) ); } } else { - return MetricTime (0, 0, 0, raw_convert<int> (u.get ()) * 4); + return Time::from_hmsm (0, 0, 0, raw_convert<int> (u.get ()) * 4); } - - assert (false); } diff --git a/src/dcp/subtitle.h b/src/dcp/subtitle.h index 95c96cf..672dc9a 100644 --- a/src/dcp/subtitle.h +++ b/src/dcp/subtitle.h @@ -20,7 +20,7 @@ #ifndef LIBSUB_DCP_SUBTITLE_H #define LIBSUB_DCP_SUBTITLE_H -#include "../time_pair.h" +#include "../sub_time.h" #include <boost/shared_ptr.hpp> #include <boost/optional.hpp> #include <list> @@ -39,16 +39,16 @@ class Subtitle { public: Subtitle () {} - Subtitle (boost::shared_ptr<const cxml::Node> node, bool smpte); + Subtitle (boost::shared_ptr<const cxml::Node> node, boost::optional<int> tcr); - TimePair in; - TimePair out; - TimePair fade_up_time; - TimePair fade_down_time; + Time in; + Time out; + Time fade_up_time; + Time fade_down_time; private: - boost::optional<FrameTime> smpte_time (boost::shared_ptr<const cxml::Node> node, std::string name); - boost::optional<MetricTime> interop_time (boost::shared_ptr<const cxml::Node> node, std::string name); + boost::optional<Time> smpte_time (boost::shared_ptr<const cxml::Node> node, std::string name, int tcr); + boost::optional<Time> interop_time (boost::shared_ptr<const cxml::Node> node, std::string name); }; } diff --git a/src/dcp_reader.cc b/src/dcp_reader.cc index dbe318c..e83f79c 100644 --- a/src/dcp_reader.cc +++ b/src/dcp_reader.cc @@ -31,20 +31,21 @@ using std::list; using std::cout; using std::string; using boost::shared_ptr; +using boost::optional; using namespace sub; void -DCPReader::parse_common (cxml::NodePtr root, bool smpte) +DCPReader::parse_common (cxml::NodePtr root, optional<int> tcr) { _reel_number = root->string_child ("ReelNumber"); _language = root->string_child ("Language"); ParseState parse_state; - parse_node (root->node(), parse_state, smpte); + parse_node (root->node(), parse_state, tcr); } void -DCPReader::parse_node (xmlpp::Node const * node, ParseState& parse_state, bool smpte) +DCPReader::parse_node (xmlpp::Node const * node, ParseState& parse_state, optional<int> tcr) { xmlpp::Node::NodeList children = node->get_children (); for (xmlpp::Node::NodeList::const_iterator i = children.begin(); i != children.end(); ++i) { @@ -58,18 +59,18 @@ DCPReader::parse_node (xmlpp::Node const * node, ParseState& parse_state, bool s cxml::ConstNodePtr n (new cxml::Node (e)); if (n->name() == "Font") { parse_state.font_nodes.push_back (shared_ptr<dcp::Font> (new dcp::Font (n))); - parse_node (e, parse_state, smpte); + parse_node (e, parse_state, tcr); parse_state.font_nodes.pop_back (); } else if (n->name() == "Text") { parse_state.text_nodes.push_back (shared_ptr<dcp::Text> (new dcp::Text (n))); - parse_node (e, parse_state, smpte); + parse_node (e, parse_state, tcr); parse_state.text_nodes.pop_back (); } else if (n->name() == "Subtitle") { - parse_state.subtitle_nodes.push_back (shared_ptr<dcp::Subtitle> (new dcp::Subtitle (n, smpte))); - parse_node (e, parse_state, smpte); + parse_state.subtitle_nodes.push_back (shared_ptr<dcp::Subtitle> (new dcp::Subtitle (n, tcr))); + parse_node (e, parse_state, tcr); parse_state.subtitle_nodes.pop_back (); } else if (n->name() == "SubtitleList") { - parse_node (e, parse_state, smpte); + parse_node (e, parse_state, tcr); } } } diff --git a/src/dcp_reader.h b/src/dcp_reader.h index 07324b4..f749f82 100644 --- a/src/dcp_reader.h +++ b/src/dcp_reader.h @@ -46,12 +46,12 @@ protected: std::list<boost::shared_ptr<dcp::Subtitle> > subtitle_nodes; }; - void parse_common (cxml::NodePtr root, bool smpte); + void parse_common (cxml::NodePtr root, boost::optional<int> tcr); std::string _id; private: - void parse_node (xmlpp::Node const * node, ParseState& parse_state, bool smtpe); + void parse_node (xmlpp::Node const * node, ParseState& parse_state, boost::optional<int> tcr); void maybe_add_subtitle (std::string text, ParseState const & parse_state); std::string _reel_number; diff --git a/src/exceptions.h b/src/exceptions.h index 4ec931e..8602517 100644 --- a/src/exceptions.h +++ b/src/exceptions.h @@ -91,6 +91,22 @@ public: {} }; +class UnknownFrameRateException : public MessageError +{ +public: + UnknownFrameRateException () + : MessageError ("subtitle frame rate required but not known") + {} +}; + +class UnsupportedFrameRateException : public MessageError +{ +public: + UnsupportedFrameRateException () + : MessageError ("frame rate not supported") + {} +}; + } #endif diff --git a/src/frame_rate.cc b/src/frame_rate.cc new file mode 100644 index 0000000..efc87d1 --- /dev/null +++ b/src/frame_rate.cc @@ -0,0 +1,59 @@ +/* + Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "frame_rate.h" +#include "exceptions.h" +#include <cmath> + +double +sub::enum_to_value (FrameRate r) +{ + switch (r) { + case TWENTY_THREE_DROP: + return 23.976; + case TWENTY_FOUR: + return 24; + case TWENTY_FIVE: + return 25; + case THIRTY_DROP: + return 29.97; + case THIRTY: + return 30; + } + + return TWENTY_FOUR; +} + +sub::FrameRate +sub::value_to_enum (double r) +{ + if (fabs (r - 23.976) < 0.001) { + return TWENTY_THREE_DROP; + } else if (fabs (r - 24) < 0.001) { + return TWENTY_FOUR; + } else if (fabs (r - 25) < 0.001) { + return TWENTY_FIVE; + } else if (fabs (r - 29.97) < 0.001) { + return THIRTY_DROP; + } else if (fabs (r - 30) < 0.001) { + return THIRTY; + } + + throw UnsupportedFrameRateException (); +} diff --git a/src/frame_rate.h b/src/frame_rate.h new file mode 100644 index 0000000..dd973ed --- /dev/null +++ b/src/frame_rate.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef LIBSUB_FRAME_RATE_H +#define LIBSUB_FRAME_RATE_H + +namespace sub { + +enum FrameRate { + TWENTY_THREE_DROP, + TWENTY_FOUR, + TWENTY_FIVE, + THIRTY_DROP, + THIRTY +}; + +extern double enum_to_value (FrameRate); +extern FrameRate value_to_enum (double); + +} + +#endif diff --git a/src/frame_time.cc b/src/frame_time.cc deleted file mode 100644 index c67bd68..0000000 --- a/src/frame_time.cc +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "frame_time.h" -#include "compose.hpp" -#include <iostream> - -using std::ostream; -using std::string; -using namespace sub; - -bool -sub::operator== (FrameTime const & a, FrameTime const & b) -{ - return a.hours() == b.hours() && a.minutes() == b.minutes() && a.seconds() == b.seconds() && a.frames() == b.frames(); -} - -bool -sub::operator< (FrameTime const & a, FrameTime const & b) -{ - if (a.hours() != b.hours()) { - return a.hours() < b.hours(); - } - - if (a.minutes() != b.minutes()) { - return a.minutes() < b.minutes(); - } - - if (a.seconds() != b.seconds()) { - return a.seconds() < b.seconds(); - } - - return a.frames() < b.frames(); -} - -bool -sub::operator> (FrameTime const & a, FrameTime const & b) -{ - if (a.hours() != b.hours()) { - return a.hours() > b.hours(); - } - - if (a.minutes() != b.minutes()) { - return a.minutes() > b.minutes(); - } - - if (a.seconds() != b.seconds()) { - return a.seconds() > b.seconds(); - } - - return a.frames() > b.frames(); -} - -ostream& -sub::operator<< (ostream& s, FrameTime const & t) -{ - s << t.hours() << ":" << t.minutes() << ":" << t.seconds() << ":" << t.frames(); - return s; -} - -string -FrameTime::timecode () const -{ - return String::compose ("%1:%2:%3:%4", _hours, _minutes, _seconds, _frames); -} - -FrameTime::FrameTime (int64_t f, float fps) -{ - set_from_frames (f, fps); -} - -void -FrameTime::set_from_frames (int64_t f, float fps) -{ - _hours = f / (60 * 60 * fps); - f -= _hours * 60 * 60 * fps; - _minutes = f / (60 * fps); - f -= _minutes * 60 * fps; - _seconds = f / fps; - f -= _seconds * fps; - _frames = int (f); -} - -void -FrameTime::add (FrameTime t, float fps) -{ - _frames += t.frames (); - if (_frames > fps) { - _frames -= fps; - _seconds++; - } - - _seconds += t.seconds (); - if (_seconds >= 60) { - _seconds -= 60; - ++_minutes; - } - - _minutes += t.minutes (); - if (_minutes >= 60) { - _minutes -= 60; - ++_hours; - } - - _hours += t.hours (); -} - -void -FrameTime::scale (float f, float frames_per_second) -{ - set_from_frames ( - (((_hours * 3600 + _minutes * 60 + _seconds) * frames_per_second) + _frames) * f, - frames_per_second - ); -} diff --git a/src/frame_time.h b/src/frame_time.h deleted file mode 100644 index 9125791..0000000 --- a/src/frame_time.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef LIBSUB_FRAME_TIME_H -#define LIBSUB_FRAME_TIME_H - -#include <iostream> -#include <stdint.h> - -namespace sub { - -/** @class FrameTime - * @brief A time stored in hours, minutes, seconds and frames. - */ -class FrameTime -{ -public: - FrameTime () - : _hours (0) - , _minutes (0) - , _seconds (0) - , _frames (0) - {} - - /** @param f Number of frames. - * @param fps Frames per second. - */ - FrameTime (int64_t f, float fps); - - FrameTime (int h, int m, int s, int f) - : _hours (h) - , _minutes (m) - , _seconds (s) - , _frames (f) - {} - - int hours () const { - return _hours; - } - - int minutes () const { - return _minutes; - } - - int seconds () const { - return _seconds; - } - - int frames () const { - return _frames; - } - - std::string timecode () const; - - void add (FrameTime t, float fps); - void scale (float f, float fps); - -private: - void set_from_frames (int64_t f, float fps); - - int _hours; - int _minutes; - int _seconds; - int _frames; -}; - -bool operator== (FrameTime const & a, FrameTime const & b); -bool operator< (FrameTime const & a, FrameTime const & b); -bool operator> (FrameTime const & a, FrameTime const & b); -std::ostream& operator<< (std::ostream&, FrameTime const & t); - -} - -#endif diff --git a/src/interop_dcp_reader.cc b/src/interop_dcp_reader.cc index 5767b05..5751dcd 100644 --- a/src/interop_dcp_reader.cc +++ b/src/interop_dcp_reader.cc @@ -26,6 +26,7 @@ using std::list; using boost::shared_ptr; +using boost::optional; using namespace sub; InteropDCPReader::InteropDCPReader (boost::filesystem::path file) @@ -37,5 +38,5 @@ InteropDCPReader::InteropDCPReader (boost::filesystem::path file) _movie_title = xml->string_child ("MovieTitle"); _load_font_nodes = type_children<dcp::InteropLoadFont> (xml, "LoadFont"); - parse_common (xml, false); + parse_common (xml, optional<int> ()); } diff --git a/src/metric_time.cc b/src/metric_time.cc deleted file mode 100644 index 4fad390..0000000 --- a/src/metric_time.cc +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "metric_time.h" -#include "compose.hpp" -#include <iostream> -#include <cmath> - -using std::ostream; -using std::string; -using std::cout; -using namespace sub; - -MetricTime::MetricTime (int h, int m, int s, int ms) - /* cast up to int64_t to force a 64-bit calculation */ - : _ms ((int64_t (h) * 3600 + m * 60 + s) * 1000 + ms) -{ - -} - -void -MetricTime::split (int& h, int &m, int& s, int& ms) const -{ - int64_t w = _ms; - h = floor (w / (3600 * 1000)); - /* this multiply could overflow 32 bits so cast to make sure it is done as 64-bit */ - w -= int64_t (h) * (3600 * 1000); - m = floor (w / (60 * 1000)); - w -= m * (60 * 1000); - s = floor (w / 1000); - w -= s * 1000; - ms = w; -} - -int -MetricTime::hours () const -{ - int h, m, s, ms; - split (h, m, s, ms); - return h; -} - -int -MetricTime::minutes () const -{ - int h, m, s, ms; - split (h, m, s, ms); - return m; -} - -int -MetricTime::seconds () const -{ - int h, m, s, ms; - split (h, m, s, ms); - return s; -} - -int -MetricTime::milliseconds () const -{ - int h, m, s, ms; - split (h, m, s, ms); - return ms; -} - -void -MetricTime::add (MetricTime t) -{ - _ms += t._ms; -} - -void -MetricTime::scale (float f) -{ - _ms *= f; -} - -bool -sub::operator== (MetricTime const & a, MetricTime const & b) -{ - return a._ms == b._ms; -} - -bool -sub::operator> (MetricTime const & a, MetricTime const & b) -{ - return a._ms > b._ms; -} - -bool -sub::operator< (MetricTime const & a, MetricTime const & b) -{ - return a._ms < b._ms; -} - -ostream& -sub::operator<< (ostream& st, MetricTime const & t) -{ - int h, m, s, ms; - t.split (h, m, s, ms); - st << h << ":" << m << ":" << s << ":" << ms; - return st; -} diff --git a/src/metric_time.h b/src/metric_time.h deleted file mode 100644 index 404464e..0000000 --- a/src/metric_time.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef LIBSUB_METRIC_TIME_H -#define LIBSUB_METRIC_TIME_H - -#include <stdint.h> -#include <iostream> - -namespace sub { - -/** @class MetricTime - * @brief A time stored in milliseconds. - */ -class MetricTime -{ -public: - MetricTime () - : _ms (0) - {} - - MetricTime (int h, int m, int s, int ms); - - int hours () const; - int minutes () const; - int seconds () const; - int milliseconds () const; - - double all_as_seconds () const { - return all_as_milliseconds() / 1000.0; - } - - int64_t all_as_milliseconds () const { - return _ms; - } - - void add (MetricTime t); - void scale (float f); - -private: - void split (int& h, int& m, int& s, int& ms) const; - - friend bool operator== (MetricTime const & a, MetricTime const & b); - friend bool operator> (MetricTime const & a, MetricTime const & b); - friend bool operator< (MetricTime const & a, MetricTime const & b); - friend std::ostream& operator<< (std::ostream&, MetricTime const & t); - - int64_t _ms; -}; - -bool operator== (MetricTime const & a, MetricTime const & b); -bool operator> (MetricTime const & a, MetricTime const & b); -bool operator< (MetricTime const & a, MetricTime const & b); -std::ostream& operator<< (std::ostream&, MetricTime const & t); - -} - -#endif diff --git a/src/raw_subtitle.cc b/src/raw_subtitle.cc index 24f1a8e..818bb15 100644 --- a/src/raw_subtitle.cc +++ b/src/raw_subtitle.cc @@ -24,13 +24,5 @@ using namespace sub; bool sub::operator< (RawSubtitle const & a, RawSubtitle const & b) { - if (a.from.frame() && b.from.frame()) { - return a.from.frame().get() < b.from.frame().get(); - } - - if (a.from.metric() && b.from.metric()) { - return a.from.metric().get() < b.from.metric().get(); - } - - assert (false); + return a.from < b.from; } diff --git a/src/raw_subtitle.h b/src/raw_subtitle.h index fdd7331..d812d34 100644 --- a/src/raw_subtitle.h +++ b/src/raw_subtitle.h @@ -20,13 +20,11 @@ #ifndef LIBSUB_RAW_SUBTITLE_H #define LIBSUB_RAW_SUBTITLE_H -#include "frame_time.h" -#include "metric_time.h" #include "colour.h" #include "vertical_reference.h" #include "effect.h" -#include "time_pair.h" #include "font_size.h" +#include "sub_time.h" #include "vertical_position.h" #include <boost/optional.hpp> #include <string> @@ -68,16 +66,16 @@ public: VerticalPosition vertical_position; /** from time */ - TimePair from; + Time from; /** to time */ - TimePair to; + Time to; - boost::optional<TimePair> fade_up; - boost::optional<TimePair> fade_down; + boost::optional<Time> fade_up; + boost::optional<Time> fade_down; }; -bool operator< (RawSubtitle const &, RawSubtitle const &); - +bool operator< (RawSubtitle const &, RawSubtitle const &); + } #endif diff --git a/src/reader_factory.cc b/src/reader_factory.cc index 2652763..1a7a6f2 100644 --- a/src/reader_factory.cc +++ b/src/reader_factory.cc @@ -32,8 +32,9 @@ using boost::algorithm::ends_with; using boost::shared_ptr; using namespace sub; +/** @param frame_rate Frame rate to use if the file does not specify one */ shared_ptr<Reader> -sub::reader_factory (boost::filesystem::path file_name) +sub::reader_factory (boost::filesystem::path file_name, sub::FrameRate frame_rate) { string ext = file_name.extension().string(); transform (ext.begin(), ext.end(), ext.begin(), ::tolower); @@ -65,7 +66,7 @@ sub::reader_factory (boost::filesystem::path file_name) if (f.gcount() == 11 && buffer[3] == 'S' && buffer[4] == 'T' && buffer[5] == 'L') { return shared_ptr<Reader> (new STLBinaryReader (f)); } else { - return shared_ptr<Reader> (new STLTextReader (f)); + return shared_ptr<Reader> (new STLTextReader (f, frame_rate)); } } diff --git a/src/reader_factory.h b/src/reader_factory.h index e7c349b..916502c 100644 --- a/src/reader_factory.h +++ b/src/reader_factory.h @@ -17,6 +17,7 @@ */ +#include "frame_rate.h" #include <boost/shared_ptr.hpp> #include <boost/filesystem.hpp> @@ -25,6 +26,6 @@ namespace sub { class Reader; extern boost::shared_ptr<Reader> -reader_factory (boost::filesystem::path); +reader_factory (boost::filesystem::path, sub::FrameRate); } diff --git a/src/smpte_dcp_reader.cc b/src/smpte_dcp_reader.cc index b60cc8b..6014196 100644 --- a/src/smpte_dcp_reader.cc +++ b/src/smpte_dcp_reader.cc @@ -63,5 +63,5 @@ SMPTEDCPReader::SMPTEDCPReader (boost::filesystem::path file, bool mxf) _load_font_nodes = type_children<dcp::SMPTELoadFont> (xml, "LoadFont"); - parse_common (xml, true); + parse_common (xml, xml->number_child<int> ("TimeCodeRate")); } diff --git a/src/stl_binary_reader.cc b/src/stl_binary_reader.cc index 2246a01..8a4bd1b 100644 --- a/src/stl_binary_reader.cc +++ b/src/stl_binary_reader.cc @@ -95,8 +95,8 @@ STLBinaryReader::STLBinaryReader (istream& in) for (size_t i = 0; i < lines.size(); ++i) { RawSubtitle sub; - sub.from.set_frame (get_timecode (5)); - sub.to.set_frame (get_timecode (9)); + sub.from = get_timecode (5); + sub.to = get_timecode (9); sub.vertical_position.line = get_int (13, 1) + i; sub.vertical_position.lines = maximum_rows; sub.vertical_position.reference = TOP_OF_SCREEN; @@ -174,10 +174,10 @@ STLBinaryReader::get_int (int offset, int length) const return v; } -FrameTime +Time STLBinaryReader::get_timecode (int offset) const { - return FrameTime (_buffer[offset], _buffer[offset + 1], _buffer[offset + 2], _buffer[offset + 3]); + return Time::from_hmsf (_buffer[offset], _buffer[offset + 1], _buffer[offset + 2], _buffer[offset + 3]); } map<string, string> diff --git a/src/stl_binary_reader.h b/src/stl_binary_reader.h index a637e91..40bc5b7 100644 --- a/src/stl_binary_reader.h +++ b/src/stl_binary_reader.h @@ -21,6 +21,8 @@ #define LIBSUB_STL_BINARY_READER_H #include "reader.h" +#include "frame_rate.h" +#include "sub_time.h" #include "stl_binary_tables.h" #include <map> @@ -38,7 +40,7 @@ public: std::map<std::string, std::string> metadata () const; int code_page_number; - int frame_rate; + FrameRate frame_rate; DisplayStandard display_standard; LanguageGroup language_group; Language language; @@ -70,7 +72,7 @@ public: private: std::string get_string (int, int) const; int get_int (int, int) const; - FrameTime get_timecode (int) const; + Time get_timecode (int) const; STLBinaryTables _tables; unsigned char* _buffer; diff --git a/src/stl_binary_writer.cc b/src/stl_binary_writer.cc index b9ad86f..dedac84 100644 --- a/src/stl_binary_writer.cc +++ b/src/stl_binary_writer.cc @@ -92,7 +92,7 @@ put_int_as_int (char* p, int v, unsigned int n) void sub::write_stl_binary ( list<Subtitle> subtitles, - float frames_per_second, + FrameRate frame_rate, Language language, string original_programme_title, string original_episode_title, @@ -148,7 +148,7 @@ sub::write_stl_binary ( /* Code page: 850 */ put_string (buffer + 0, "850"); /* Disk format code */ - put_string (buffer + 3, stl_frame_rate_to_dfc (frames_per_second)); + put_string (buffer + 3, stl_frame_rate_to_dfc (frame_rate)); /* Display standard code: open subtitling */ put_string (buffer + 11, "0"); /* Character code table: Latin (ISO 6937) */ @@ -209,15 +209,15 @@ sub::write_stl_binary ( /* Cumulative status */ put_int_as_int (buffer + 4, tables.cumulative_status_enum_to_file (CUMULATIVE_STATUS_NOT_CUMULATIVE), 1); /* Time code in */ - put_int_as_int (buffer + 5, i->from.frame(frames_per_second).hours (), 1); - put_int_as_int (buffer + 6, i->from.frame(frames_per_second).minutes (), 1); - put_int_as_int (buffer + 7, i->from.frame(frames_per_second).seconds (), 1); - put_int_as_int (buffer + 8, i->from.frame(frames_per_second).frames (), 1); + put_int_as_int (buffer + 5, i->from.hours, 1); + put_int_as_int (buffer + 6, i->from.minutes, 1); + put_int_as_int (buffer + 7, i->from.seconds, 1); + put_int_as_int (buffer + 8, i->from.frames (frame_rate), 1); /* Time code out */ - put_int_as_int (buffer + 9, i->to.frame(frames_per_second).hours (), 1); - put_int_as_int (buffer + 10, i->to.frame(frames_per_second).minutes (), 1); - put_int_as_int (buffer + 11, i->to.frame(frames_per_second).seconds (), 1); - put_int_as_int (buffer + 12, i->to.frame(frames_per_second).frames (), 1); + put_int_as_int (buffer + 9, i->to.hours, 1); + put_int_as_int (buffer + 10, i->to.minutes, 1); + put_int_as_int (buffer + 11, i->to.seconds, 1); + put_int_as_int (buffer + 12, i->to.frames (frame_rate), 1); /* Vertical position */ int vp = 0; if (j->vertical_position.proportional) { diff --git a/src/stl_binary_writer.h b/src/stl_binary_writer.h index 4986afb..afddffa 100644 --- a/src/stl_binary_writer.h +++ b/src/stl_binary_writer.h @@ -25,6 +25,7 @@ #define LIBSUB_STL_BINARY_WRITER_H #include "stl_binary_tables.h" +#include "frame_rate.h" #include <string> #include <boost/filesystem.hpp> @@ -34,7 +35,7 @@ class Subtitle; extern void write_stl_binary ( std::list<Subtitle> subtitles, - float frames_per_second, + FrameRate frames_per_second, Language language, std::string original_programme_title, std::string original_episode_title, diff --git a/src/stl_text_reader.cc b/src/stl_text_reader.cc index b86a656..d5e701f 100644 --- a/src/stl_text_reader.cc +++ b/src/stl_text_reader.cc @@ -36,7 +36,8 @@ using boost::optional; using boost::lexical_cast; using namespace sub; -STLTextReader::STLTextReader (istream& in) +STLTextReader::STLTextReader (istream& in, sub::FrameRate frame_rate) + : _frame_rate (frame_rate) { _subtitle.vertical_position.line = 0; /* XXX: no idea what this should be */ @@ -88,16 +89,16 @@ STLTextReader::STLTextReader (istream& in) string to_string = line.substr (divider[0] + 1, divider[1] - divider[0] - 1); trim (to_string); - optional<FrameTime> from = time (from_string); - optional<FrameTime> to = time (to_string); + optional<Time> from = time (from_string); + optional<Time> to = time (to_string); if (!from || !to) { warn (String::compose ("Unrecognised line %1", line)); continue; } - _subtitle.from.set_frame (from.get ()); - _subtitle.to.set_frame (to.get ()); + _subtitle.from = from.get (); + _subtitle.to = to.get (); /* Parse ^B/^I/^U */ string text = line.substr (divider[1] + 1); @@ -131,17 +132,17 @@ STLTextReader::STLTextReader (istream& in) } } -optional<FrameTime> +optional<Time> STLTextReader::time (string t) const { vector<string> b; split (b, t, is_any_of (":")); if (b.size() != 4) { warn (String::compose ("Unrecognised time %1", t)); - return optional<FrameTime> (); + return optional<Time> (); } - return FrameTime (lexical_cast<int> (b[0]), lexical_cast<int> (b[1]), lexical_cast<int> (b[2]), lexical_cast<int> (b[3])); + return Time::from_hmsf (lexical_cast<int> (b[0]), lexical_cast<int> (b[1]), lexical_cast<int> (b[2]), lexical_cast<int> (b[3]), _frame_rate); } void diff --git a/src/stl_text_reader.h b/src/stl_text_reader.h index 77e9b73..026e38f 100644 --- a/src/stl_text_reader.h +++ b/src/stl_text_reader.h @@ -31,14 +31,15 @@ namespace sub { class STLTextReader : public Reader { public: - STLTextReader (std::istream &); + STLTextReader (std::istream &, sub::FrameRate frame_rate); private: void set (std::string name, std::string value); void maybe_push (); - boost::optional<FrameTime> time (std::string t) const; + boost::optional<Time> time (std::string t) const; RawSubtitle _subtitle; + sub::FrameRate _frame_rate; }; } diff --git a/src/stl_util.cc b/src/stl_util.cc index c145a34..2ee0100 100644 --- a/src/stl_util.cc +++ b/src/stl_util.cc @@ -26,40 +26,38 @@ using std::string; using namespace sub; -bool -about_equal (float a, float b) -{ - return fabs (a - b) < 1e-4; -} - string -sub::stl_frame_rate_to_dfc (float r) +sub::stl_frame_rate_to_dfc (FrameRate r) { /* This is the FAB Subtitler mapping, as used by Annotation Edit */ - if (about_equal (r, 23.976)) { + switch (r) { + case TWENTY_THREE_DROP: return "STL24.01"; - } else if (about_equal (r, 24)) { + case TWENTY_FOUR: return "STL23.01"; - } else if (about_equal (r, 25)) { + case TWENTY_FIVE: return "STL25.01"; - } else if (about_equal (r, 30)) { + case THIRTY_DROP: + /* XXX: not right, but I don't think there is a value for this */ + return "STL30.01"; + case THIRTY: return "STL30.01"; } return "STL25.01"; } -float +FrameRate sub::stl_dfc_to_frame_rate (string s) { if (s == "STL24.01") { - return 23.976; + return TWENTY_THREE_DROP; } else if (s == "STL23.01") { - return 24; + return TWENTY_FOUR; } else if (s == "STL25.01") { - return 25; + return TWENTY_FIVE; } else if (s == "STL30.01") { - return 30; + return THIRTY; } throw STLError (String::compose ("Unknown disk format code %1 in binary STL file", s)); diff --git a/src/stl_util.h b/src/stl_util.h index 0da8215..a5c98ed 100644 --- a/src/stl_util.h +++ b/src/stl_util.h @@ -17,11 +17,12 @@ */ +#include "frame_rate.h" #include <string> namespace sub { -std::string stl_frame_rate_to_dfc (float r); -float stl_dfc_to_frame_rate (std::string s); +std::string stl_frame_rate_to_dfc (FrameRate r); +FrameRate stl_dfc_to_frame_rate (std::string s); } diff --git a/src/sub_time.cc b/src/sub_time.cc new file mode 100644 index 0000000..780dbc9 --- /dev/null +++ b/src/sub_time.cc @@ -0,0 +1,196 @@ +/* + Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "sub_time.h" +#include "exceptions.h" +#include <cmath> + +using std::ostream; +using boost::optional; +using namespace sub; + +/** @return The whole time as a number of milliseconds */ +int64_t +Time::as_milliseconds () const +{ + if (_frames && !_frame_rate) { + throw UnknownFrameRateException (); + } + + int64_t s = (int64_t (hours) * 3600 + minutes * 60 + seconds) * 1000; + if (_frames) { + s += rint (_frames.get() * 1000 / enum_to_value (_frame_rate.get ())); + } else { + s += _milliseconds.get(); + } + + return s; +} + +int +Time::frames (FrameRate r) const +{ + if (_frames && !_frame_rate) { + throw UnknownFrameRateException (); + } + + if (_frames) { + if (_frame_rate == r) { + return _frames.get(); + } else { + return rint (double (_frames.get()) * enum_to_value (r) / _frame_rate.get()); + } + } else { + return rint (double (_milliseconds.get()) * enum_to_value (r) / 1000); + } +} + +Time +Time::from_hmsf (int h, int m, int s, int f) +{ + return Time (h, m, s, optional<int> (), f, optional<FrameRate> ()); +} + +Time +Time::from_hmsf (int h, int m, int s, int f, sub::FrameRate r) +{ + return Time (h, m, s, optional<int> (), f, r); +} + +Time +Time::from_hms (int h, int m, double s) +{ + int const is = int (s); + return Time (h, m, is, rint ((s - is) * 1000), optional<int> (), optional<FrameRate> ()); +} + +Time +Time::from_hmsm (int h, int m, int s, int ms) +{ + return Time (h, m, s, ms, optional<int> (), optional<FrameRate> ()); +} + +bool +Time::operator< (Time const & other) const +{ + if ((_frames && !_frame_rate) || (other._frames && !other._frame_rate)) { + throw UnknownFrameRateException (); + } + + if (hours != other.hours) { + return hours < other.hours; + } + + if (minutes != other.minutes) { + return minutes < other.minutes; + } + + if (seconds != other.seconds) { + return seconds < other.seconds; + } + + /* Both frames with the same rate */ + if (_frames && other._frames && _frame_rate.get() == other._frame_rate.get()) { + return _frames.get() < other._frames.get(); + } + + /* Otherwise we have to do it by comparing milliseconds */ + return as_milliseconds() < other.as_milliseconds(); +} + +bool +Time::operator> (Time const & other) const +{ + if ((_frames && !_frame_rate) || (other._frames && !other._frame_rate)) { + throw UnknownFrameRateException (); + } + + if (hours != other.hours) { + return hours > other.hours; + } + + if (minutes != other.minutes) { + return minutes > other.minutes; + } + + if (seconds != other.seconds) { + return seconds > other.seconds; + } + + /* Both frames with the same rate */ + if (_frames && other._frames && _frame_rate.get() == other._frame_rate.get()) { + return _frames.get() > other._frames.get(); + } + + /* Otherwise we have to do it by comparing milliseconds */ + return as_milliseconds() > other.as_milliseconds(); +} + +bool +Time::operator== (Time const & other) const +{ + if (hours != other.hours || minutes != other.minutes || seconds != other.seconds) { + return false; + } + + if ((_frames && !_frame_rate) || (other._frames && !other._frame_rate)) { + throw UnknownFrameRateException (); + } + + /* Both frames with the same rate */ + if (_frames && other._frames && _frame_rate.get() == other._frame_rate.get()) { + return _frames.get() == other._frames.get(); + } + + /* Otherwise we have to do it by comparing milliseconds */ + return abs (as_milliseconds() - other.as_milliseconds()) <= 1; +} + +bool +Time::operator!= (Time const & other) const +{ + return !(*this == other); +} + +ostream & +sub::operator<< (ostream& s, Time const & t) +{ + s << t.hours << "h " << t.minutes << "m " << t.seconds << "s "; + if (t._frames) { + s << t._frames.get() << "f"; + } + if (t._frame_rate) { + s << " @ " << enum_to_value (t._frame_rate.get ()); + } + if (t._milliseconds) { + s << t._milliseconds.get() << "ms"; + } + return s; +} + +Time::Time (int h, int m, int s, optional<int> ms, optional<int> f, optional<FrameRate> r) + : hours (h) + , minutes (m) + , seconds (s) + , _milliseconds (ms) + , _frames (f) + , _frame_rate (r) +{ + +} diff --git a/src/sub_time.h b/src/sub_time.h new file mode 100644 index 0000000..4b3f0e1 --- /dev/null +++ b/src/sub_time.h @@ -0,0 +1,75 @@ +/* + Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef LIBSUB_SUB_TIME_H +#define LIBSUB_SUB_TIME_H + +#include "frame_rate.h" +#include <boost/optional.hpp> + +struct time_construction_test; + +namespace sub { + +class Time +{ +public: + Time () + : hours (0) + , minutes (0) + , seconds (0) + {} + + int hours; + int minutes; + int seconds; + + /** @return the frames part of the time at a particular frame rate */ + int frames (FrameRate r) const; + + /** @return the whole time in milliseconds */ + int64_t as_milliseconds () const; + + static Time from_hmsf (int h, int m, int s, int f); + static Time from_hmsf (int h, int m, int s, int f, FrameRate r); + static Time from_hms (int h, int m, double s); + static Time from_hmsm (int h, int m, int s, int ms); + + bool operator== (Time const & other) const; + bool operator!= (Time const & other) const; + bool operator< (Time const & other) const; + bool operator> (Time const & other) const; + +private: + friend std::ostream & operator<< (std::ostream& s, Time const & t); + + friend struct ::time_construction_test; + + Time (int h, int m, int s, boost::optional<int> ms, boost::optional<int> f, boost::optional<FrameRate> r); + + boost::optional<int> _milliseconds; + boost::optional<int> _frames; + boost::optional<FrameRate> _frame_rate; +}; + +std::ostream& operator<< (std::ostream& s, Time const & t); + +} + +#endif diff --git a/src/subrip_reader.cc b/src/subrip_reader.cc index 0aba120..20b234d 100644 --- a/src/subrip_reader.cc +++ b/src/subrip_reader.cc @@ -39,8 +39,8 @@ SubripReader::SubripReader (FILE* f) char buffer[256]; - TimePair from; - TimePair to; + Time from; + Time to; string line; int line_number = 0; @@ -94,7 +94,7 @@ SubripReader::SubripReader (FILE* f) } } -TimePair +Time SubripReader::convert_time (string t) { vector<string> a; @@ -106,18 +106,16 @@ SubripReader::convert_time (string t) vector<string> b; boost::algorithm::split (b, a[2], boost::is_any_of (",")); - return TimePair ( - MetricTime ( - lexical_cast<int> (a[0]), - lexical_cast<int> (a[1]), - lexical_cast<int> (b[0]), - lexical_cast<int> (b[1]) - ) + return Time::from_hmsm ( + lexical_cast<int> (a[0]), + lexical_cast<int> (a[1]), + lexical_cast<int> (b[0]), + lexical_cast<int> (b[1]) ); } void -SubripReader::convert_line (string t, int line_number, TimePair from, TimePair to) +SubripReader::convert_line (string t, int line_number, Time from, Time to) { enum { TEXT, diff --git a/src/subrip_reader.h b/src/subrip_reader.h index 9b9ff92..a010f4a 100644 --- a/src/subrip_reader.h +++ b/src/subrip_reader.h @@ -21,7 +21,6 @@ #define LIBSUB_SUBRIP_READER_H #include "reader.h" -#include "time_pair.h" struct subrip_reader_convert_line_test; struct subrip_reader_convert_time_test; @@ -39,8 +38,8 @@ private: friend struct ::subrip_reader_convert_time_test; SubripReader () {} - static TimePair convert_time (std::string t); - void convert_line (std::string t, int line_number, TimePair from, TimePair to); + static Time convert_time (std::string t); + void convert_line (std::string t, int line_number, Time from, Time to); void maybe_content (RawSubtitle& p); }; diff --git a/src/subtitle.cc b/src/subtitle.cc index d828628..dc316c3 100644 --- a/src/subtitle.cc +++ b/src/subtitle.cc @@ -33,7 +33,27 @@ Subtitle::Subtitle (RawSubtitle s) bool Subtitle::same_metadata (RawSubtitle s) const { - return from == s.from && to == s.to && fade_up == s.fade_up && fade_down == s.fade_down; + if (from != s.from || to != s.to) { + return false; + } + + if (fade_up && s.fade_up && fade_up.get() != s.fade_up.get()) { + return false; + } + + if ((fade_up && !s.fade_up) || (!fade_up && s.fade_up)) { + return false; + } + + if (fade_down && s.fade_down && fade_down.get() != s.fade_down.get()) { + return false; + } + + if ((fade_down && !s.fade_down) || (!fade_down && s.fade_down)) { + return false; + } + + return true; } Line::Line (RawSubtitle s) diff --git a/src/subtitle.h b/src/subtitle.h index 71dff80..d747a60 100644 --- a/src/subtitle.h +++ b/src/subtitle.h @@ -20,12 +20,10 @@ #ifndef LIBSUB_SUBTITLE_H #define LIBSUB_SUBTITLE_H -#include "frame_time.h" -#include "metric_time.h" #include "colour.h" +#include "sub_time.h" #include "vertical_reference.h" #include "effect.h" -#include "time_pair.h" #include "font_size.h" #include "vertical_position.h" #include "raw_subtitle.h" @@ -106,12 +104,12 @@ public: Subtitle (RawSubtitle s); /** from time */ - TimePair from; + Time from; /** to time */ - TimePair to; + Time to; - boost::optional<TimePair> fade_up; - boost::optional<TimePair> fade_down; + boost::optional<Time> fade_up; + boost::optional<Time> fade_down; std::list<Line> lines; diff --git a/src/time_pair.cc b/src/time_pair.cc deleted file mode 100644 index 9bad713..0000000 --- a/src/time_pair.cc +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/time_pair.cc - * @brief TimePair class. - */ - -#include "time_pair.h" -#include <cmath> - -using std::ostream; -using namespace sub; - -FrameTime -TimePair::frame (float fps) const -{ - if (_frame) { - return _frame.get (); - } - - MetricTime const m = _metric.get (); - return FrameTime (m.hours(), m.minutes(), m.seconds(), rint (m.milliseconds() * fps / 1000)); -} - -MetricTime -TimePair::metric (float fps) const -{ - if (_metric) { - return _metric.get (); - } - - FrameTime const f = _frame.get (); - return MetricTime (f.hours(), f.minutes(), f.seconds(), rint (f.frames() * 1000 / fps)); -} - -void -TimePair::add (FrameTime t, float fps) -{ - if (_frame) { - _frame.get().add (t, fps); - } else { - _metric.get().add (MetricTime (t.hours(), t.minutes(), t.seconds(), rint (t.frames() * 1000 / fps))); - } -} - -void -TimePair::scale (float f, float fps) -{ - if (_frame) { - _frame.get().scale (f, fps); - } else { - _metric.get().scale (f); - } -} - -bool -TimePair::operator== (TimePair const & other) const -{ - if (_metric && other._metric) { - return _metric.get() == other._metric.get(); - } else if (_frame && other._frame) { - return _frame.get() == other._frame.get(); - } - - return false; -} - -bool -TimePair::operator< (TimePair const & other) const -{ - if (_metric && other._metric) { - return _metric.get() < other._metric.get(); - } else if (_frame && other._frame) { - return _frame.get() < other._frame.get(); - } - - assert (false); -} - -bool -TimePair::operator<= (TimePair const & other) const -{ - return (*this == other || *this < other); -} - -bool -TimePair::operator> (TimePair const & other) const -{ - return (!(*this <= other)); -} - -bool -TimePair::operator>= (TimePair const & other) const -{ - return !(*this < other); -} - -ostream & -sub::operator<< (ostream& s, TimePair const & t) -{ - if (t.frame ()) { - s << "[FRAME] " << t.frame().get(); - } else { - s << "[METRIC]" << t.metric().get(); - } - - return s; -} diff --git a/src/time_pair.h b/src/time_pair.h deleted file mode 100644 index f06edda..0000000 --- a/src/time_pair.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/time_pair.h - * @brief TimePair class. - */ - -#ifndef LIBSUB_TIME_PAIR_H -#define LIBSUB_TIME_PAIR_H - -#include "frame_time.h" -#include "metric_time.h" -#include <boost/optional.hpp> - -namespace sub { - -/** @class TimePair - * @brief A time, expressed either in metric (h:m:s:ms) or frames (h:m:s:f). - */ -class TimePair -{ -public: - TimePair () {} - - TimePair (FrameTime t) - : _frame (t) - {} - - TimePair (MetricTime t) - : _metric (t) - {} - - void set_frame (FrameTime t) { - _frame = t; - _metric = boost::optional<MetricTime> (); - } - - void set_metric (MetricTime t) { - _metric = t; - _frame = boost::optional<FrameTime> (); - } - - boost::optional<FrameTime> frame () const { - return _frame; - } - - boost::optional<MetricTime> metric () const { - return _metric; - } - - FrameTime frame (float fps) const; - MetricTime metric (float fps) const; - - void add (FrameTime t, float fps); - void scale (float f, float fps); - - bool operator== (TimePair const & other) const; - bool operator< (TimePair const & other) const; - bool operator<= (TimePair const & other) const; - bool operator> (TimePair const & other) const; - bool operator>= (TimePair const & other) const; - -private: - boost::optional<FrameTime> _frame; - boost::optional<MetricTime> _metric; -}; - -std::ostream& operator<< (std::ostream & s, TimePair const &); - -} - -#endif diff --git a/src/wscript b/src/wscript index acb9bd6..b1a4ca4 100644 --- a/src/wscript +++ b/src/wscript @@ -15,11 +15,10 @@ def build(bld): colour.cc dcp_reader.cc effect.cc - frame_time.cc + frame_rate.cc interop_dcp_reader.cc iso6937.cc iso6937_tables.cc - metric_time.cc raw_subtitle.cc reader.cc reader_factory.cc @@ -28,8 +27,8 @@ def build(bld): stl_binary_writer.cc stl_text_reader.cc stl_util.cc - time_pair.cc smpte_dcp_reader.cc + sub_time.cc subrip_reader.cc subtitle.cc util.cc @@ -48,8 +47,6 @@ def build(bld): dcp_reader.h effect.h font_size.h - frame_time.h - metric_time.h raw_subtitle.h reader.h reader_factory.h @@ -59,7 +56,6 @@ def build(bld): stl_text_reader.h subrip_reader.h subtitle.h - time_pair.h vertical_position.h vertical_reference.h """ diff --git a/test/dcp_reader_test.cc b/test/dcp_reader_test.cc index 902e09f..026677f 100644 --- a/test/dcp_reader_test.cc +++ b/test/dcp_reader_test.cc @@ -35,10 +35,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test1) list<sub::Subtitle>::iterator i = subs.begin (); BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 0, 5, 198 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 0, 7, 115 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 4)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 4)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 0, 5, 198 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 0, 7, 115 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 4)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 4)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -61,10 +61,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test1) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 0, 7, 177 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 0, 11, 31 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 4)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 4)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 0, 7, 177 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 0, 11, 31 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 4)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 4)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -101,10 +101,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test1) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 0, 11, 94 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 0, 13, 63 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 4)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 4)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 0, 11, 94 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 0, 13, 63 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 4)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 4)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -127,10 +127,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test1) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 0, 13, 104 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 0, 15, 177 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 4)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 4)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 0, 13, 104 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 0, 15, 177 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 4)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 4)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -160,10 +160,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) list<sub::Subtitle>::iterator i = subs.begin (); BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 0, 41, 62 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 0, 43, 52 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 0, 41, 62 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 0, 43, 52 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -200,10 +200,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 0, 50, 42 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 0, 52, 21 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 0, 50, 42 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 0, 52, 21 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -240,10 +240,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 1, 2, 208 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 1, 4, 10 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 2, 208 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 4, 10 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -268,15 +268,15 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) BOOST_CHECK_EQUAL (b.italic, true); BOOST_CHECK (b.colour == sub::Colour (1, 1, 1)); BOOST_CHECK_EQUAL (b.font_size.proportional().get(), float (42) / (72 * 11)); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 1, 2, 208 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 1, 4, 10 * 4)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 2, 208 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 4, 10 * 4)); BOOST_CHECK_CLOSE (j->vertical_position.proportional.get(), 0.95, 1); BOOST_CHECK_EQUAL (j->vertical_position.reference.get(), sub::TOP_OF_SCREEN); BOOST_CHECK_EQUAL (b.text, "I spent a long weekend in Brighton"); BOOST_CHECK_EQUAL (b.effect, sub::BORDER); BOOST_CHECK (b.effect_colour.get() == sub::Colour (0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); ++j; BOOST_CHECK (j == i->lines.end ()); @@ -284,10 +284,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 1, 15, 42 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 1, 16, 42 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 15, 42 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 16, 42 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -324,10 +324,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 1, 20, 219 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 1, 22, 73 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 20, 219 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 22, 73 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -364,10 +364,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 1, 27, 115 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 1, 28, 208 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 27, 115 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 28, 208 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -404,10 +404,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 1, 42, 229 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 1, 45, 62 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 42, 229 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 45, 62 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -444,10 +444,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 1, 45, 146 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 1, 47, 94 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 45, 146 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 47, 94 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -484,10 +484,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 1, 47, 146 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 1, 48, 167 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 47, 146 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 48, 167 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -524,10 +524,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 1, 53, 21 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 1, 56, 10 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 53, 21 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 56, 10 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -564,10 +564,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test2) ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from, sub::MetricTime (0, 2, 5, 208 * 4)); - BOOST_CHECK_EQUAL (i->to, sub::MetricTime (0, 2, 7, 31 * 4)); - BOOST_CHECK_EQUAL (i->fade_up.get(), sub::MetricTime (0, 0, 0, 0)); - BOOST_CHECK_EQUAL (i->fade_down.get(), sub::MetricTime (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 2, 5, 208 * 4)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 2, 7, 31 * 4)); + BOOST_CHECK_EQUAL (i->fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 0)); + BOOST_CHECK_EQUAL (i->fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 0)); { list<sub::Line>::iterator j = i->lines.begin (); @@ -611,10 +611,10 @@ BOOST_AUTO_TEST_CASE (dcp_reader_test3) BOOST_REQUIRE_EQUAL (subs.size(), 1); sub::Subtitle sub = subs.front (); - BOOST_REQUIRE_EQUAL (sub.from, sub::MetricTime (0, 0, 5, 198 * 4)); - BOOST_REQUIRE_EQUAL (sub.to, sub::MetricTime (0, 0, 7, 115 * 4)); - BOOST_REQUIRE_EQUAL (sub.fade_up.get(), sub::MetricTime (0, 0, 0, 4)); - BOOST_REQUIRE_EQUAL (sub.fade_down.get(), sub::MetricTime (0, 0, 0, 4)); + BOOST_REQUIRE_EQUAL (sub.from, sub::Time::from_hmsm (0, 0, 5, 198 * 4)); + BOOST_REQUIRE_EQUAL (sub.to, sub::Time::from_hmsm (0, 0, 7, 115 * 4)); + BOOST_REQUIRE_EQUAL (sub.fade_up.get(), sub::Time::from_hmsm (0, 0, 0, 4)); + BOOST_REQUIRE_EQUAL (sub.fade_down.get(), sub::Time::from_hmsm (0, 0, 0, 4)); BOOST_REQUIRE_EQUAL (sub.lines.size(), 1); sub::Line line = sub.lines.front (); diff --git a/test/dcp_to_stl_binary_test.cc b/test/dcp_to_stl_binary_test.cc index 6199c69..a3a7787 100644 --- a/test/dcp_to_stl_binary_test.cc +++ b/test/dcp_to_stl_binary_test.cc @@ -37,7 +37,7 @@ BOOST_AUTO_TEST_CASE (dcp_to_stl_binary_test1) boost::filesystem::path p = private_test / "fd586c30-6d38-48f2-8241-27359acf184c_sub.xml"; sub::write_stl_binary ( sub::collect<list<sub::Subtitle> > (sub::InteropDCPReader(p).subtitles ()), - 25, + sub::TWENTY_FIVE, sub::LANGUAGE_FRENCH, "", "", "", "", @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE (dcp_to_stl_binary_test2) boost::filesystem::path p = private_test / "93e8a6bf-499e-4d36-9350-a9bfa2e6758a_sub.xml"; sub::write_stl_binary ( sub::collect<list<sub::Subtitle> > (sub::InteropDCPReader(p).subtitles ()), - 25, + sub::TWENTY_FIVE, sub::LANGUAGE_FRENCH, "", "", "", "", @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE (dcp_to_stl_binary_test3) boost::filesystem::path p = private_test / "Paddington_FTR_Subs_DE-FR_24fps_R1.xml"; sub::write_stl_binary ( sub::collect<list<sub::Subtitle> > (sub::InteropDCPReader(p).subtitles ()), - 25, + sub::TWENTY_FIVE, sub::LANGUAGE_FRENCH, "", "", "", "", @@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE (dcp_to_stl_binary_test4) { sub::write_stl_binary ( sub::collect<list<sub::Subtitle> > (sub::InteropDCPReader("test/data/test1.xml").subtitles ()), - 25, + sub::TWENTY_FIVE, sub::LANGUAGE_FRENCH, "", "", "", "", @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE (dcp_to_stl_binary_test5) boost::filesystem::path p = private_test / "065d39ff-6723-4dbf-a94f-849cde82f5e1_sub.mxf"; sub::write_stl_binary ( sub::collect<list<sub::Subtitle> > (sub::SMPTEDCPReader(p, true).subtitles ()), - 25, + sub::TWENTY_FIVE, sub::LANGUAGE_FRENCH, "", "", "", "", diff --git a/test/stl_binary_writer_test.cc b/test/stl_binary_writer_test.cc index 9bc3ec7..3596d73 100644 --- a/test/stl_binary_writer_test.cc +++ b/test/stl_binary_writer_test.cc @@ -30,8 +30,8 @@ BOOST_AUTO_TEST_CASE (stl_binary_writer_test) { sub::Subtitle s; - s.from.set_frame (sub::FrameTime (0, 0, 41, 9)); - s.to.set_frame (sub::FrameTime (0, 0, 42, 21)); + s.from = sub::Time::from_hmsf (0, 0, 41, 9, sub::TWENTY_FIVE); + s.to = sub::Time::from_hmsf (0, 0, 42, 21, sub::TWENTY_FIVE); { sub::Block b; @@ -64,8 +64,8 @@ BOOST_AUTO_TEST_CASE (stl_binary_writer_test) { sub::Subtitle s; - s.from.set_frame (sub::FrameTime (0, 1, 1, 1)); - s.to.set_frame (sub::FrameTime (0, 1, 2, 10)); + s.from = sub::Time::from_hmsf (0, 1, 1, 1, sub::TWENTY_FIVE); + s.to = sub::Time::from_hmsf (0, 1, 2, 10, sub::TWENTY_FIVE); sub::Line l; l.vertical_position.line = 0; @@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE (stl_binary_writer_test) sub::write_stl_binary ( subs, - 25, + sub::TWENTY_FIVE, sub::LANGUAGE_GERMAN, "Original programme title", "Original episode title", diff --git a/test/stl_text_reader_test.cc b/test/stl_text_reader_test.cc index c6f58b3..b99da2e 100644 --- a/test/stl_text_reader_test.cc +++ b/test/stl_text_reader_test.cc @@ -31,7 +31,7 @@ using std::vector; BOOST_AUTO_TEST_CASE (stl_text_reader_test) { ifstream file ("test/data/test_text.stl"); - sub::STLTextReader reader (file); + sub::STLTextReader reader (file, sub::TWENTY_FIVE); list<sub::Subtitle> subs = sub::collect<list<sub::Subtitle> > (reader.subtitles ()); list<sub::Subtitle>::iterator i = subs.begin (); @@ -40,8 +40,8 @@ BOOST_AUTO_TEST_CASE (stl_text_reader_test) /* First subtitle */ BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.frame().get(), sub::FrameTime (0, 0, 41, 9)); - BOOST_CHECK_EQUAL (i->to.frame().get(), sub::FrameTime (0, 0, 42, 21)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsf (0, 0, 41, 9, sub::TWENTY_FIVE)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsf (0, 0, 42, 21, sub::TWENTY_FIVE)); list<sub::Line>::iterator j = i->lines.begin (); BOOST_CHECK (j != i->lines.end ()); @@ -72,8 +72,8 @@ BOOST_AUTO_TEST_CASE (stl_text_reader_test) /* Second subtitle */ BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.frame().get(), sub::FrameTime (0, 1, 1, 1)); - BOOST_CHECK_EQUAL (i->to.frame().get(), sub::FrameTime (0, 1, 2, 10)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsf (0, 1, 1, 1, sub::TWENTY_FIVE)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsf (0, 1, 2, 10, sub::TWENTY_FIVE)); BOOST_CHECK_EQUAL (i->lines.size(), 1); sub::Line l = i->lines.front (); diff --git a/test/subrip_reader_test.cc b/test/subrip_reader_test.cc index decca01..ea629c6 100644 --- a/test/subrip_reader_test.cc +++ b/test/subrip_reader_test.cc @@ -44,8 +44,8 @@ BOOST_AUTO_TEST_CASE (subrip_reader_test) /* First subtitle */ BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.metric().get(), sub::MetricTime (0, 0, 41, 90)); - BOOST_CHECK_EQUAL (i->to.metric().get(), sub::MetricTime (0, 0, 42, 210)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 0, 41, 90)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 0, 42, 210)); list<sub::Line>::iterator j = i->lines.begin (); BOOST_CHECK (j != i->lines.end ()); @@ -78,8 +78,8 @@ BOOST_AUTO_TEST_CASE (subrip_reader_test) /* Second subtitle */ BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.metric().get(), sub::MetricTime (0, 1, 1, 10)); - BOOST_CHECK_EQUAL (i->to.metric().get(), sub::MetricTime (0, 1, 2, 100)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 1, 10)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 2, 100)); BOOST_CHECK_EQUAL (i->lines.size(), 1); sub::Line l = i->lines.front (); @@ -166,46 +166,46 @@ BOOST_AUTO_TEST_CASE (subrip_reader_test2) list<sub::Subtitle>::const_iterator i = subs.begin(); BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.metric().get(), sub::MetricTime (0, 1, 49, 200)); - BOOST_CHECK_EQUAL (i->to.metric().get(), sub::MetricTime (0, 1, 52, 351)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 49, 200)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 52, 351)); BOOST_CHECK_EQUAL (i->lines.size(), 2); BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "This is a subtitle, and it goes "); BOOST_CHECK_EQUAL (i->lines.back().blocks.front().text, "over two lines."); ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.metric().get(), sub::MetricTime (0, 1, 52, 440)); - BOOST_CHECK_EQUAL (i->to.metric().get(), sub::MetricTime (0, 1, 54, 351)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 52, 440)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 54, 351)); BOOST_CHECK_EQUAL (i->lines.size(), 1); BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "We have emboldened this"); BOOST_CHECK_EQUAL (i->lines.front().blocks.front().bold, true); ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.metric().get(), sub::MetricTime (0, 1, 54, 440)); - BOOST_CHECK_EQUAL (i->to.metric().get(), sub::MetricTime (0, 1, 56, 590)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 54, 440)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 56, 590)); BOOST_CHECK_EQUAL (i->lines.size(), 1); BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "And italicised this."); BOOST_CHECK_EQUAL (i->lines.front().blocks.front().italic, true); ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.metric().get(), sub::MetricTime (0, 1, 56, 680)); - BOOST_CHECK_EQUAL (i->to.metric().get(), sub::MetricTime (0, 1, 58, 955)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 1, 56, 680)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 1, 58, 955)); BOOST_CHECK_EQUAL (i->lines.size(), 1); BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Shall I compare thee to a summers' day?"); ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.metric().get(), sub::MetricTime (0, 2, 0, 840)); - BOOST_CHECK_EQUAL (i->to.metric().get(), sub::MetricTime (0, 2, 3, 400)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 2, 0, 840)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 2, 3, 400)); BOOST_CHECK_EQUAL (i->lines.size(), 1); BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Is this a dagger I see before me?"); ++i; BOOST_CHECK (i != subs.end ()); - BOOST_CHECK_EQUAL (i->from.metric().get(), sub::MetricTime (0, 3, 54, 560)); - BOOST_CHECK_EQUAL (i->to.metric().get(), sub::MetricTime (0, 3, 56, 471)); + BOOST_CHECK_EQUAL (i->from, sub::Time::from_hmsm (0, 3, 54, 560)); + BOOST_CHECK_EQUAL (i->to, sub::Time::from_hmsm (0, 3, 56, 471)); BOOST_CHECK_EQUAL (i->lines.size(), 1); BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Hello world."); @@ -218,48 +218,48 @@ BOOST_AUTO_TEST_CASE (subrip_reader_convert_line_test) { sub::SubripReader r; - r.convert_line ("Hello world", 0, sub::TimePair (), sub::TimePair ()); + r.convert_line ("Hello world", 0, sub::Time (), sub::Time ()); BOOST_CHECK_EQUAL (r._subs.size(), 1); BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world"); r._subs.clear (); - r.convert_line ("<b>Hello world</b>", 0, sub::TimePair (), sub::TimePair ()); + r.convert_line ("<b>Hello world</b>", 0, sub::Time (), sub::Time ()); BOOST_CHECK_EQUAL (r._subs.size(), 1); BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world"); BOOST_CHECK_EQUAL (r._subs.front().bold, true); r._subs.clear (); - r.convert_line ("<i>Hello world</i>", 0, sub::TimePair (), sub::TimePair ()); + r.convert_line ("<i>Hello world</i>", 0, sub::Time (), sub::Time ()); BOOST_CHECK_EQUAL (r._subs.size(), 1); BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world"); BOOST_CHECK_EQUAL (r._subs.front().italic, true); r._subs.clear (); - r.convert_line ("<u>Hello world</u>", 0, sub::TimePair (), sub::TimePair ()); + r.convert_line ("<u>Hello world</u>", 0, sub::Time (), sub::Time ()); BOOST_CHECK_EQUAL (r._subs.size(), 1); BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world"); BOOST_CHECK_EQUAL (r._subs.front().underline, true); r._subs.clear (); - r.convert_line ("{b}Hello world{/b}", 0, sub::TimePair (), sub::TimePair ()); + r.convert_line ("{b}Hello world{/b}", 0, sub::Time (), sub::Time ()); BOOST_CHECK_EQUAL (r._subs.size(), 1); BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world"); BOOST_CHECK_EQUAL (r._subs.front().bold, true); r._subs.clear (); - r.convert_line ("{i}Hello world{/i}", 0, sub::TimePair (), sub::TimePair ()); + r.convert_line ("{i}Hello world{/i}", 0, sub::Time (), sub::Time ()); BOOST_CHECK_EQUAL (r._subs.size(), 1); BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world"); BOOST_CHECK_EQUAL (r._subs.front().italic, true); r._subs.clear (); - r.convert_line ("{u}Hello world{/u}", 0, sub::TimePair (), sub::TimePair ()); + r.convert_line ("{u}Hello world{/u}", 0, sub::Time (), sub::Time ()); BOOST_CHECK_EQUAL (r._subs.size(), 1); BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world"); BOOST_CHECK_EQUAL (r._subs.front().underline, true); r._subs.clear (); - r.convert_line ("<b>This is <i>nesting</i> of subtitles</b>", 0, sub::TimePair (), sub::TimePair ()); + r.convert_line ("<b>This is <i>nesting</i> of subtitles</b>", 0, sub::Time (), sub::Time ()); BOOST_CHECK_EQUAL (r._subs.size(), 3); list<sub::RawSubtitle>::iterator i = r._subs.begin (); BOOST_CHECK_EQUAL (i->text, "This is "); @@ -281,8 +281,8 @@ BOOST_AUTO_TEST_CASE (subrip_reader_convert_line_test) /** Test SubripReader::convert_time */ BOOST_AUTO_TEST_CASE (subrip_reader_convert_time_test) { - BOOST_CHECK_EQUAL (sub::SubripReader::convert_time ("00:03:10,500"), sub::TimePair (sub::MetricTime (0, 3, 10, 500))); - BOOST_CHECK_EQUAL (sub::SubripReader::convert_time ("04:19:51,782"), sub::TimePair (sub::MetricTime (4, 19, 51, 782))); + BOOST_CHECK_EQUAL (sub::SubripReader::convert_time ("00:03:10,500"), sub::Time::from_hmsm (0, 3, 10, 500)); + BOOST_CHECK_EQUAL (sub::SubripReader::convert_time ("04:19:51,782"), sub::Time::from_hmsm (4, 19, 51, 782)); } diff --git a/test/time_test.cc b/test/time_test.cc index d6ca14a..2179815 100644 --- a/test/time_test.cc +++ b/test/time_test.cc @@ -18,70 +18,40 @@ */ #include <boost/test/unit_test.hpp> -#include "metric_time.h" -#include "frame_time.h" -#include "time_pair.h" +#include "sub_time.h" /* Check time construction */ BOOST_AUTO_TEST_CASE (time_construction_test) { { - sub::MetricTime t (3, 5, 7, 40); - BOOST_CHECK_EQUAL (t.hours(), 3); - BOOST_CHECK_EQUAL (t.minutes(), 5); - BOOST_CHECK_EQUAL (t.seconds(), 7); - BOOST_CHECK_EQUAL (t.milliseconds(), 40); + sub::Time t = sub::Time::from_hmsm (3, 5, 7, 40); + BOOST_CHECK_EQUAL (t.hours, 3); + BOOST_CHECK_EQUAL (t.minutes, 5); + BOOST_CHECK_EQUAL (t.seconds, 7); + BOOST_CHECK_EQUAL (t._milliseconds.get(), 40); } { - sub::MetricTime t (591353, 1, 2, 3); - BOOST_CHECK_EQUAL (t.hours(), 591353); - BOOST_CHECK_EQUAL (t.minutes(), 1); - BOOST_CHECK_EQUAL (t.seconds(), 2); - BOOST_CHECK_EQUAL (t.milliseconds(), 3); - } - - { - sub::FrameTime t (3 * 60 * 60 * 24 + 31 * 60 * 24 + 4 * 24 + 11, 24); - BOOST_CHECK_EQUAL (t.hours(), 3); - BOOST_CHECK_EQUAL (t.minutes(), 31); - BOOST_CHECK_EQUAL (t.seconds(), 4); - BOOST_CHECK_EQUAL (t.frames(), 11); + sub::Time t = sub::Time::from_hmsm (591353, 1, 2, 3); + BOOST_CHECK_EQUAL (t.hours, 591353); + BOOST_CHECK_EQUAL (t.minutes, 1); + BOOST_CHECK_EQUAL (t.seconds, 2); + BOOST_CHECK_EQUAL (t._milliseconds.get(), 3); } } /* Check time conversions */ BOOST_AUTO_TEST_CASE (time_conversion_test) { - sub::TimePair p; - /* 40ms = 1 frame at 25fps */ - p.set_metric (sub::MetricTime (3, 5, 7, 40)); - BOOST_CHECK_EQUAL (p.frame (25), sub::FrameTime (3, 5, 7, 1)); - p.set_frame (sub::FrameTime (3, 5, 7, 1)); - BOOST_CHECK_EQUAL (p.metric (25), sub::MetricTime (3, 5, 7, 40)); + sub::Time p = sub::Time::from_hmsm (3, 5, 7, 40); + BOOST_CHECK_EQUAL (p.frames (sub::TWENTY_FIVE), 1); + p = sub::Time::from_hmsf (3, 5, 7, 1, sub::TWENTY_FIVE); + BOOST_CHECK_EQUAL (p.as_milliseconds(), sub::Time::from_hmsm (3, 5, 7, 40).as_milliseconds ()); /* 120ms = 3 frames at 25fps */ - p.set_metric (sub::MetricTime (3, 5, 7, 120)); - BOOST_CHECK_EQUAL (p.frame (25), sub::FrameTime (3, 5, 7, 3)); - p.set_frame (sub::FrameTime (3, 5, 7, 3)); - BOOST_CHECK_EQUAL (p.metric (25), sub::MetricTime (3, 5, 7, 120)); -} - -/* Check time maths */ -BOOST_AUTO_TEST_CASE (time_maths_test) -{ - { - sub::FrameTime a (1, 59, 59, 23); - sub::FrameTime b (2, 31, 19, 2); - a.add (b, 24); - BOOST_CHECK_EQUAL (a, sub::FrameTime (4, 31, 19, 1)); - } - - { - sub::MetricTime a (1, 59, 59, 999); - sub::MetricTime b (2, 31, 19, 2); - a.add (b); - BOOST_CHECK_EQUAL (a, sub::MetricTime (4, 31, 19, 1)); - } + p = sub::Time::from_hmsm (3, 5, 7, 120); + BOOST_CHECK_EQUAL (p.frames (sub::TWENTY_FIVE), 3); + p = sub::Time::from_hmsf (3, 5, 7, 3, sub::TWENTY_FIVE); + BOOST_CHECK_EQUAL (p.as_milliseconds (), sub::Time::from_hmsm (3, 5, 7, 120).as_milliseconds ()); } diff --git a/tools/dumpsubs.cc b/tools/dumpsubs.cc index fef3885..fe7350d 100644 --- a/tools/dumpsubs.cc +++ b/tools/dumpsubs.cc @@ -71,7 +71,7 @@ main (int argc, char* argv[]) exit (EXIT_FAILURE); } - shared_ptr<Reader> reader = reader_factory (argv[optind]); + shared_ptr<Reader> reader = reader_factory (argv[optind], sub::TWENTY_FIVE); if (!reader) { cerr << argv[0] << ": could not read subtitle file " << argv[optind] << "\n"; exit (EXIT_FAILURE); |
