X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fverify.cc;h=a2298f385ce98dae4b93f62d1196d5796ffdcad1;hb=488e3d1bd5e6b17d49f6db4df14c64f4b64db89b;hp=e57439957aa8213cf63a0db1c2cc8738d90e6aef;hpb=45525875fef67ec1885968c0c5692307b16a279b;p=libdcp.git diff --git a/src/verify.cc b/src/verify.cc index e5743995..a2298f38 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -47,9 +47,11 @@ #include "raw_convert.h" #include "reel.h" #include "reel_closed_caption_asset.h" +#include "reel_interop_subtitle_asset.h" #include "reel_markers_asset.h" #include "reel_picture_asset.h" #include "reel_sound_asset.h" +#include "reel_smpte_subtitle_asset.h" #include "reel_subtitle_asset.h" #include "smpte_subtitle_asset.h" #include "stereo_picture_asset.h" @@ -637,6 +639,7 @@ struct State void verify_smpte_timed_text_asset ( shared_ptr asset, + optional reel_asset_duration, vector& notes ) { @@ -670,6 +673,16 @@ verify_smpte_timed_text_asset ( } else if (asset->start_time() != Time()) { notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_SUBTITLE_START_TIME, asset->file().get() }); } + + if (reel_asset_duration && *reel_asset_duration != asset->intrinsic_duration()) { + notes.push_back ( + { + VerificationNote::Type::BV21_ERROR, + VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION, + String::compose("%1 %2", *reel_asset_duration, asset->intrinsic_duration()), + asset->file().get() + }); + } } @@ -704,6 +717,7 @@ verify_smpte_subtitle_asset ( static void verify_subtitle_asset ( shared_ptr asset, + optional reel_asset_duration, function)> stage, boost::filesystem::path xsd_dtd_directory, vector& notes, @@ -718,7 +732,7 @@ verify_subtitle_asset ( auto smpte = dynamic_pointer_cast(asset); if (smpte) { - verify_smpte_timed_text_asset (smpte, notes); + verify_smpte_timed_text_asset (smpte, reel_asset_duration, notes); verify_smpte_subtitle_asset (smpte, notes, state); } } @@ -728,6 +742,7 @@ verify_subtitle_asset ( static void verify_closed_caption_asset ( shared_ptr asset, + optional reel_asset_duration, function)> stage, boost::filesystem::path xsd_dtd_directory, vector& notes @@ -741,7 +756,7 @@ verify_closed_caption_asset ( auto smpte = dynamic_pointer_cast(asset); if (smpte) { - verify_smpte_timed_text_asset (smpte, notes); + verify_smpte_timed_text_asset (smpte, reel_asset_duration, notes); } if (asset->raw_xml().size() > 256 * 1024) { @@ -978,7 +993,13 @@ verify_text_timing (vector> reels, vector& no return static_cast(reel->main_subtitle()); }, [](shared_ptr reel) { - return reel->main_subtitle()->asset()->raw_xml(); + auto interop = dynamic_pointer_cast(reel->main_subtitle()); + if (interop) { + return interop->asset()->raw_xml(); + } + auto smpte = dynamic_pointer_cast(reel->main_subtitle()); + DCP_ASSERT (smpte); + return smpte->asset()->raw_xml(); }, [](shared_ptr reel) { return reel->main_subtitle()->actual_duration(); @@ -1067,14 +1088,9 @@ pkl_has_encrypted_assets (shared_ptr dcp, shared_ptr pkl) for (auto i: dcp->cpls()) { for (auto j: i->reel_file_assets()) { if (j->asset_ref().resolved()) { - /* It's a bit surprising / broken but Interop subtitle assets are represented - * in reels by ReelSubtitleAsset which inherits ReelFileAsset, so it's possible for - * ReelFileAssets to have assets which are not MXFs. - */ - if (auto asset = dynamic_pointer_cast(j->asset_ref().asset())) { - if (asset->encrypted()) { - encrypted.push_back(j->asset_ref().id()); - } + auto mxf = dynamic_pointer_cast(j->asset_ref().asset()); + if (mxf && mxf->encrypted()) { + encrypted.push_back(j->asset_ref().id()); } } } @@ -1221,7 +1237,7 @@ dcp::verify ( notes.push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::INVALID_INTRINSIC_DURATION, i->id()}); } auto file_asset = dynamic_pointer_cast(i); - if (file_asset && !file_asset->hash()) { + if (i->encryptable() && !file_asset->hash()) { notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_HASH, i->id()}); } } @@ -1268,7 +1284,7 @@ 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, state); + verify_subtitle_asset (reel->main_subtitle()->asset(), reel->main_subtitle()->duration(), stage, *xsd_dtd_directory, notes, state); } have_main_subtitle = true; } else { @@ -1278,7 +1294,7 @@ dcp::verify ( for (auto 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(), i->duration(), stage, *xsd_dtd_directory, notes); } } @@ -1580,6 +1596,13 @@ dcp::note_to_string (VerificationNote note) return "The Resource ID in a timed text MXF did not match the ID of the contained XML."; case VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID: return "The Asset ID in a timed text MXF is the same as the Resource ID or that of the contained XML."; + case VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION: + { + vector parts; + boost::split (parts, note.note().get(), boost::is_any_of(" ")); + DCP_ASSERT (parts.size() == 2); + return String::compose("The reel duration of some timed text (%1) is not the same as the ContainerDuration of its MXF (%2).", parts[0], parts[1]); + } } return "";