Compare using maximum mean absolute difference and standard deviation.
authorCarl Hetherington <cth@carlh.net>
Wed, 1 Aug 2012 23:59:36 +0000 (00:59 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 1 Aug 2012 23:59:36 +0000 (00:59 +0100)
src/asset.cc
src/asset.h
src/dcp.cc
src/dcp.h
src/picture_asset.cc
src/picture_asset.h
src/sound_asset.cc
src/sound_asset.h
tools/dcpdiff.cc

index f8362c8b16ca61c16d18e7e8eb32b4fac6dd3854..38617e8584fc7e4c01c57c32c2622a219ff6977b 100644 (file)
@@ -96,7 +96,7 @@ Asset::mxf_path () const
 }
 
 list<string>
-Asset::equals (shared_ptr<const Asset> other, EqualityFlags flags) const
+Asset::equals (shared_ptr<const Asset> other, EqualityFlags flags, double, double) const
 {
        list<string> notes;
        
index cf161104be681706970bbeb06232a517a5179b32..51e5dc5426c7cf6db0a953bf5f91a9048a31c2cd 100644 (file)
@@ -66,7 +66,7 @@ public:
         */
        void write_to_assetmap (std::ostream& s) const;
 
-       virtual std::list<std::string> equals (boost::shared_ptr<const Asset> other, EqualityFlags flags) const;
+       virtual std::list<std::string> equals (boost::shared_ptr<const Asset> other, EqualityFlags flags, double max_mean, double max_std_dev) const;
 
 protected:
        friend class PictureAsset;
index 322859e7288d1a6f6c2d5c354e5c77f06119c157..cf37579f716382d916857199249e97da053197f8 100644 (file)
@@ -334,7 +334,7 @@ DCP::DCP (string directory)
 }
 
 list<string>
