From: Carl Hetherington Date: Mon, 14 Dec 2020 23:51:34 +0000 (+0100) Subject: Bv2.1 7.2.2: Check that subtitle languages are the same for all reels. X-Git-Tag: v1.8.0~186 X-Git-Url: https://main.carlh.net/gitweb/?p=libdcp.git;a=commitdiff_plain;h=e182156f75a74457c4452cc3bfe91d778d0d7148 Bv2.1 7.2.2: Check that subtitle languages are the same for all reels. --- diff --git a/BRANCH b/BRANCH index 09e77d12..7b9aab02 100644 --- a/BRANCH +++ b/BRANCH @@ -24,6 +24,6 @@ Mark things with [Bv2.1_paragraph] - Timed text XML files for closed captions must be <= 256kB [/] - Timed text total track asset must be <= 115MB [/] - Font resource <= 10MB [/] -7.2.2 Language Element shall be present [/] and contiguous across all MainSubtitles. +7.2.2 Language Element shall be present [/] and contiguous across all MainSubtitles [/] diff --git a/src/verify.cc b/src/verify.cc index 1b476ef2..0b7def3c 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -640,12 +640,19 @@ verify_closed_caption_reel (shared_ptr reel_asset, } +struct State +{ + boost::optional subtitle_language; +}; + + static void verify_subtitle_asset ( shared_ptr asset, function)> stage, boost::filesystem::path xsd_dtd_directory, - list& notes + list& notes, + State& state ) { stage ("Checking subtitle XML", asset->file()); @@ -657,7 +664,17 @@ verify_subtitle_asset ( shared_ptr smpte = dynamic_pointer_cast(asset); if (smpte) { if (smpte->language()) { - verify_language_tag (*smpte->language(), notes); + string const language = *smpte->language(); + verify_language_tag (language, notes); + if (!state.subtitle_language) { + state.subtitle_language = language; + } else if (state.subtitle_language != language) { + notes.push_back ( + VerificationNote( + VerificationNote::VERIFY_BV21_ERROR, VerificationNote::SUBTITLE_LANGUAGES_DIFFER, *asset->file() + ) + ); + } } else { notes.push_back ( VerificationNote( @@ -696,10 +713,11 @@ verify_closed_caption_asset ( shared_ptr asset, function)> stage, boost::filesystem::path xsd_dtd_directory, - list& notes + list& notes, + State& state ) { - verify_subtitle_asset (asset, stage, xsd_dtd_directory, notes); + verify_subtitle_asset (asset, stage, xsd_dtd_directory, notes, state); if (asset->raw_xml().size() > 256 * 1024) { notes.push_back ( @@ -722,6 +740,7 @@ dcp::verify ( xsd_dtd_directory = boost::filesystem::canonical (xsd_dtd_directory); list notes; + State state; list > dcps; BOOST_FOREACH (boost::filesystem::path i, directories) { @@ -804,14 +823,14 @@ dcp::verify ( if (reel->main_subtitle()) { verify_main_subtitle_reel (reel->main_subtitle(), notes); if (reel->main_subtitle()->asset_ref().resolved()) { - verify_subtitle_asset (reel->main_subtitle()->asset(), stage, xsd_dtd_directory, notes); + verify_subtitle_asset (reel->main_subtitle()->asset(), stage, xsd_dtd_directory, notes, state); } } BOOST_FOREACH (shared_ptr i, reel->closed_captions()) { verify_closed_caption_reel (i, notes); if (i->asset_ref().resolved()) { - verify_closed_caption_asset (i->asset(), stage, xsd_dtd_directory, notes); + verify_closed_caption_asset (i->asset(), stage, xsd_dtd_directory, notes, state); } } } @@ -891,6 +910,8 @@ dcp::note_to_string (dcp::VerificationNote note) return String::compose("The total size of the fonts in timed text asset %1 is larger than the 10MB maximum required by Bv2.1", note.file()->filename()); case dcp::VerificationNote::MISSING_SUBTITLE_LANGUAGE: return String::compose("The XML for a SMPTE subtitle asset has no tag, which is required by Bv2.1", note.file()->filename()); + case dcp::VerificationNote::SUBTITLE_LANGUAGES_DIFFER: + return String::compose("Some subtitle assets have different tags than others", note.file()->filename()); } return ""; diff --git a/src/verify.h b/src/verify.h index 8a049dd5..170aeb8b 100644 --- a/src/verify.h +++ b/src/verify.h @@ -110,6 +110,8 @@ public: TIMED_TEXT_FONTS_TOO_LARGE_IN_BYTES, /** Some SMPTE subtitle XML has no tag [Bv2.1_7.2.2] */ MISSING_SUBTITLE_LANGUAGE, + /** Not all subtitle assets specify the same tag [Bv2.1_7.2.2] */ + SUBTITLE_LANGUAGES_DIFFER, }; VerificationNote (Type type, Code code) diff --git a/test/test.h b/test/test.h index 1d9cd921..10f99ce1 100644 --- a/test/test.h +++ b/test/test.h @@ -45,6 +45,7 @@ extern void check_xml (std::string ref, std::string test, std::list extern void check_file (boost::filesystem::path ref, boost::filesystem::path check); extern std::shared_ptr simple_picture (boost::filesystem::path path, std::string suffix); extern std::shared_ptr simple_sound (boost::filesystem::path path, std::string suffix, dcp::MXFMetadata mxf_meta, std::string language); +extern std::shared_ptr simple_subtitle (); extern std::shared_ptr make_simple (boost::filesystem::path path, int reels = 1); extern std::shared_ptr make_simple_with_interop_subs (boost::filesystem::path path); extern std::shared_ptr make_simple_with_smpte_subs (boost::filesystem::path path); diff --git a/test/verify_test.cc b/test/verify_test.cc index 24d583b6..9bb3859a 100644 --- a/test/verify_test.cc +++ b/test/verify_test.cc @@ -1335,3 +1335,39 @@ BOOST_AUTO_TEST_CASE (verify_missing_language_tag_in_subtitle_xml) BOOST_CHECK_EQUAL (notes.front().type(), dcp::VerificationNote::VERIFY_BV21_ERROR); BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::MISSING_SUBTITLE_LANGUAGE); } + + +BOOST_AUTO_TEST_CASE (verify_inconsistent_subtitle_languages) +{ + boost::filesystem::path path ("build/test/verify_inconsistent_subtitle_languages"); + shared_ptr dcp = make_simple (path, 2); + shared_ptr cpl = dcp->cpls().front(); + + { + shared_ptr subs(new dcp::SMPTESubtitleAsset()); + subs->set_language (dcp::LanguageTag("de-DE")); + subs->add (simple_subtitle()); + subs->write (path / "subs1.mxf"); + shared_ptr reel_subs(new dcp::ReelSubtitleAsset(subs, dcp::Fraction(24, 1), 240, 0)); + cpl->reels().front()->add (reel_subs); + } + + { + shared_ptr subs(new dcp::SMPTESubtitleAsset()); + subs->set_language (dcp::LanguageTag("en-US")); + subs->add (simple_subtitle()); + subs->write (path / "subs2.mxf"); + shared_ptr reel_subs(new dcp::ReelSubtitleAsset(subs, dcp::Fraction(24, 1), 240, 0)); + cpl->reels().back()->add (reel_subs); + } + + dcp->write_xml (dcp::SMPTE); + + vector dirs; + dirs.push_back (path); + list notes = dcp::verify (dirs, &stage, &progress, xsd_test); + BOOST_REQUIRE_EQUAL (notes.size(), 1U); + BOOST_CHECK_EQUAL (notes.front().type(), dcp::VerificationNote::VERIFY_BV21_ERROR); + BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::SUBTITLE_LANGUAGES_DIFFER); +} +