Check that Interop subtitle files have at least one subtitle.
authorCarl Hetherington <cth@carlh.net>
Sun, 15 Jan 2023 22:13:49 +0000 (23:13 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 15 Jan 2023 22:14:00 +0000 (23:14 +0100)
It was reported on the forum that files without any <Font> or
<Subtitle> tags fail validation on EasyDCP 3.0.1 and crash
Qubemaster Pro 3.0.15.

src/verify.cc
src/verify.h
test/data/subs4.xml [new file with mode: 0644]
test/verify_test.cc

index bfa697dae21bf6aa1ae40243c182bd86a6f8e8fa..8ea9ae9759e35c343e732d5be4026593a768165c 100644 (file)
@@ -687,6 +687,16 @@ verify_smpte_timed_text_asset (
 }
 
 
+/** Verify Interop subtitle-only stuff */
+void
+verify_interop_subtitle_asset(shared_ptr<const InteropSubtitleAsset> asset, vector<VerificationNote>& notes)
+{
+       if (asset->subtitles().empty()) {
+               notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_SUBTITLE, asset->id(), asset->file().get() });
+       }
+}
+
+
 /** Verify SMPTE subtitle-only stuff */
 void
 verify_smpte_subtitle_asset (
@@ -740,6 +750,11 @@ verify_subtitle_asset (
                notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
        }
 
+       auto interop = dynamic_pointer_cast<const InteropSubtitleAsset>(asset);
+       if (interop) {
+               verify_interop_subtitle_asset(interop, notes);
+       }
+
        auto smpte = dynamic_pointer_cast<const SMPTESubtitleAsset>(asset);
        if (smpte) {
                verify_smpte_timed_text_asset (smpte, reel_asset_duration, notes);
@@ -1938,6 +1953,8 @@ dcp::note_to_string (VerificationNote note)
                return String::compose("The PKL %1 has more than one asset with the same ID", note.note().get());
        case VerificationNote::Code::DUPLICATE_ASSET_ID_IN_ASSETMAP:
                return String::compose("The ASSETMAP %1 has more than one asset with the same ID", note.note().get());
+       case VerificationNote::Code::MISSING_SUBTITLE:
+               return String::compose("The subtitle asset %1 has no subtitles", note.note().get());
        }
 
        return "";
index e9b5c9d01d82cc89260adbd16d7d566404dbe594..2e20bc3199b05ee9265fafcb51815576bf944bd1 100644 (file)
@@ -410,7 +410,12 @@ public:
                 *  note contains the ASSETMAP ID
                 *  file contains the ASSETMAP filename
                 */
-               DUPLICATE_ASSET_ID_IN_ASSETMAP
+               DUPLICATE_ASSET_ID_IN_ASSETMAP,
+               /** An Interop subtitle asset has no subtitles.
+                *  note contains the asset ID
+                *  file contains the asset filename
+                */
+               MISSING_SUBTITLE
        };
 
        VerificationNote (Type type, Code code)
diff --git a/test/data/subs4.xml b/test/data/subs4.xml
new file mode 100644 (file)
index 0000000..5aea4c1
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DCSubtitle Version="1.0">
+  <SubtitleID>cab5c268-222b-41d2-88ae-6d6999441b17</SubtitleID>
+  <MovieTitle>Movie Title</MovieTitle>
+  <ReelNumber>1</ReelNumber>
+  <Language>French</Language>
+  <LoadFont Id="theFontId" URI="arial.ttf"/>
+</DCSubtitle>
index 652bf12da894220e1337b8182e2ab6a5fad8729b..34dc79bc08c1738b9d383802d0a9b52eb497e8bb 100644 (file)
@@ -806,6 +806,25 @@ BOOST_AUTO_TEST_CASE (verify_invalid_interop_subtitles)
 }
 
 
+BOOST_AUTO_TEST_CASE(verify_interop_subtitle_asset_with_no_subtitles)
+{
+       path const dir("build/test/verify_interop_subtitle_asset_with_no_subtitles");
+       prepare_directory(dir);
+       copy_file("test/data/subs4.xml", dir / "subs.xml");
+       auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "subs.xml");
+       auto reel_asset = make_shared<dcp::ReelInteropSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
+       write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
+
+       check_verify_result (
+               { dir },
+               {
+                       { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
+                       { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE, asset->id(), boost::filesystem::canonical(asset->file().get()) },
+               });
+
+}
+
+
 BOOST_AUTO_TEST_CASE (verify_valid_smpte_subtitles)
 {
        path const dir("build/test/verify_valid_smpte_subtitles");