Bv2.1 8.5: Features must have FFEC/FFMC markers.
authorCarl Hetherington <cth@carlh.net>
Sun, 17 Jan 2021 21:25:59 +0000 (22:25 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 17 Jan 2021 21:26:33 +0000 (22:26 +0100)
src/verify.cc
src/verify.h
test/verify_test.cc

index e02c573b5ace043c62afaf1b30f937fb694c76a1..aa296fec57e7078610081d28622b8d976ca31c52 100644 (file)
@@ -47,6 +47,7 @@
 #include "exceptions.h"
 #include "compose.hpp"
 #include "raw_convert.h"
+#include "reel_markers_asset.h"
 #include "smpte_subtitle_asset.h"
 #include <xercesc/util/PlatformUtils.hpp>
 #include <xercesc/parsers/XercesDOMParser.hpp>
@@ -1046,7 +1047,17 @@ dcp::verify (
                        }
 
                        if (cpl->release_territory()) {
-                               verify_language_tag (cpl->release_territory().get(), notes);
+                               if (!cpl->release_territory_scope() || cpl->release_territory_scope().get() != "http://www.smpte-ra.org/schemas/429-16/2014/CPL-Metadata#scope/release-territory/UNM49") {
+                                       auto terr = cpl->release_territory().get();
+                                       /* Must be a valid region tag, or "001" */
+                                       try {
+                                               LanguageTag::RegionSubtag test (terr);
+                                       } catch (...) {
+                                               if (terr != "001") {
+                                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::BAD_LANGUAGE, terr});
+                                               }
+                                       }
+                               }
                        }
 
                        if (dcp->standard() == dcp::SMPTE) {
@@ -1073,6 +1084,10 @@ dcp::verify (
                        size_t fewest_closed_captions = SIZE_MAX;
                        /* most number of closed caption assets seen in a reel */
                        size_t most_closed_captions = 0;
+                       /* true if we've seen a FFEC marker */
+                       auto have_ffec = false;
+                       /* true if we've seen a FFMC marker */
+                       auto have_ffmc = false;
 
                        for (auto reel: cpl->reels()) {
                                stage ("Checking reel", optional<boost::filesystem::path>());
@@ -1142,6 +1157,15 @@ dcp::verify (
                                        }
                                }
 
+                               if (reel->main_markers()) {
+                                       if (reel->main_markers()->get(Marker::FFEC)) {
+                                               have_ffec = true;
+                                       }
+                                       if (reel->main_markers()->get(Marker::FFMC)) {
+                                               have_ffmc = true;
+                                       }
+                               }
+
                                fewest_closed_captions = std::min (fewest_closed_captions, reel->closed_captions().size());
                                most_closed_captions = std::max (most_closed_captions, reel->closed_captions().size());
                        }
@@ -1156,6 +1180,15 @@ dcp::verify (
                                        notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::CLOSED_CAPTION_ASSET_COUNTS_DIFFER});
                                }
 
+                               if (cpl->content_kind() == FEATURE) {
+                                       if (!have_ffec) {
+                                               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_FFEC_IN_FEATURE});
+                                       }
+                                       if (!have_ffmc) {
+                                               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_FFMC_IN_FEATURE});
+                                       }
+                               }
+
                                check_text_timing (cpl->reels(), notes);
 
                                LinesCharactersResult result;
@@ -1310,6 +1343,10 @@ dcp::note_to_string (dcp::VerificationNote note)
                return "Closed caption assets must have an <EntryPoint> of 0.";
        case dcp::VerificationNote::MISSING_HASH:
                return String::compose("An asset is missing a <Hash> tag: %1", note.note().get());
+       case dcp::VerificationNote::MISSING_FFEC_IN_FEATURE:
+               return "The DCP is marked as a Feature but there is no FFEC (first frame of end credits) marker";
+       case dcp::VerificationNote::MISSING_FFMC_IN_FEATURE:
+               return "The DCP is marked as a Feature but there is no FFMC (first frame of moving credits) marker";
        }
 
        return "";
