Fix case where -ve duration subtitles could be created at reel boundaries (#3012)
authorCarl Hetherington <cth@carlh.net>
Sat, 12 Apr 2025 20:25:04 +0000 (22:25 +0200)
committerCarl Hetherington <cth@carlh.net>
Sat, 12 Apr 2025 20:25:04 +0000 (22:25 +0200)
src/lib/writer.cc
test/subtitle_reel_test.cc

index 9f64a16865dad3a72c65bca6c824453951f1c185..ce5d40c7581d75ebbae311b27a4818847e58e7bc 100644 (file)
@@ -846,7 +846,11 @@ Writer::write (PlayerText text, TextType type, optional<DCPTextTrack> track, DCP
        }
 
        auto back_off = [this](DCPTimePeriod period) {
-               period.to -= DCPTime::from_frames(2, film()->video_frame_rate());
+               auto const vfr = film()->video_frame_rate();
+               period.to -= DCPTime::from_frames(2, vfr);
+               if (period.duration().frames_floor(vfr) <= 0) {
+                       period.to = period.from + DCPTime::from_frames(1, vfr);
+               }
                return period;
        };
 
@@ -860,7 +864,7 @@ Writer::write (PlayerText text, TextType type, optional<DCPTextTrack> track, DCP
                                _hanging_texts.push_back (HangingText{text, type, track, back_off(*overlap)});
                        }
                }
-               /* Back off from the reel boundary by a couple of frames to avoid tripping checks
+               /* Try to back off from the reel boundary by a couple of frames to avoid tripping checks
                 * for subtitles being too close together.
                 */
                period.to = (*reel)->period().to;
index 877709f730e167546e4dfd26b69748c9db073907..d72a543fd0c2980fd8250a71fed73f964c8c1396 100644 (file)
@@ -234,3 +234,28 @@ BOOST_AUTO_TEST_CASE (subtitles_split_at_reel_boundaries)
        }
 }
 
+
+BOOST_AUTO_TEST_CASE(bad_subtitle_not_created_at_reel_boundaries)
+{
+       boost::filesystem::path const srt = "build/test/bad_subtitle_not_created_at_reel_boundaries.srt";
+       dcp::write_string_to_file("1\n00:00:10,000 -> 00:00:20,000\nHello world", srt);
+       auto content = content_factory(srt)[0];
+
+       auto film = new_test_film("bad_subtitle_not_created_at_reel_boundaries", { content });
+       film->set_reel_type(ReelType::CUSTOM);
+       content->text[0]->set_language(dcp::LanguageTag("de-DE"));
+       /* This is 1 frame after the start of the subtitle */
+       film->set_custom_reel_boundaries({dcpomatic::DCPTime::from_frames(241, 24)});
+
+       /* This is a tricky situation and the way DoM deals with it gives two Bv2.1
+        * warnings, but these are "should" not "shall" so I think it's OK.
+        */
+       make_and_verify_dcp(
+               film,
+               {
+                       dcp::VerificationNote::Code::MISSING_CPL_METADATA,
+                       dcp::VerificationNote::Code::INVALID_SUBTITLE_DURATION,
+                       dcp::VerificationNote::Code::INVALID_SUBTITLE_SPACING,
+               });
+}
+