class DCPErrorHandler : public ErrorHandler
{
public:
- void warning(const SAXParseException& e)
+ void warning(const SAXParseException& e) override
{
maybe_add (XMLValidationError(e));
}
- void error(const SAXParseException& e)
+ void error(const SAXParseException& e) override
{
maybe_add (XMLValidationError(e));
}
- void fatalError(const SAXParseException& e)
+ void fatalError(const SAXParseException& e) override
{
maybe_add (XMLValidationError(e));
}
- void resetErrors() {
+ void resetErrors() override {
_errors.clear ();
}
add("http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL", "SMPTE-429-10-2008.xsd");
}
- InputSource* resolveEntity(XMLCh const *, XMLCh const * system_id)
+ InputSource* resolveEntity(XMLCh const *, XMLCh const * system_id) override
{
if (!system_id) {
return 0;
}
DCP_ASSERT (asset->resource_id());
- if (asset->resource_id().get() != asset->xml_id()) {
- notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISMATCHED_TIMED_TEXT_RESOURCE_ID });
- }
+ auto xml_id = asset->xml_id();
+ if (xml_id) {
+ if (asset->resource_id().get() != xml_id) {
+ notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISMATCHED_TIMED_TEXT_RESOURCE_ID });
+ }
- if (asset->id() == asset->resource_id().get() || asset->id() == asset->xml_id()) {
- notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID });
+ if (asset->id() == asset->resource_id().get() || asset->id() == xml_id) {
+ notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID });
+ }
+ } else {
+ notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
}
}
/* Note: we must not use SubtitleAsset::xml_as_string() here as that will mean the data on disk
* gets passed through libdcp which may clean up and therefore hide errors.
*/
- validate_xml (asset->raw_xml(), xsd_dtd_directory, notes);
+ if (asset->raw_xml()) {
+ validate_xml (asset->raw_xml().get(), xsd_dtd_directory, notes);
+ } else {
+ notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
+ }
auto smpte = dynamic_pointer_cast<const SMPTESubtitleAsset>(asset);
if (smpte) {
/* Note: we must not use SubtitleAsset::xml_as_string() here as that will mean the data on disk
* gets passed through libdcp which may clean up and therefore hide errors.
*/
- validate_xml (asset->raw_xml(), xsd_dtd_directory, notes);
+ auto raw_xml = asset->raw_xml();
+ if (raw_xml) {
+ validate_xml (*raw_xml, xsd_dtd_directory, notes);
+ if (raw_xml->size() > 256 * 1024) {
+ notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, raw_convert<string>(raw_xml->size()), *asset->file()});
+ }
+ } else {
+ notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
+ }
auto smpte = dynamic_pointer_cast<const SMPTESubtitleAsset>(asset);
if (smpte) {
verify_smpte_timed_text_asset (smpte, reel_asset_duration, notes);
}
-
- if (asset->raw_xml().size() > 256 * 1024) {
- notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, raw_convert<string>(asset->raw_xml().size()), *asset->file()});
- }
}
int edit_rate,
vector<VerificationNote>& notes,
std::function<bool (shared_ptr<Reel>)> check,
- std::function<string (shared_ptr<Reel>)> xml,
+ std::function<optional<string> (shared_ptr<Reel>)> xml,
std::function<int64_t (shared_ptr<Reel>)> duration
)
{
continue;
}
+ auto reel_xml = xml(reels[i]);
+ if (!reel_xml) {
+ notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
+ continue;
+ }
+
/* We need to look at <Subtitle> instances in the XML being checked, so we can't use the subtitles
* read in by libdcp's parser.
*/
optional<Time> start_time;
try {
doc = make_shared<cxml::Document>("SubtitleReel");
- doc->read_string (xml(reels[i]));
+ doc->read_string (*reel_xml);
tcr = doc->number_child<int>("TimeCodeRate");
auto start_time_string = doc->optional_string_child("StartTime");
if (start_time_string) {
}
} catch (...) {
doc = make_shared<cxml::Document>("DCSubtitle");
- doc->read_string (xml(reels[i]));
+ doc->read_string (*reel_xml);
}
parse (doc, tcr, start_time, edit_rate, i == 0);
auto end = reel_offset + duration(reels[i]);
stage ("Checking DCP", dcp->directory());
bool carry_on = true;
try {
- dcp->read (¬es);
+ dcp->read (¬es, true);
} catch (MissingAssetmapError& e) {
notes.push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::FAILED_READ, string(e.what())});
carry_on = false;
return String::compose("The instantaneous bit rate of the picture asset %1 is close to the limit of 250Mbit/s in at least one place.", note.file()->filename());
case VerificationNote::Code::EXTERNAL_ASSET:
return String::compose("The asset %1 that this DCP refers to is not included in the DCP. It may be a VF.", note.note().get());
+ case VerificationNote::Code::THREED_ASSET_MARKED_AS_TWOD:
+ return String::compose("The asset %1 is 3D but its MXF is marked as 2D.", note.file()->filename());
case VerificationNote::Code::INVALID_STANDARD:
return "This DCP does not use the SMPTE standard.";
case VerificationNote::Code::INVALID_LANGUAGE:
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]);
}
+ case VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED:
+ return "Some aspect of this DCP could not be checked because it is encrypted.";
}
return "";
}
+bool
+dcp::operator< (dcp::VerificationNote const& a, dcp::VerificationNote const& b)
+{
+ if (a.type() != b.type()) {
+ return a.type() < b.type();
+ }
+
+ if (a.code() != b.code()) {
+ return a.code() < b.code();
+ }
+
+ if (a.note() != b.note()) {
+ return a.note().get_value_or("") < b.note().get_value_or("");
+ }
+
+ if (a.file() != b.file()) {
+ return a.file().get_value_or("") < b.file().get_value_or("");
+ }
+
+ return a.line().get_value_or(0) < b.line().get_value_or(0);
+}
+
+
std::ostream&
dcp::operator<< (std::ostream& s, dcp::VerificationNote const& note)
{