index 5ba029c98bc80480034842d6ce1be119b98683cc..5fb46a1bdf8263f69b34eda61df52b3e994c9e05 100644 (file)
@@ -153,6 +153,10 @@ public:
                CLOSED_CAPTION_ENTRY_POINT_NON_ZERO,
                /** <Hash> must be present for assets in CPLs */
                MISSING_HASH,
+               /** If ContentKind is Feature there must be a FFEC marker */
+               MISSING_FFEC_IN_FEATURE,
+               /** If ContentKind is Feature there must be a FFMC marker */
+               MISSING_FFMC_IN_FEATURE,
        };
 
        VerificationNote (Type type, Code code)
index cfc3990c301a35758f0b06cb4390309ad6138228..edb37cfbc684314c69a7c83d7ca3659f3b8712cf 100644 (file)
@@ -48,6 +48,7 @@
 #include "reel_closed_caption_asset.h"
 #include "reel_stereo_picture_asset.h"
 #include "reel_subtitle_asset.h"
+#include "reel_markers_asset.h"
 #include "compose.hpp"
 #include "test.h"
 #include <boost/test/unit_test.hpp>
@@ -1929,3 +1930,61 @@ BOOST_AUTO_TEST_CASE (verify_assets_must_have_hashes)
                });
 }
 
+
+
+BOOST_AUTO_TEST_CASE (verify_features_must_have_ffec_ffmc1)
+{
+       boost::filesystem::path const dir("build/test/verify_features_must_have_ffec_ffmc1");
+       auto dcp = make_simple (dir);
+       dcp->cpls()[0]->set_content_kind (dcp::FEATURE);
+       auto markers = make_shared<dcp::ReelMarkersAsset>(dcp::Fraction(24, 1), 0);
+       markers->set (dcp::Marker::FFEC, dcp::Time(0, 0, 4, 0, 24));
+       markers->set (dcp::Marker::FFMC, dcp::Time(0, 0, 5, 0, 24));
+       dcp->cpls()[0]->reels()[0]->add(markers);
+       dcp->write_xml (dcp::SMPTE);
+       check_verify_result ({dir}, {});
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_features_must_have_ffec_ffmc2)
+{
+       boost::filesystem::path const dir("build/test/verify_features_must_have_ffec_ffmc2");
+       auto dcp = make_simple (dir);
+       dcp->cpls()[0]->set_content_kind (dcp::FEATURE);
+       auto markers = make_shared<dcp::ReelMarkersAsset>(dcp::Fraction(24, 1), 0);
+       markers->set (dcp::Marker::FFEC, dcp::Time(0, 0, 4, 0, 24));
+       dcp->cpls()[0]->reels()[0]->add(markers);
+       dcp->write_xml (dcp::SMPTE);
+       check_verify_result ({dir}, {{dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_FFMC_IN_FEATURE}});
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_features_must_have_ffec_ffmc3)
+{
+       boost::filesystem::path const dir("build/test/verify_features_must_have_ffec_ffmc3");
+       auto dcp = make_simple (dir);
+       dcp->cpls()[0]->set_content_kind (dcp::FEATURE);
+       auto markers = make_shared<dcp::ReelMarkersAsset>(dcp::Fraction(24, 1), 0);
+       markers->set (dcp::Marker::FFMC, dcp::Time(0, 0, 4, 0, 24));
+       dcp->cpls()[0]->reels()[0]->add(markers);
+       dcp->write_xml (dcp::SMPTE);
+       check_verify_result ({dir}, {{dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_FFEC_IN_FEATURE}});
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_features_must_have_ffec_ffmc4)
+{
+       boost::filesystem::path const dir("build/test/verify_features_must_have_ffec_ffmc4");
+       auto dcp = make_simple (dir);
+       dcp->cpls()[0]->set_content_kind (dcp::FEATURE);
+       auto markers = make_shared<dcp::ReelMarkersAsset>(dcp::Fraction(24, 1), 0);
+       dcp->cpls()[0]->reels()[0]->add(markers);
+       dcp->write_xml (dcp::SMPTE);
+       check_verify_result (
+               {dir},
+               {
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_FFEC_IN_FEATURE },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_FFMC_IN_FEATURE }
+               });
+}
+