-DCP::equals (DCP const & other, EqualityFlags flags) const
+DCP::equals (DCP const & other, EqualityFlags flags, double max_mean, double max_std_dev) const
 {
        list<string> notes;
        
@@ -361,7 +361,7 @@ DCP::equals (DCP const & other, EqualityFlags flags) const
        list<shared_ptr<Asset> >::const_iterator b = other._assets.begin ();
        
        while (a != _assets.end ()) {
-               list<string> n = (*a)->equals (*b, flags);
+               list<string> n = (*a)->equals (*b, flags, max_mean, max_std_dev);
                notes.merge (n);
                ++a;
                ++b;
index bc829fe96d1e69be5a837fc2ccdf8060b9edb95e..1ad56efc1a9a0a89217d787a0d925ee16611b4ae 100644 (file)
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -106,7 +106,7 @@ public:
                return _length;
        }
 
-       std::list<std::string> equals (DCP const & other, EqualityFlags flags) const;
+       std::list<std::string> equals (DCP const & other, EqualityFlags flags, double max_mean, double max_std_dev) const;
 
        /** Emitted with a parameter between 0 and 1 to indicate progress
         *  for long jobs.
index 969a5523f0872c0e83a25a90a243f2eca17360eb..3386d6d40c414fc473a4afb6c5b117ce15c37c94 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdexcept>
 #include <iostream>
 #include <sstream>
+#include <fstream>
 #include <boost/filesystem.hpp>
 #include <boost/lexical_cast.hpp>
 #include <openjpeg.h>
@@ -142,9 +143,9 @@ PictureAsset::write_to_cpl (ostream& s) const
 }
 
 list<string>
-PictureAsset::equals (shared_ptr<const Asset> other, EqualityFlags flags) const
+PictureAsset::equals (shared_ptr<const Asset> other, EqualityFlags flags, double max_mean, double max_std_dev) const
 {
-       list<string> notes = Asset::equals (other, flags);
+       list<string> notes = Asset::equals (other, flags, max_mean, max_std_dev);
                     
        if (flags & MXF_INSPECT) {
                ASDCP::JP2K::MXFReader reader_A;
@@ -214,13 +215,9 @@ PictureAsset::equals (shared_ptr<const Asset> other, EqualityFlags flags) const
                        if (buffer_A.Size() != buffer_B.Size()) {
                                notes.push_back ("sizes of video data for frame " + lexical_cast<string>(i) + " differ");
                                j2k_same = false;
-                               continue;
-                       }
-
-                       if (memcmp (buffer_A.RoData(), buffer_B.RoData(), buffer_A.Size()) != 0) {
+                       } else if (memcmp (buffer_A.RoData(), buffer_B.RoData(), buffer_A.Size()) != 0) {
                                notes.push_back ("J2K data for frame " + lexical_cast<string>(i) + " differ");
                                j2k_same = false;
-                               continue;
                        }
 
                        if (!j2k_same) {
@@ -234,21 +231,38 @@ PictureAsset::equals (shared_ptr<const Asset> other, EqualityFlags flags) const
                                        notes.push_back ("image component counts for frame " + lexical_cast<string>(i) + " differ");
                                }
 
+                               vector<int> abs_diffs (image_A->comps[0].w * image_A->comps[0].h * image_A->numcomps);
+                               int d = 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<string>(i) + " differ");
                                        }
-                                       
-                                       cout << "comp " << c << " of " << image_A->numcomps << "\n";
-                                       cout << "bpp " << image_A->comps[c].bpp << "\n";
-                                       
-                                       for (int x = 0; x < image_A->comps[c].w; ++x) {
-                                               for (int y = 0; y < image_A->comps[c].h; ++y) {
-                                                               
-                                               }
+
+                                       int const pixels = image_A->comps[c].w * image_A->comps[c].h;
+                                       for (int j = 0; j < pixels; ++j) {
+                                               abs_diffs[d++] = abs (image_A->comps[c].data[j] - image_B->comps[c].data[j]);
                                        }
                                }
-                               
+
+                               uint64_t total = 0;
+                               for (vector<int>::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<int>::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 > max_mean || std_dev > max_std_dev) {
+                                       notes.push_back ("mean or standard deviation out of range for " + lexical_cast<string>(i));
+                               }
 
                                opj_image_destroy (image_A);
                                opj_image_destroy (image_B);
index 3980794a13f741d8168c494d063efc6b3512aa85..8a697f2cd3ca13ca6b579a02ee3933dcf67e720d 100644 (file)
@@ -82,7 +82,7 @@ public:
         */
        void write_to_cpl (std::ostream& s) const;
 
-       std::list<std::string> equals (boost::shared_ptr<const Asset> other, EqualityFlags flags) const;
+       std::list<std::string> equals (boost::shared_ptr<const Asset> other, EqualityFlags flags, double max_mean, double max_std_dev) const;
        
 private:
        std::string path_from_list (int f, std::vector<std::string> const & files) const;
index ed815eda96549c45cc3cb6672c79e6659f538ab2..2d8349579ccdacc171fab4cf176a5d79d5326832 100644 (file)
@@ -177,9 +177,9 @@ SoundAsset::write_to_cpl (ostream& s) const
 }
 
 list<string>
-SoundAsset::equals (shared_ptr<const Asset> other, EqualityFlags flags) const
+SoundAsset::equals (shared_ptr<const Asset> other, EqualityFlags flags, double max_mean, double max_std_dev) const
 {
-       list<string> notes = Asset::equals (other, flags);
+       list<string> notes = Asset::equals (other, flags, max_mean, max_std_dev);
                     
        if (flags & MXF_INSPECT) {
                ASDCP::PCM::MXFReader reader_A;
index 2d797998cb0e7f830da7cb11dbcc1639f9c736a3..4b7c0967b85a6655b74e3ec1da2d9df900fe19cf 100644 (file)
@@ -84,7 +84,7 @@ public:
         */
        void write_to_cpl (std::ostream& s) const;
 
-       std::list<std::string> equals (boost::shared_ptr<const Asset> other, EqualityFlags flags) const;
+       std::list<std::string> equals (boost::shared_ptr<const Asset> other, EqualityFlags flags, double max_mean, double max_std_dev) const;
        
 private:
        void construct (sigc::slot<std::string, Channel> get_path);
index 9d4243331a215a638f5ed3ef4e0e6507ea584423..73097ccdd698f2890932f504b8834034b3cca953 100644 (file)
@@ -90,7 +90,7 @@ main (int argc, char* argv[])
                flags = EqualityFlags (flags | MXF_BITWISE);
        }
 
-       list<string> notes = a->equals (*b, flags);
+       list<string> notes = a->equals (*b, flags, 5, 5);
        if (notes.empty ()) {
                cout << "DCPs identical\n";
                exit (EXIT_SUCCESS);