From b424b9d40a472c00d2ddbe2218375dcbd3d947fc Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 2 Feb 2023 01:03:27 +0100 Subject: [PATCH] Check IssueDate for Deluxe complaint. --- src/verify.cc | 14 ++++++++++++++ src/verify.h | 8 +++++++- test/verify_test.cc | 22 +++++++++++++++------- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/verify.cc b/src/verify.cc index 8ea9ae97..61c41743 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -79,6 +79,7 @@ #include #include #include +#include #include #include @@ -726,6 +727,17 @@ verify_smpte_subtitle_asset ( } else { notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED}); } + + if (asset->raw_xml()) { + /* Deluxe require this in their QC even if it seems never to be mentioned in any standard */ + cxml::Document doc("SubtitleReel"); + doc.read_string(*asset->raw_xml()); + auto issue_date = doc.string_child("IssueDate"); + std::regex reg("^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d$"); + if (!std::regex_match(issue_date, reg)) { + notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, issue_date}); + } + } } @@ -1955,6 +1967,8 @@ dcp::note_to_string (VerificationNote note) 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()); + case VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE: + return String::compose(" has an invalid value: %1", note.note().get()); } return ""; diff --git a/src/verify.h b/src/verify.h index 2e20bc31..1ddb7066 100644 --- a/src/verify.h +++ b/src/verify.h @@ -415,7 +415,13 @@ public: * note contains the asset ID * file contains the asset filename */ - MISSING_SUBTITLE + MISSING_SUBTITLE, + /** A SMPTE subtitle asset as an which is not of the form yyyy-mm-ddThh:mm:ss + * I can find no reference in a standard to this being required, but the Deluxe delivery + * specifications require it and their QC will fail DCPs that don't have it. + * note contains the incorrect + */ + INVALID_SUBTITLE_ISSUE_DATE }; VerificationNote (Type type, Code code) diff --git a/test/verify_test.cc b/test/verify_test.cc index 12bd3b01..eaec1617 100644 --- a/test/verify_test.cc +++ b/test/verify_test.cc @@ -834,7 +834,12 @@ BOOST_AUTO_TEST_CASE (verify_valid_smpte_subtitles) auto reel_asset = make_shared(asset, dcp::Fraction(24, 1), 6046, 0); auto cpl = write_dcp_with_single_asset (dir, reel_asset); - check_verify_result ({dir}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }}); + check_verify_result( + {dir}, + { + { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }, + { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2021-04-14T13:19:14.000+02:00"} } + }); } @@ -863,6 +868,7 @@ BOOST_AUTO_TEST_CASE (verify_invalid_smpte_subtitles) }, { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") }, { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }, + { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2020-05-09T00:29:21.000+02:00"} } }); } @@ -883,6 +889,7 @@ BOOST_AUTO_TEST_CASE (verify_empty_text_node_in_subtitles) { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME }, { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, canonical(dir / "subs.mxf") }, { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }, + { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2021-08-09T18:34:46.000+02:00"} } }); } @@ -1386,7 +1393,7 @@ BOOST_AUTO_TEST_CASE (verify_invalid_closed_caption_xml_size_in_bytes) { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, - string("419346"), + string("419336"), canonical(dir / "subs.mxf") }, { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME }, @@ -1426,7 +1433,7 @@ verify_timed_text_asset_too_large (string name) check_verify_result ( { dir }, { - { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121695542"), canonical(dir / "subs.mxf") }, + { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121695532"), canonical(dir / "subs.mxf") }, { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, string("121634816"), canonical(dir / "subs.mxf") }, { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") }, { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME }, @@ -2359,7 +2366,7 @@ BOOST_AUTO_TEST_CASE (verify_missing_main_subtitle_from_some_reels) { dir }, { { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_MAIN_SUBTITLE_FROM_SOME_REELS }, - { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() } + { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }, }); } @@ -2496,7 +2503,7 @@ verify_text_entry_point_check (path dir, dcp::VerificationNote::Code code, boost {dir}, { { dcp::VerificationNote::Type::BV21_ERROR, code, subs->id() }, - { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() } + { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }, }); } @@ -3114,7 +3121,7 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_subtitle_resource_id) "urn:uuid:%1" "Content" "Annotation" - "2018-10-02T12:25:14+02:00" + "2018-10-02T12:25:14" "1" "en-US" "25 1" @@ -3207,7 +3214,8 @@ BOOST_AUTO_TEST_CASE (verify_incorrect_timed_text_id) { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION , "240 0", boost::filesystem::canonical(subs_mxf) }, { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID }, { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME }, - { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() } + { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }, + { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2018-10-02T12:25:14+02:00"} } }); } -- 2.30.2