Bv2.1 6.2.1: Check that subtitle reel <Language> conforms to RFC 5646.
authorCarl Hetherington <cth@carlh.net>
Wed, 9 Dec 2020 00:08:14 +0000 (01:08 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 17 Jan 2021 19:13:22 +0000 (20:13 +0100)
BRANCH
src/reel_subtitle_asset.h
src/verify.cc
src/verify.h
test/verify_test.cc

diff --git a/BRANCH b/BRANCH
index daf59830a40925d6f3e83c29dab05eca0f3fba7c..43445112ba8a410e2a81d40f0e2c2918d240debe 100644 (file)
--- a/BRANCH
+++ b/BRANCH
@@ -8,7 +8,7 @@ Mark things with [Bv2.1_paragraph]
 6.1 must be smpte [/]
     immersive audio DCPs must comply with 429-18, 429-19 [*] don't have these standards
 6.2 Language and Territory must comply with RFC 5646
-    - subtitle reel <Language>
+    - subtitle reel <Language> /
     - subtitle XML <Language>
     - sound reel <Language>
     - ccap reel <Language>
index 13e72133faffaad02cf5ece856d9479fdd24a29f..8c3b7d185cad946a7a91f05cc7f091d3c741ae74 100644 (file)
@@ -43,6 +43,8 @@
 #include "reel_mxf.h"
 #include "subtitle_asset.h"
 
+struct verify_test26;
+
 namespace dcp {
 
 class SubtitleAsset;
@@ -70,6 +72,8 @@ public:
        }
 
 private:
+       friend struct ::verify_test26;
+
        std::string key_type () const;
        std::string cpl_node_name (Standard standard) const;
 
index f3ecb1f4d09a2413050a31516a4ff52a9ba88bd8..b440894622e94d324cd1bde201138c77cc5bde91 100644 (file)
@@ -394,6 +394,17 @@ verify_asset (shared_ptr<const DCP> dcp, shared_ptr<const ReelMXF> reel_mxf, fun
 }
 
 
+void
+verify_language_tag (string tag, list<VerificationNote>& notes)
+{
+       try {
+               dcp::LanguageTag test (tag);
+       } catch (dcp::LanguageTagError &) {
+               notes.push_back (VerificationNote(VerificationNote::VERIFY_BV21_ERROR, VerificationNote::BAD_LANGUAGE, tag));
+       }
+}
+
+
 enum VerifyPictureAssetResult
 {
        VERIFY_PICTURE_ASSET_RESULT_GOOD,
@@ -543,6 +554,16 @@ verify_main_sound_asset (
 }
 
 
+static void
+verify_main_subtitle_reel (shared_ptr<const ReelSubtitleAsset> reel_asset, list<VerificationNote>& notes)
+{
+       /* XXX: is Language compulsory? */
+       if (reel_asset->language()) {
+               verify_language_tag (*reel_asset->language(), notes);
+       }
+}
+
+
 static void
 verify_main_subtitle_asset (
        shared_ptr<const Reel> reel,
@@ -642,8 +663,11 @@ dcp::verify (
                                        verify_main_sound_asset (dcp, reel, stage, progress, notes);
                                }
 
-                               if (reel->main_subtitle() && reel->main_subtitle()->asset_ref().resolved()) {
-                                       verify_main_subtitle_asset (reel, stage, xsd_dtd_directory, notes);
+                               if (reel->main_subtitle()) {
+                                       verify_main_subtitle_reel (reel->main_subtitle(), notes);
+                                       if (reel->main_subtitle()->asset_ref().resolved()) {
+                                               verify_main_subtitle_asset (reel, stage, xsd_dtd_directory, notes);
+                                       }
                                }
                        }
                }
@@ -704,6 +728,8 @@ dcp::note_to_string (dcp::VerificationNote note)
                return String::compose("An asset that this DCP refers to is not included in the DCP.  It may be a VF.  Missing asset is %1.", note.note().get());
        case dcp::VerificationNote::NOT_SMPTE:
                return "This DCP does not use the SMPTE standard, which is required for Bv2.1 compliance.";
+       case dcp::VerificationNote::BAD_LANGUAGE:
+               return String::compose("The DCP specifies a language '%1' which does not conform to the RFC 5646 standard.", note.note().get());
        }
 
        return "";
index 0140066e7edd72a76dfd008a2a6bcda82cc9baa6..8eb5aa12db88fb7b6cef3f3f7620c9495f3c13a0 100644 (file)
@@ -92,6 +92,8 @@ public:
                EXTERNAL_ASSET,
                /** DCP is Interop, not SMPTE [Bv2.1_6.1] */
                NOT_SMPTE,
+               /** A language or territory does not conform to RFC 5646 [Bv2.1_6.2.1] */
+               BAD_LANGUAGE,
        };
 
        VerificationNote (Type type, Code code)
index 5a05bcd36ab35c5947ffd3c5d456bfe5440bda52..d3c17b7797c48cd923d08311ee1d9b6bb38fa607 100644 (file)
@@ -874,3 +874,31 @@ BOOST_AUTO_TEST_CASE (verify_test25)
        list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
 }
 
+
+/* SMPTE DCP with invalid <Language> in the MainSubtitle */
+BOOST_AUTO_TEST_CASE (verify_test26)
+{
+       boost::filesystem::path const dir("build/test/verify_test26");
+       boost::filesystem::remove_all (dir);
+       boost::filesystem::create_directories (dir);
+       boost::filesystem::copy_file ("test/data/subs.mxf", dir / "subs.mxf");
+       shared_ptr<dcp::SMPTESubtitleAsset> asset(new dcp::SMPTESubtitleAsset(dir / "subs.mxf"));
+       shared_ptr<dcp::ReelSubtitleAsset> reel_asset(new dcp::ReelSubtitleAsset(asset, dcp::Fraction(24, 1), 16 * 24, 0));
+       reel_asset->_language = "badlang";
+       shared_ptr<dcp::Reel> reel(new dcp::Reel());
+       reel->add (reel_asset);
+       shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+       cpl->add (reel);
+       shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+       dcp->add (cpl);
+       dcp->write_xml (dcp::SMPTE);
+
+       vector<boost::filesystem::path> dirs;
+       dirs.push_back (dir);
+       list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
+       BOOST_REQUIRE_EQUAL (notes.size(), 1U);
+       list<dcp::VerificationNote>::const_iterator i = notes.begin ();
+       BOOST_CHECK_EQUAL (i->code(), dcp::VerificationNote::BAD_LANGUAGE);
+
+}
+