X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fverify.cc;h=0445a854e7a513df61654f2c98e8cd7e6b0eb65a;hb=9d3e7f716accd67985f23048b4c36e7581348848;hp=76d7c18d401a4c27f72f0177e419abea61d41854;hpb=623e1979815d1282b4a4ce5fadf8e8a6e93a8368;p=libdcp.git diff --git a/src/verify.cc b/src/verify.cc index 76d7c18d..0445a854 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Carl Hetherington + Copyright (C) 2018-2019 Carl Hetherington This file is part of libdcp. @@ -33,19 +33,68 @@ #include "verify.h" #include "dcp.h" +#include "cpl.h" +#include "reel.h" +#include "reel_picture_asset.h" +#include "reel_sound_asset.h" #include "exceptions.h" +#include "compose.hpp" #include #include #include +#include using std::list; using std::vector; +using std::string; +using std::cout; using boost::shared_ptr; +using boost::optional; +using boost::function; using namespace dcp; +enum Result { + RESULT_GOOD, + RESULT_CPL_PKL_DIFFER, + RESULT_BAD +}; + +static Result +verify_asset (shared_ptr dcp, shared_ptr reel_asset, function progress) +{ + string const actual_hash = reel_asset->asset_ref()->hash(progress); + + list > pkls = dcp->pkls(); + /* We've read this DCP in so it must have at least one PKL */ + DCP_ASSERT (!pkls.empty()); + + shared_ptr asset = reel_asset->asset_ref().asset(); + + optional pkl_hash; + BOOST_FOREACH (shared_ptr i, pkls) { + pkl_hash = i->hash (reel_asset->asset_ref()->id()); + if (pkl_hash) { + break; + } + } + + DCP_ASSERT (pkl_hash); + + optional cpl_hash = reel_asset->hash(); + if (cpl_hash && *cpl_hash != *pkl_hash) { + return RESULT_CPL_PKL_DIFFER; + } + + if (actual_hash != *pkl_hash) { + return RESULT_BAD; + } + + return RESULT_GOOD; +} + list -dcp::verify (vector directories) +dcp::verify (vector directories, function)> stage, function progress) { list notes; @@ -54,14 +103,81 @@ dcp::verify (vector directories) dcps.push_back (shared_ptr (new DCP (i))); } - BOOST_FOREACH (shared_ptr i, dcps) { + BOOST_FOREACH (shared_ptr dcp, dcps) { + stage ("Checking DCP", dcp->directory()); DCP::ReadErrors errors; try { - i->read (true, &errors); + dcp->read (true, &errors); } catch (DCPReadError& e) { - notes.push_back (VerificationNote (VerificationNote::ERROR, e.what ())); + notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::GENERAL_READ, string(e.what()))); } catch (XMLError& e) { - notes.push_back (VerificationNote (VerificationNote::ERROR, e.what ())); + notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::GENERAL_READ, string(e.what()))); + } + + BOOST_FOREACH (shared_ptr cpl, dcp->cpls()) { + stage ("Checking CPL", cpl->file()); + + /* Check that the CPL's hash corresponds to the PKL */ + BOOST_FOREACH (shared_ptr i, dcp->pkls()) { + optional h = i->hash(cpl->id()); + if (h && make_digest(Data(*cpl->file())) != *h) { + notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::CPL_HASH_INCORRECT)); + } + } + + BOOST_FOREACH (shared_ptr reel, cpl->reels()) { + stage ("Checking reel", optional()); + if (reel->main_picture()) { + /* Check reel stuff */ + Fraction const frame_rate = reel->main_picture()->frame_rate(); + if (frame_rate.denominator != 1 || + (frame_rate.numerator != 24 && + frame_rate.numerator != 25 && + frame_rate.numerator != 30 && + frame_rate.numerator != 48 && + frame_rate.numerator != 50 && + frame_rate.numerator != 60)) { + notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::INVALID_PICTURE_FRAME_RATE)); + } + /* Check asset */ + if (reel->main_picture()->asset_ref().resolved()) { + stage ("Checking picture asset hash", reel->main_picture()->asset()->file()); + Result const r = verify_asset (dcp, reel->main_picture(), progress); + switch (r) { + case RESULT_BAD: + notes.push_back ( + VerificationNote( + VerificationNote::VERIFY_ERROR, VerificationNote::PICTURE_HASH_INCORRECT, *reel->main_picture()->asset()->file() + ) + ); + break; + case RESULT_CPL_PKL_DIFFER: + notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::PKL_CPL_PICTURE_HASHES_DISAGREE)); + break; + default: + break; + } + } + } + if (reel->main_sound() && reel->main_sound()->asset_ref().resolved()) { + stage ("Checking sound asset hash", reel->main_sound()->asset()->file()); + Result const r = verify_asset (dcp, reel->main_sound(), progress); + switch (r) { + case RESULT_BAD: + notes.push_back ( + VerificationNote( + VerificationNote::VERIFY_ERROR, VerificationNote::SOUND_HASH_INCORRECT, *reel->main_sound()->asset()->file() + ) + ); + break; + case RESULT_CPL_PKL_DIFFER: + notes.push_back (VerificationNote (VerificationNote::VERIFY_ERROR, VerificationNote::PKL_CPL_SOUND_HASHES_DISAGREE)); + break; + default: + break; + } + } + } } }