Allow SMPTE timecodes with 3 digits in the editable units field.
authorCarl Hetherington <cth@carlh.net>
Sat, 16 Mar 2024 17:02:35 +0000 (18:02 +0100)
committerCarl Hetherington <cth@carlh.net>
Sat, 16 Mar 2024 17:02:40 +0000 (18:02 +0100)
It seems that these should only be present if the timecode rate is 101
or above, and in that case all timecodes should have 3 editable rate digits,
but someone sent a DCP from what seems to be EasyDCP Creator and it has
one timecode of 00:05:01:000.

src/dcp_time.cc
test/dcp_time_test.cc

index e21eaf2794aa8d37ef25c0705f2f547d8ceb5018..f08f2b1c4a7c9157e69dac6e68745e2cd1c7fe1a 100644 (file)
@@ -147,7 +147,8 @@ Time::Time (string time, optional<int> tcr_)
                }
 
        } else {
-               /* SMPTE: HH:MM:SS:EE */
+               /* SMPTE: HH:MM:SS:EE[E].
+                * It seems like there can be any number of E digits but let's just allow 2 or 3 */
                split (b, time, is_any_of (":"));
                if (b.size() != 4) {
                        boost::throw_exception (ReadError (String::compose ("unrecognised time specification %1; does not have 4 parts", time)));
@@ -159,7 +160,7 @@ Time::Time (string time, optional<int> tcr_)
                        boost::throw_exception (ReadError (String::compose ("unrecognised time specification %1; %2 has bad length", time, b[2])));
                }
                s = raw_convert<int> (b[2]);
-               if (b[3].empty() || b[3].length() > 2) {
+               if (b[3].empty() || b[3].length() > 3) {
                        boost::throw_exception (ReadError (String::compose ("unrecognised time specification %1; %2 has bad length", time, b[3])));
                }
                e = raw_convert<int> (b[3]);
index 4b529be68d44eed0d81a954f56893d3639d6b841..3e0050b4c5682160b078978c9fad0d9ed25ca40e 100644 (file)
@@ -131,6 +131,11 @@ BOOST_AUTO_TEST_CASE (dcp_time)
        /* SMPTE */
        a = dcp::Time ("01:23:45:12", 250);
        BOOST_CHECK_EQUAL (a, dcp::Time (1, 23, 45, 12, 250));
+       /* The editable units field can be any length (depending on the timecode rate)
+        * but in practice I think 3 is enough.
+        */
+       a = dcp::Time("00:05:01:519", 250);
+       BOOST_CHECK_EQUAL(a, dcp::Time(0, 5, 1, 519, 250));
 
        /* Check some disallowed constructions from string */
        BOOST_CHECK_THROW (dcp::Time ("01:23:45:1234", optional<int>()), dcp::ReadError);
@@ -145,7 +150,6 @@ BOOST_AUTO_TEST_CASE (dcp_time)
        BOOST_CHECK_THROW (dcp::Time ("01:23:.123", optional<int>()), dcp::ReadError);
        BOOST_CHECK_THROW (dcp::Time ("01::45.123", optional<int>()), dcp::ReadError);
        BOOST_CHECK_THROW (dcp::Time (":23:45.123", optional<int>()), dcp::ReadError);
-       BOOST_CHECK_THROW (dcp::Time ("01:23:45:123", 250), dcp::ReadError);
        BOOST_CHECK_THROW (dcp::Time ("01:23:45:123:66", 250), dcp::ReadError);
        BOOST_CHECK_THROW (dcp::Time ("01:23:45:", 250), dcp::ReadError);
        BOOST_CHECK_THROW (dcp::Time ("01:23::123", 250), dcp::ReadError);