From 8fca5499789ae1deb2dbcad8d3501a8f42fb95f0 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 2 Oct 2012 21:51:56 +0100 Subject: [PATCH 1/1] Clean up DCP comparison a bit. --- src/asset.h | 2 +- src/dcp.cc | 59 ++++++------ src/dcp.h | 8 +- src/mxf_asset.cc | 39 ++++---- src/mxf_asset.h | 2 +- src/picture_asset.cc | 209 +++++++++++++++++++++---------------------- src/picture_asset.h | 11 +-- src/reel.cc | 32 ++++--- src/reel.h | 2 +- src/sound_asset.cc | 17 ++-- src/sound_asset.h | 2 +- src/subtitle_asset.h | 5 +- src/types.h | 13 ++- tools/dcpdiff.cc | 22 ++--- 14 files changed, 212 insertions(+), 211 deletions(-) diff --git a/src/asset.h b/src/asset.h index eab24d28..32fd93ae 100644 --- a/src/asset.h +++ b/src/asset.h @@ -68,7 +68,7 @@ public: return _uuid; } - virtual std::list equals (boost::shared_ptr other, EqualityOptions opt) const = 0; + virtual bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const = 0; protected: friend class PictureAsset; diff --git a/src/dcp.cc b/src/dcp.cc index fb7fb288..9a83edfd 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -245,26 +245,26 @@ DCP::read (bool require_mxfs) } -list -DCP::equals (DCP const & other, EqualityOptions opt) const +bool +DCP::equals (DCP const & other, EqualityOptions opt, list& notes) const { - list notes; - if (_cpls.size() != other._cpls.size()) { notes.push_back ("CPL counts differ"); + return false; } list >::const_iterator a = _cpls.begin (); list >::const_iterator b = other._cpls.begin (); while (a != _cpls.end ()) { - list n = (*a)->equals (*b->get(), opt); - notes.merge (n); + if (!(*a)->equals (*b->get(), opt, notes)) { + return false; + } ++a; ++b; } - return notes; + return true; } @@ -509,39 +509,44 @@ CPL::write_to_assetmap (ostream& s) const -list -CPL::equals (CPL const & other, EqualityOptions opt) const +bool +CPL::equals (CPL const & other, EqualityOptions opt, list& notes) const { - list notes; - - if (opt.flags & LIBDCP_METADATA) { - if (_name != other._name) { - notes.push_back ("names differ"); - } - if (_content_kind != other._content_kind) { - notes.push_back ("content kinds differ"); - } - if (_fps != other._fps) { - notes.push_back ("frames per second differ"); - } - if (_length != other._length) { - notes.push_back ("lengths differ"); - } + if (_name != other._name) { + notes.push_back ("names differ"); + return false; + } + + if (_content_kind != other._content_kind) { + notes.push_back ("content kinds differ"); + return false; + } + + if (_fps != other._fps) { + notes.push_back ("frames per second differ"); + return false; + } + + if (_length != other._length) { + notes.push_back ("lengths differ"); + return false; } if (_reels.size() != other._reels.size()) { notes.push_back ("reel counts differ"); + return false; } list >::const_iterator a = _reels.begin (); list >::const_iterator b = other._reels.begin (); while (a != _reels.end ()) { - list n = (*a)->equals (*b, opt); - notes.merge (n); + if (!(*a)->equals (*b, opt, notes)) { + return false; + } ++a; ++b; } - return notes; + return true; } diff --git a/src/dcp.h b/src/dcp.h index 79be5ca5..1ae5cf97 100644 --- a/src/dcp.h +++ b/src/dcp.h @@ -83,7 +83,7 @@ public: std::list > assets () const; - std::list equals (CPL const & other, EqualityOptions options) const; + bool equals (CPL const & other, EqualityOptions options, std::list& notes) const; void write_xml () const; void write_to_assetmap (std::ostream& s) const; @@ -139,10 +139,10 @@ public: /** Compare this DCP with another, according to various options. * @param other DCP to compare this one to. * @param options Options to define just what "equality" means. - * @return An empty list if the DCPs are equal; otherwise a list of messages - * which explain the ways in which they differ. + * @param notes Filled in with notes about differences. + * @return true if the DCPs are equal according to EqualityOptions, otherwise false. */ - std::list equals (DCP const & other, EqualityOptions options) const; + bool equals (DCP const & other, EqualityOptions options, std::list& notes) const; void add_cpl (boost::shared_ptr cpl); diff --git a/src/mxf_asset.cc b/src/mxf_asset.cc index 2246c55d..d0e02c8b 100644 --- a/src/mxf_asset.cc +++ b/src/mxf_asset.cc @@ -57,37 +57,40 @@ MXFAsset::fill_writer_info (ASDCP::WriterInfo* writer_info) const assert (c == Kumu::UUID_Length); } -list -MXFAsset::equals (shared_ptr other, EqualityOptions opt) const +bool +MXFAsset::equals (shared_ptr other, EqualityOptions opt, list& notes) const { shared_ptr other_mxf = dynamic_pointer_cast (other); if (!other_mxf) { - return list (); + notes.push_back ("comparing an MXF asset with a non-MXF asset"); + return false; } - list notes; + if (_file_name != other_mxf->_file_name) { + notes.push_back ("MXF names differ"); + return false; + } + + if (_fps != other_mxf->_fps) { + notes.push_back ("MXF frames per second differ"); + return false; + } - if (opt.flags & LIBDCP_METADATA) { - if (_file_name != other_mxf->_file_name) { - notes.push_back ("MXF names differ"); - } - if (_fps != other_mxf->_fps) { - notes.push_back ("MXF frames per second differ"); - } - if (_length != other_mxf->_length) { - notes.push_back ("MXF lengths differ"); - } + if (_length != other_mxf->_length) { + notes.push_back ("MXF lengths differ"); + return false; } - if (opt.flags & MXF_BITWISE) { + if (opt.bitwise) { if (digest() != other_mxf->digest()) { notes.push_back ("MXF digests differ"); + return false; } if (filesystem::file_size (path()) != filesystem::file_size (other_mxf->path())) { notes.push_back (path().string() + " and " + other_mxf->path().string() + " sizes differ"); - return notes; + return false; } ifstream a (path().string().c_str(), ios::binary); @@ -106,14 +109,14 @@ MXFAsset::equals (shared_ptr other, EqualityOptions opt) const if (memcmp (abuffer, bbuffer, t) != 0) { notes.push_back (path().string() + " and " + other_mxf->path().string() + " content differs"); - return notes; + return false; } n -= t; } } - return notes; + return true; } int diff --git a/src/mxf_asset.h b/src/mxf_asset.h index 7f36b30a..240e042d 100644 --- a/src/mxf_asset.h +++ b/src/mxf_asset.h @@ -38,7 +38,7 @@ public: */ MXFAsset (std::string directory, std::string file_name, sigc::signal1* progress, int fps, int entry_point, int length); - virtual std::list equals (boost::shared_ptr other, EqualityOptions opt) const; + virtual bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; int length () const; diff --git a/src/picture_asset.cc b/src/picture_asset.cc index a1d8321d..898fe75b 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -63,12 +63,14 @@ PictureAsset::write_to_cpl (ostream& s) const << " \n"; } -list -PictureAsset::equals (shared_ptr other, EqualityOptions opt) const +bool +PictureAsset::equals (shared_ptr other, EqualityOptions opt, list& notes) const { - list notes = MXFAsset::equals (other, opt); + if (!MXFAsset::equals (other, opt, notes)) { + return false; + } - if (opt.flags & MXF_INSPECT) { + if (!opt.bitwise) { ASDCP::JP2K::MXFReader reader_A; if (ASDCP_FAILURE (reader_A.OpenRead (path().string().c_str()))) { throw MXFFileError ("could not open MXF file for reading", path().string()); @@ -119,7 +121,7 @@ PictureAsset::equals (shared_ptr other, EqualityOptions opt) const // } } - return notes; + return true; } @@ -229,139 +231,134 @@ MonoPictureAsset::get_frame (int n) const } -list -MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt) const +bool +MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt, list& notes) const { - list notes = PictureAsset::equals (other, opt); + if (!PictureAsset::equals (other, opt, notes)) { + return false; + } shared_ptr other_picture = dynamic_pointer_cast (other); assert (other_picture); - for (int i = 0; i < _length; ++i) { - shared_ptr frame_A = get_frame (i); - shared_ptr frame_B = other_picture->get_frame (i); - - list n = frame_buffer_equals ( - i, opt, - frame_A->j2k_frame()->RoData(), frame_A->j2k_frame()->Size(), - frame_B->j2k_frame()->RoData(), frame_B->j2k_frame()->Size() - ); - - notes.merge (n); + if (!opt.bitwise) { + for (int i = 0; i < _length; ++i) { + shared_ptr frame_A = get_frame (i); + shared_ptr frame_B = other_picture->get_frame (i); + + if (!frame_buffer_equals ( + i, opt, notes, + frame_A->j2k_frame()->RoData(), frame_A->j2k_frame()->Size(), + frame_B->j2k_frame()->RoData(), frame_B->j2k_frame()->Size() + )) { + return false; + } + } } - return notes; + return true; } -list -StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt) const +bool +StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, list& notes) const { - list notes = PictureAsset::equals (other, opt); + if (!PictureAsset::equals (other, opt, notes)) { + return false; + } shared_ptr other_picture = dynamic_pointer_cast (other); assert (other_picture); - - for (int i = 0; i < _length; ++i) { - shared_ptr frame_A = get_frame (i); - shared_ptr frame_B = other_picture->get_frame (i); - - list n = frame_buffer_equals ( - i, opt, - frame_A->j2k_frame()->Left.RoData(), frame_A->j2k_frame()->Left.Size(), - frame_B->j2k_frame()->Left.RoData(), frame_B->j2k_frame()->Left.Size() - ); - - notes.merge (n); - n = frame_buffer_equals ( - i, opt, - frame_A->j2k_frame()->Right.RoData(), frame_A->j2k_frame()->Right.Size(), - frame_B->j2k_frame()->Right.RoData(), frame_B->j2k_frame()->Right.Size() - ); + if (!opt.bitwise) { + + for (int i = 0; i < _length; ++i) { + shared_ptr frame_A = get_frame (i); + shared_ptr frame_B = other_picture->get_frame (i); + + if (!frame_buffer_equals ( + i, opt, notes, + frame_A->j2k_frame()->Left.RoData(), frame_A->j2k_frame()->Left.Size(), + frame_B->j2k_frame()->Left.RoData(), frame_B->j2k_frame()->Left.Size() + )) { + return false; + } - notes.merge (n); + if (!frame_buffer_equals ( + i, opt, notes, + frame_A->j2k_frame()->Right.RoData(), frame_A->j2k_frame()->Right.Size(), + frame_B->j2k_frame()->Right.RoData(), frame_B->j2k_frame()->Right.Size() + )) { + return false; + } + } } - return notes; + return true; } -list +bool PictureAsset::frame_buffer_equals ( - int frame, EqualityOptions opt, uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B + int frame, EqualityOptions opt, list& notes, uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B ) const { - list notes; + if (size_A == size_B && memcmp (data_A, data_B, size_A) == 0) { + /* Easy result; the J2K data is identical */ + return true; + } + + /* Decompress the images to bitmaps */ + opj_image_t* image_A = decompress_j2k (const_cast (data_A), size_A, 0); + opj_image_t* image_B = decompress_j2k (const_cast (data_B), size_B, 0); + + /* Compare them */ - bool j2k_same = true; - if (size_A != size_B) { - notes.push_back ("sizes of video data for frame " + lexical_cast(frame) + " differ"); - j2k_same = false; - } else if (memcmp (data_A, data_B, size_A) != 0) { - notes.push_back ("J2K data for frame " + lexical_cast(frame) + " differ"); - j2k_same = false; + if (image_A->numcomps != image_B->numcomps) { + notes.push_back ("image component counts for frame " + lexical_cast(frame) + " differ"); + return false; } - if (!j2k_same) { - - if (opt.verbose) { - cout << "J2K images for " << frame << " differ; checking by pixel\n"; - } - - /* Decompress the images to bitmaps */ - opj_image_t* image_A = decompress_j2k (const_cast (data_A), size_A, 0); - opj_image_t* image_B = decompress_j2k (const_cast (data_B), size_B, 0); - - /* Compare them */ - - if (image_A->numcomps != image_B->numcomps) { - notes.push_back ("image component counts for frame " + lexical_cast(frame) + " differ"); - } - - vector abs_diffs (image_A->comps[0].w * image_A->comps[0].h * image_A->numcomps); - int d = 0; - int max_diff = 0; - - for (int c = 0; c < image_A->numcomps; ++c) { - - if (image_A->comps[c].w != image_B->comps[c].w || image_A->comps[c].h != image_B->comps[c].h) { - notes.push_back ("image sizes for frame " + lexical_cast(frame) + " differ"); - } - - int const pixels = image_A->comps[c].w * image_A->comps[c].h; - for (int j = 0; j < pixels; ++j) { - int const t = abs (image_A->comps[c].data[j] - image_B->comps[c].data[j]); - abs_diffs[d++] = t; - max_diff = max (max_diff, t); - } - } - - uint64_t total = 0; - for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { - total += *j; - } - - double const mean = double (total) / abs_diffs.size (); - - uint64_t total_squared_deviation = 0; - for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { - total_squared_deviation += pow (*j - mean, 2); - } - - double const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size()); + vector abs_diffs (image_A->comps[0].w * image_A->comps[0].h * image_A->numcomps); + int d = 0; + int max_diff = 0; + + for (int c = 0; c < image_A->numcomps; ++c) { - if (mean > opt.max_mean_pixel_error || std_dev > opt.max_std_dev_pixel_error) { - notes.push_back ("mean or standard deviation out of range for " + lexical_cast(frame)); + if (image_A->comps[c].w != image_B->comps[c].w || image_A->comps[c].h != image_B->comps[c].h) { + notes.push_back ("image sizes for frame " + lexical_cast(frame) + " differ"); + return false; } - if (opt.verbose) { - cout << "\tmax pixel error " << max_diff << ", mean pixel error " << mean << ", standard deviation " << std_dev << "\n"; + int const pixels = image_A->comps[c].w * image_A->comps[c].h; + for (int j = 0; j < pixels; ++j) { + int const t = abs (image_A->comps[c].data[j] - image_B->comps[c].data[j]); + abs_diffs[d++] = t; + max_diff = max (max_diff, t); } + } - opj_image_destroy (image_A); - opj_image_destroy (image_B); + uint64_t total = 0; + for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { + total += *j; + } + + double const mean = double (total) / abs_diffs.size (); + + uint64_t total_squared_deviation = 0; + for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { + total_squared_deviation += pow (*j - mean, 2); + } + + double const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size()); + + if (mean > opt.max_mean_pixel_error || std_dev > opt.max_std_dev_pixel_error) { + notes.push_back ("mean or standard deviation out of range for " + lexical_cast(frame)); + return false; } + + opj_image_destroy (image_A); + opj_image_destroy (image_B); - return notes; + return true; } diff --git a/src/picture_asset.h b/src/picture_asset.h index baea22c3..da3eb7d0 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -41,7 +41,7 @@ public: */ void write_to_cpl (std::ostream& s) const; - std::list equals (boost::shared_ptr other, EqualityOptions opt) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; int width () const { return _width; @@ -53,8 +53,9 @@ public: protected: - std::list frame_buffer_equals ( - int frame, EqualityOptions opt, uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B + bool frame_buffer_equals ( + int frame, EqualityOptions opt, std::list& notes, + uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B ) const; /** picture width in pixels */ @@ -114,7 +115,7 @@ public: MonoPictureAsset (std::string directory, std::string mxf_name, int fps, int entry_point, int length); boost::shared_ptr get_frame (int n) const; - std::list equals (boost::shared_ptr other, EqualityOptions opt) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; private: std::string path_from_list (int f, std::vector const & files) const; @@ -128,7 +129,7 @@ public: StereoPictureAsset (std::string directory, std::string mxf_name, int fps, int entry_point, int length); boost::shared_ptr get_frame (int n) const; - std::list equals (boost::shared_ptr other, EqualityOptions opt) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; }; diff --git a/src/reel.cc b/src/reel.cc index 50426cc1..52a4f0fb 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -46,38 +46,36 @@ Reel::write_to_cpl (ostream& s) const } } -list -Reel::equals (boost::shared_ptr other, EqualityOptions opt) const +bool +Reel::equals (boost::shared_ptr other, EqualityOptions opt, list& notes) const { - list o; - if ((_main_picture && !other->_main_picture) || (!_main_picture && other->_main_picture)) { - o.push_back ("reel has different assets"); + notes.push_back ("reel has different assets"); + return false; } - if (_main_picture) { - list m = _main_picture->equals (other->_main_picture, opt); - o.merge (m); + if (_main_picture && !_main_picture->equals (other->_main_picture, opt, notes)) { + return false; } if ((_main_sound && !other->_main_sound) || (!_main_sound && other->_main_sound)) { - o.push_back ("reel has different assets"); + notes.push_back ("reel has different assets"); + return false; } - if (_main_sound) { - list m = _main_sound->equals (other->_main_sound, opt); - o.merge (m); + if (_main_sound && !_main_sound->equals (other->_main_sound, opt, notes)) { + return false; } if ((_main_subtitle && !other->_main_subtitle) || (!_main_subtitle && other->_main_subtitle)) { - o.push_back ("reel has different assets"); + notes.push_back ("reel has different assets"); + return false; } - if (_main_subtitle) { - list m = _main_subtitle->equals (other->_main_subtitle, opt); - o.merge (m); + if (_main_subtitle && !_main_subtitle->equals (other->_main_subtitle, opt, notes)) { + return false; } - return o; + return true; } diff --git a/src/reel.h b/src/reel.h index 58caed31..08a438dd 100644 --- a/src/reel.h +++ b/src/reel.h @@ -54,7 +54,7 @@ public: void write_to_cpl (std::ostream & s) const; - std::list equals (boost::shared_ptr other, EqualityOptions opt) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; private: boost::shared_ptr _main_picture; diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 86ce69cf..9395a487 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -193,12 +193,14 @@ SoundAsset::write_to_cpl (ostream& s) const << " \n"; } -list -SoundAsset::equals (shared_ptr other, EqualityOptions opt) const +bool +SoundAsset::equals (shared_ptr other, EqualityOptions opt, list& notes) const { - list notes = MXFAsset::equals (other, opt); + if (!MXFAsset::equals (other, opt, notes)) { + return false; + } - if (opt.flags & MXF_INSPECT) { + if (!opt.bitwise) { ASDCP::PCM::MXFReader reader_A; if (ASDCP_FAILURE (reader_A.OpenRead (path().string().c_str()))) { throw MXFFileError ("could not open MXF file for reading", path().string()); @@ -232,6 +234,7 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt) const ) { notes.push_back ("audio MXF picture descriptors differ"); + return false; } ASDCP::PCM::FrameBuffer buffer_A (1 * Kumu::Megabyte); @@ -248,17 +251,17 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt) const if (buffer_A.Size() != buffer_B.Size()) { notes.push_back ("sizes of audio data for frame " + lexical_cast(i) + " differ"); - continue; + return false; } if (memcmp (buffer_A.RoData(), buffer_B.RoData(), buffer_A.Size()) != 0) { notes.push_back ("PCM data for MXF frame " + lexical_cast(i) + " differ"); - continue; + return false; } } } - return notes; + return true; } shared_ptr diff --git a/src/sound_asset.h b/src/sound_asset.h index 3f42a522..a19d6726 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -87,7 +87,7 @@ public: */ void write_to_cpl (std::ostream& s) const; - std::list equals (boost::shared_ptr other, EqualityOptions opt) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; boost::shared_ptr get_frame (int n) const; diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index d02e364c..66f75cbe 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -183,9 +183,10 @@ public: SubtitleAsset (std::string directory, std::string xml); void write_to_cpl (std::ostream&) const {} - virtual std::list equals (boost::shared_ptr, EqualityOptions) const { + virtual bool equals (boost::shared_ptr, EqualityOptions, std::list& notes) const { /* XXX */ - return std::list (); + notes.push_back ("subtitle assets not compared yet"); + return true; } std::string language () const { diff --git a/src/types.h b/src/types.h index 314b674b..7c98a3b3 100644 --- a/src/types.h +++ b/src/types.h @@ -85,15 +85,12 @@ public: extern bool operator== (Fraction const & a, Fraction const & b); extern bool operator!= (Fraction const & a, Fraction const & b); -enum EqualityFlags { - LIBDCP_METADATA = 0x1, - MXF_BITWISE = 0x2, - MXF_INSPECT = 0x4 -}; - struct EqualityOptions { - EqualityFlags flags; - bool verbose; + /** true to do a bitwise comparison. + * false to compare PCM and image data, possibly allowing + * some variation in values. + */ + bool bitwise; double max_mean_pixel_error; double max_std_dev_pixel_error; }; diff --git a/tools/dcpdiff.cc b/tools/dcpdiff.cc index 6141b8ff..c9139e7b 100644 --- a/tools/dcpdiff.cc +++ b/tools/dcpdiff.cc @@ -14,7 +14,6 @@ help (string n) cerr << "Syntax: " << n << " [OPTION] \n" << " -b, --bitwise bitwise check\n" << " -v, --version show libdcp version\n" - << " -d, --verbose be verbose\n" << " -h, --help show this help\n" << "\n" << "The s are the DCP directories to compare.\n" @@ -26,8 +25,7 @@ int main (int argc, char* argv[]) { EqualityOptions options; - options.flags = EqualityFlags (LIBDCP_METADATA | MXF_INSPECT); - options.verbose = false; + options.bitwise = false; int option_index = 0; while (1) { @@ -35,7 +33,6 @@ main (int argc, char* argv[]) { "bitwise", no_argument, 0, 'b'}, { "version", no_argument, 0, 'v'}, { "help", no_argument, 0, 'h'}, - { "verbose", no_argument, 0, 'd'}, { 0, 0, 0, 0 } }; @@ -47,7 +44,7 @@ main (int argc, char* argv[]) switch (c) { case 'b': - options.flags = EqualityFlags (options.flags | MXF_BITWISE); + options.bitwise = true; break; case 'v': cout << "dcpdiff version " << LIBDCP_VERSION << "\n"; @@ -55,9 +52,6 @@ main (int argc, char* argv[]) case 'h': help (argv[0]); exit (EXIT_SUCCESS); - case 'd': - options.verbose = true; - break; } } @@ -97,15 +91,17 @@ main (int argc, char* argv[]) options.max_mean_pixel_error = 5; options.max_std_dev_pixel_error = 5; - list notes = a->equals (*b, options); - if (notes.empty ()) { - cout << "DCPs equal\n"; - exit (EXIT_SUCCESS); - } + list notes; + bool equals = a->equals (*b, options, notes); for (list::iterator i = notes.begin(); i != notes.end(); ++i) { cout << " " << *i << "\n"; } + if (equals) { + cout << "DCPs equal\n"; + exit (EXIT_SUCCESS); + } + exit (EXIT_FAILURE); } -- 2.30.2