Handle fonts for ccaps coming from DCP content (#2525).
authorCarl Hetherington <cth@carlh.net>
Thu, 11 May 2023 11:50:57 +0000 (13:50 +0200)
committerCarl Hetherington <cth@carlh.net>
Fri, 12 May 2023 20:11:06 +0000 (22:11 +0200)
Not dealing with them calls all sort of chaos as described in the
bug report.

cscript
src/lib/dcp_content.cc
src/lib/dcp_examiner.cc
src/lib/reel_writer.cc
src/wx/verify_dcp_dialog.cc
test/torture_test.cc
wscript

diff --git a/cscript b/cscript
index c3bfeda0472207842e08f0824a4f7e0bad11357d..a85cc736914a303e57d3b30663eb242c1aa9f056 100644 (file)
--- a/cscript
+++ b/cscript
@@ -479,7 +479,7 @@ def dependencies(target, options):
         # Use distro-provided FFmpeg on Arch
         deps = []
 
-    deps.append(('libdcp', 'v1.8.67'))
+    deps.append(('libdcp', 'v1.8.68'))
     deps.append(('libsub', 'v1.6.44'))
     deps.append(('leqm-nrt', '4560105773c66ac9216b62313a24093bb0a027ae'))
     deps.append(('rtaudio', 'f619b76'))
index 7d835e618f1ecdfe2185f57863fea40093d7144d..e7bef573b172dcbf7e9e6278541bd9457b8ba46e 100644 (file)
@@ -276,6 +276,7 @@ DCPContent::examine (shared_ptr<const Film> film, shared_ptr<Job> job)
        for (int i = 0; i < examiner->text_count(TextType::CLOSED_CAPTION); ++i) {
                auto c = make_shared<TextContent>(this, TextType::CLOSED_CAPTION, TextType::CLOSED_CAPTION);
                c->set_dcp_track (examiner->dcp_text_track(i));
+               add_fonts_from_examiner(c, examiner->fonts());
                new_text.push_back (c);
        }
 
index 6586e6e81f86e0adabcd61f18c6b4b2f85187720..9c4f899c6d0fd6697e70e0cc1238856bbc3116d8 100644 (file)
@@ -230,6 +230,9 @@ DCPExaminer::DCPExaminer (shared_ptr<const DCPContent> content, bool tolerant)
 
                        LOG_GENERAL("Closed caption %1 of reel %2 found", ccap->id(), reel->id());
 
+                       for (auto const& font: ccap->asset()->font_data()) {
+                               reel_fonts.push_back(make_shared<dcpomatic::Font>(font.first, font.second));
+                       }
                }
 
                if (reel->main_markers ()) {
index 5d9f4dae0d9a19e1af95c1dd19b08ffc10ad4fe0..139c5aed431ce51a8ecf51aee988958f083815da 100644 (file)
@@ -491,18 +491,17 @@ maybe_add_text (
        shared_ptr<Result> reel_asset;
 
        if (asset) {
-               if (!std::is_same<Result, dcp::ReelClosedCaptionAsset>::value) {
-                       if (film->interop()) {
-                               if (chosen_interop_font) {
-                                       /* We only add one font, as Interop will ignore subsequent ones (and some validators will
-                                        * complain if they are even present)
-                                        */
-                                       asset->add_font(fonts.get(chosen_interop_font), chosen_interop_font->data().get_value_or(default_font));
-                               }
+               if (film->interop()) {
+                       if (chosen_interop_font) {
+                               /* We only add one font, as Interop will ignore subsequent ones (and some validators will
+                                * complain if they are even present)
+                                */
+                               asset->add_font(fonts.get(chosen_interop_font), chosen_interop_font->data().get_value_or(default_font));
                        } else {
-                               for (auto const& font: fonts.map()) {
-                                       asset->add_font(font.second, font.first->data().get_value_or(default_font));
-                               }
+                       }
+               } else {
+                       for (auto const& font: fonts.map()) {
+                               asset->add_font(font.second, font.first->data().get_value_or(default_font));
                        }
                }
 
@@ -979,9 +978,7 @@ ReelWriter::write (PlayerText subs, TextType type, optional<DCPTextTrack> track,
                i.set_out (dcp::Time(period.to.seconds() - _period.from.seconds(), tcr));
                i.set_v_position(convert_vertical_position(i, film()->interop() ? dcp::SubtitleStandard::INTEROP : dcp::SubtitleStandard::SMPTE_2014));
                auto sub = make_shared<dcp::SubtitleString>(i);
-               if (type == TextType::OPEN_SUBTITLE) {
-                       sub->set_font(fonts.get(i.font));
-               }
+               sub->set_font(fonts.get(i.font));
                asset->add(sub);
        }
 
index 07e3589e52bc4f0dfa2577b502ea3f8e831a0009..b3e229087155fdb045d7c2d91f6b991e99517e75 100644 (file)
@@ -106,6 +106,9 @@ VerifyDCPDialog::VerifyDCPDialog (wxWindow* parent, shared_ptr<VerifyDCPJob> job
                if (note.size()) {
                        message.Replace("%size", std_to_wx(dcp::raw_convert<string>(note.size().get())));
                }
+               if (note.id()) {
+                       message.Replace("%id", std_to_wx(note.id().get()));
+               }
                add_bullet (note.type(), message);
                counts[note.type()]++;
        };
@@ -419,6 +422,9 @@ VerifyDCPDialog::VerifyDCPDialog (wxWindow* parent, shared_ptr<VerifyDCPJob> job
                case dcp::VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT:
                        add(i, _("The XML in the subtitle asset %n has more than one namespace declaration."));
                        break;
+               case dcp::VerificationNote::Code::MISSING_LOAD_FONT:
+                       add(i, _("A subtitle or closed caption refers to a font with ID %id that does not have a corresponding <LoadFont> node."));
+                       break;
                }
        }
 
index bc03c93d89cea980bbd4f3a8cf07163989720880..0c781fdb1218faa4e6c5d0d0f72747a6a59cb94d 100644 (file)
@@ -299,3 +299,29 @@ BOOST_AUTO_TEST_CASE (torture_test1)
        }
 
 }
+
+
+BOOST_AUTO_TEST_CASE(multi_reel_interop_ccap_test)
+{
+       auto pic1 = content_factory("test/data/flat_red.png").front();
+       auto ccap1 = content_factory("test/data/15s.srt").front();
+       auto pic2 = content_factory("test/data/flat_red.png").front();
+       auto ccap2 = content_factory("test/data/15s.srt").front();
+       auto film1 = new_test_film2("multi_reel_interop_ccap_test1", { pic1, ccap1, pic2, ccap2 });
+       film1->set_interop(true);
+       film1->set_reel_type(ReelType::BY_VIDEO_CONTENT);
+       ccap1->text[0]->set_type(TextType::CLOSED_CAPTION);
+       pic1->video->set_length(15 * 24);
+       ccap2->text[0]->set_type(TextType::CLOSED_CAPTION);
+       pic2->video->set_length(15 * 24);
+       make_and_verify_dcp(film1, { dcp::VerificationNote::Code::INVALID_STANDARD, dcp::VerificationNote::Code::INVALID_SUBTITLE_SPACING });
+
+       auto reload = make_shared<DCPContent>(film1->dir(film1->dcp_name()));
+       auto film2 = new_test_film2("multi_reel_interop_ccap_test2", { reload });
+       for (auto i: reload->text) {
+               i->set_use(true);
+       }
+       film2->set_interop(true);
+       make_and_verify_dcp(film2, { dcp::VerificationNote::Code::INVALID_STANDARD, dcp::VerificationNote::Code::INVALID_SUBTITLE_SPACING });
+}
+
diff --git a/wscript b/wscript
index 9662359a1b168b87669ea715972f7acab65a8e01..94ab1fd7047b5ac790588408171d16cd0fd31d34 100644 (file)
--- a/wscript
+++ b/wscript
@@ -35,7 +35,7 @@ except ImportError:
 from waflib import Logs, Context
 
 APPNAME = 'dcpomatic'
-libdcp_version = '1.8.67'
+libdcp_version = '1.8.68'
 libsub_version = '1.6.42'
 
 this_version = subprocess.Popen(shlex.split('git tag -l --points-at HEAD'), stdout=subprocess.PIPE).communicate()[0]