Inspect J2K data in MXFs.
authorCarl Hetherington <cth@carlh.net>
Tue, 31 Jul 2012 10:33:19 +0000 (11:33 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 31 Jul 2012 10:33:19 +0000 (11:33 +0100)
src/asset.cc
src/asset.h
src/picture_asset.cc
src/picture_asset.h
src/types.h
tools/dcpdiff.cc

index 4b02774c3f68e6945647c253fc8d09d85262727b..8063603a293a820bfd1b23416309095896548ab9 100644 (file)
@@ -110,12 +110,14 @@ Asset::equals (shared_ptr<const Asset> other, EqualityFlags flags) const
                if (_length != other->_length) {
                        notes.push_back ("MXF lengths differ");
                }
-               if (_digest != other->_digest) {
-                       notes.push_back ("MXF digests differ");
-               }
        }
        
        if (flags & MXF_BITWISE) {
+
+               if (_digest != other->_digest) {
+                       notes.push_back ("MXF digests differ");
+               }
+               
                if (filesystem::file_size (mxf_path()) != filesystem::file_size (other->mxf_path())) {
                        notes.push_back (mxf_path().string() + " and " + other->mxf_path().string() + " sizes differ");
                        return notes;
@@ -135,20 +137,14 @@ Asset::equals (shared_ptr<const Asset> other, EqualityFlags flags) const
                        a.read (abuffer, t);
                        b.read (bbuffer, t);
 
-                       for (int i = 0; i < t; ++i) {
-                               if (abuffer[i] != bbuffer[i]) {
-                                       notes.push_back (mxf_path().string() + " and " + other->mxf_path().string() + " content differs");
-                                       return notes;
-                               }
+                       if (memcmp (abuffer, bbuffer, t) != 0) {
+                               notes.push_back (mxf_path().string() + " and " + other->mxf_path().string() + " content differs");
+                               return notes;
                        }
 
                        n -= t;
                }
        }
 
-       if (flags & MXF_INSPECT) {
-
-       }
-
        return notes;
 }
index 4d26a4bc83fc3930ae98cf50ba15877320441d8c..e078f44bd6e8da5efec9982d8f035b19bc2e88fb 100644 (file)
@@ -66,9 +66,11 @@ public:
         */
        void write_to_assetmap (std::ostream& s) const;
 
-       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) const;
 
 protected:
+       friend class PictureAsset;
+       
        /** Fill in a ADSCP::WriteInfo struct.
         *  @param w struct to fill in.
         */
index 7ff525b96ae860a8ce0b2308175529cba38b5753..c3bf39e8c7a6d223e7ea8eb69a0a2c686badaa43 100644 (file)
@@ -26,6 +26,7 @@
 #include <iostream>
 #include <sstream>
 #include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
 #include "AS_DCP.h"
 #include "KM_fileio.h"
 #include "picture_asset.h"
@@ -140,3 +141,86 @@ PictureAsset::write_to_cpl (ostream& s) const
          << "          <ScreenAspectRatio>" << _width << " " << _height << "</ScreenAspectRatio>\n"
          << "        </MainPicture>\n";
 }
