diff options
| -rw-r--r-- | src/verify.cc | 14 | ||||
| -rw-r--r-- | src/verify.h | 8 | ||||
| -rw-r--r-- | 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 <boost/algorithm/string.hpp> #include <iostream> #include <map> +#include <regex> #include <set> #include <vector> @@ -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("<IssueDate> 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 <IssueDate> 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 <IssueDate> + */ + 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<dcp::ReelSMPTESubtitleAsset>(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) "<Id>urn:uuid:%1</Id>" "<ContentTitleText>Content</ContentTitleText>" "<AnnotationText>Annotation</AnnotationText>" - "<IssueDate>2018-10-02T12:25:14+02:00</IssueDate>" + "<IssueDate>2018-10-02T12:25:14</IssueDate>" "<ReelNumber>1</ReelNumber>" "<Language>en-US</Language>" "<EditRate>25 1</EditRate>" @@ -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"} } }); } |