+
+list<string>
+PictureAsset::equals (shared_ptr<const Asset> other, EqualityFlags flags) const
+{
+       list<string> notes = Asset::equals (other, flags);
+                    
+       if (flags & MXF_INSPECT) {
+               ASDCP::JP2K::MXFReader reader_A;
+               if (ASDCP_FAILURE (reader_A.OpenRead (mxf_path().c_str()))) {
+                       throw FileError ("could not open MXF file for reading", mxf_path().string());
+               }
+
+               ASDCP::JP2K::MXFReader reader_B;
+               if (ASDCP_FAILURE (reader_B.OpenRead (other->mxf_path().c_str()))) {
+                       throw FileError ("could not open MXF file for reading", mxf_path().string());
+               }
+
+               ASDCP::JP2K::PictureDescriptor desc_A;
+               if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) {
+                       throw DCPReadError ("could not read video MXF information");
+               }
+               ASDCP::JP2K::PictureDescriptor desc_B;
+               if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) {
+                       throw DCPReadError ("could not read video MXF information");
+               }
+
+               if (
+                       desc_A.EditRate != desc_B.EditRate ||
+                       desc_A.ContainerDuration != desc_B.ContainerDuration ||
+                       desc_A.SampleRate != desc_B.SampleRate ||
+                       desc_A.StoredWidth != desc_B.StoredWidth ||
+                       desc_A.StoredHeight != desc_B.StoredHeight ||
+                       desc_A.AspectRatio != desc_B.AspectRatio ||
+                       desc_A.Rsize != desc_B.Rsize ||
+                       desc_A.Xsize != desc_B.Xsize ||
+                       desc_A.Ysize != desc_B.Ysize ||
+                       desc_A.XOsize != desc_B.XOsize ||
+                       desc_A.YOsize != desc_B.YOsize ||
+                       desc_A.XTsize != desc_B.XTsize ||
+                       desc_A.YTsize != desc_B.YTsize ||
+                       desc_A.XTOsize != desc_B.XTOsize ||
+                       desc_A.YTOsize != desc_B.YTOsize ||
+                       desc_A.Csize != desc_B.Csize
+//                     desc_A.CodingStyleDefault != desc_B.CodingStyleDefault ||
+//                     desc_A.QuantizationDefault != desc_B.QuantizationDefault
+                       ) {
+               
+                       notes.push_back ("video MXF picture descriptors differ");
+               }
+
+//             for (unsigned int j = 0; j < ASDCP::JP2K::MaxComponents; ++j) {
+//                     if (desc_A.ImageComponents[j] != desc_B.ImageComponents[j]) {
+//                             notes.pack_start ("video MXF picture descriptors differ");
+//                     }
+//             }
+                               
+
+               ASDCP::JP2K::FrameBuffer buffer_A (4 * Kumu::Megabyte);
+               ASDCP::JP2K::FrameBuffer buffer_B (4 * Kumu::Megabyte);
+
+               for (int i = 0; i < _length; ++i) {
+                       if (ASDCP_FAILURE (reader_A.ReadFrame (0, buffer_A))) {
+                               throw DCPReadError ("could not read video frame");
+                       }
+
+                       if (ASDCP_FAILURE (reader_B.ReadFrame (0, buffer_B))) {
+                               throw DCPReadError ("could not read video frame");
+                       }
+
+                       if (buffer_A.Size() != buffer_B.Size()) {
+                               notes.push_back ("sizes of video data for frame " + lexical_cast<string>(i) + " differ");
+                               continue;
+                       }
+
+                       if (memcmp (buffer_A.RoData(), buffer_B.RoData(), buffer_A.Size()) != 0) {
+                               notes.push_back ("J2K data for frame " + lexical_cast<string>(i) + " differ");
+                               continue;
+                       }
+               }
+       }
+
+       return notes;
+}
index 9fa4f99e894b88861288c6fdee1659025a655239..cccea0f33dfaf527f4bcc8e62809e27de04d3456 100644 (file)
@@ -81,6 +81,8 @@ public:
         */
        void write_to_cpl (std::ostream& s) const;
 
+       std::list<std::string> equals (boost::shared_ptr<const Asset> other, EqualityFlags flags) const;
+       
 private:
        std::string path_from_list (int f, std::vector<std::string> const & files) const;
        void construct (sigc::slot<std::string, int>);
index 019f93a783f2a88b3c31f99e070d9839f2580f21..ee3edaef0c29fb4e320cab891e31c22f2523422d 100644 (file)
@@ -65,7 +65,7 @@ public:
 enum EqualityFlags {
        LIBDCP_METADATA = 0x1,
        MXF_BITWISE = 0x2,
-       MXF_INSPECT
+       MXF_INSPECT = 0x4
 };
 
 }
index d1b49d05385332700c1a6c81dd9a2c8490cd3365..21b3ff47d53868a69778da299b83b5efc40b9897 100644 (file)
@@ -8,15 +8,20 @@ static void
 help (string n)
 {
        cerr << "Syntax: " << n << " [OPTION] <DCP> <DCP>\n"
-            << "  -v, --version      show DVD-o-matic version\n"
+            << "  -b, --bitwise      bitwise check\n"
+            << "  -v, --version      show libdcp version\n"
             << "  -h, --help         show this help\n"
             << "\n"
-            << "The <DCP>s are the DCP directories to compare.\n";
+            << "The <DCP>s are the DCP directories to compare.\n"
+            << "Default is to compare metadata and content ignoring timestamps\n"
+            << "and differing UUIDs.  Pass -b to perform a bitwise comparison.\n";
 }
 
 int
 main (int argc, char* argv[])
 {
+       bool bitwise = false;
+       
        int option_index = 0;
        while (1) {
                static struct option long_options[] = {
@@ -25,13 +30,16 @@ main (int argc, char* argv[])
                        { 0, 0, 0, 0 }
                };
 
-               int c = getopt_long (argc, argv, "vh", long_options, &option_index);
+               int c = getopt_long (argc, argv, "bvh", long_options, &option_index);
 
                if (c == -1) {
                        break;
                }
 
                switch (c) {
+               case 'b':
+                       bitwise = true;
+                       break;
                case 'v':
                        cout << "dcpdiff version " << LIBDCP_VERSION << "\n";
                        exit (EXIT_SUCCESS);
@@ -49,7 +57,12 @@ main (int argc, char* argv[])
        DCP a (argv[optind]);
        DCP b (argv[optind + 1]);
 
-       list<string> notes = a.equals (b, EqualityFlags (LIBDCP_METADATA | MXF_BITWISE));
+       EqualityFlags flags = EqualityFlags (LIBDCP_METADATA | MXF_INSPECT);
+       if (bitwise) {
+               flags = EqualityFlags (flags | MXF_BITWISE);
+       }
+
+       list<string> notes = a.equals (b, flags);
        if (notes.empty ()) {
                cout << "DCPs identical\n";
                exit (EXIT_SUCCESS);