Add operator!= and operator< for LanguageTag
[libdcp.git] / test / verify_test.cc
index a9d5c0a72711e4e443e4658aab8af488e1aa4ff3..80e985e59b03bf93a9635413848ce231abe4bd0c 100644 (file)
     files in the program, then also delete it here.
 */
 
-#include "verify.h"
-#include "util.h"
-#include "j2k.h"
-#include "reel.h"
-#include "reel_mono_picture_asset.h"
-#include "reel_sound_asset.h"
+#include "compose.hpp"
 #include "cpl.h"
 #include "dcp.h"
-#include "openjpeg_image.h"
+#include "interop_subtitle_asset.h"
+#include "j2k_transcode.h"
 #include "mono_picture_asset.h"
-#include "stereo_picture_asset.h"
 #include "mono_picture_asset_writer.h"
-#include "interop_subtitle_asset.h"
-#include "smpte_subtitle_asset.h"
+#include "openjpeg_image.h"
+#include "raw_convert.h"
+#include "reel.h"
 #include "reel_closed_caption_asset.h"
+#include "reel_markers_asset.h"
+#include "reel_mono_picture_asset.h"
+#include "reel_sound_asset.h"
 #include "reel_stereo_picture_asset.h"
 #include "reel_subtitle_asset.h"
-#include "reel_markers_asset.h"
-#include "compose.hpp"
-#include "test.h"
-#include "raw_convert.h"
+#include "smpte_subtitle_asset.h"
+#include "stereo_picture_asset.h"
 #include "stream_operators.h"
+#include "test.h"
+#include "util.h"
+#include "verify.h"
+#include "verify_j2k.h"
 #include <boost/test/unit_test.hpp>
-#include <boost/foreach.hpp>
 #include <boost/algorithm/string.hpp>
 #include <cstdio>
 #include <iostream>
@@ -202,6 +202,7 @@ void
 check_verify_result (vector<path> dir, vector<dcp::VerificationNote> test_notes)
 {
        auto notes = dcp::verify ({dir}, &stage, &progress, xsd_test);
+       dump_notes (notes);
        BOOST_REQUIRE_EQUAL (notes.size(), test_notes.size());
        for (auto i = 0U; i < notes.size(); ++i) {
                BOOST_REQUIRE_EQUAL (notes[i], test_notes[i]);
@@ -333,8 +334,8 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_picture_sound_hashes)
                        { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, dcp_test1_cpl_id, canonical(dir / dcp_test1_cpl) },
                        { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_PICTURE_HASHES, canonical(dir / "video.mxf") },
                        { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_SOUND_HASHES, canonical(dir / "audio.mxf") },
-                       { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xxz+gUPoPMdbFlAewvWIq8BRhBmA=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 12 },
-                       { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xXGhFVrqZqapOJx5Fh2SLjj48Yjg=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 19 },
+                       { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xX3bMCBdXEOYEpYmsConNWrWUAGs=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 12 },
+                       { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xaddO7je2lZSNQp55qjCWo5DLKFQ=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 19 },
                        { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xqtXbkcwhUj/yqquVLmV+wbzbxQ8=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 26 }
                });
 }
@@ -677,7 +678,7 @@ BOOST_AUTO_TEST_CASE (verify_valid_smpte_subtitles)
        prepare_directory (dir);
        copy_file ("test/data/subs.mxf", dir / "subs.mxf");
        auto asset = make_shared<dcp::SMPTESubtitleAsset>(dir / "subs.mxf");
-       auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
+       auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(25, 1), 300 * 24, 0);
        auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
        check_verify_result ({dir}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
@@ -692,7 +693,7 @@ BOOST_AUTO_TEST_CASE (verify_invalid_smpte_subtitles)
        prepare_directory (dir);
        copy_file ("test/data/broken_smpte.mxf", dir / "subs.mxf");
        auto asset = make_shared<dcp::SMPTESubtitleAsset>(dir / "subs.mxf");
-       auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
+       auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(24, 1), 300 * 24, 0);
        auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
        check_verify_result (
@@ -890,7 +891,7 @@ BOOST_AUTO_TEST_CASE (verify_invalid_language1)
        auto asset = make_shared<dcp::SMPTESubtitleAsset>(dir / "subs.mxf");
        asset->_language = "wrong-andbad";
        asset->write (dir / "subs.mxf");
-       auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
+       auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(24, 1), 300 * 24, 0);
        reel_asset->_language = "badlang";
        auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
@@ -913,7 +914,7 @@ BOOST_AUTO_TEST_CASE (verify_invalid_language2)
        auto asset = make_shared<dcp::SMPTESubtitleAsset>(dir / "subs.mxf");
        asset->_language = "wrong-andbad";
        asset->write (dir / "subs.mxf");
-       auto reel_asset = make_shared<dcp::ReelClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
+       auto reel_asset = make_shared<dcp::ReelClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 300 * 24, 0);
        reel_asset->_language = "badlang";
        auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
@@ -1168,7 +1169,7 @@ BOOST_AUTO_TEST_CASE (verify_invalid_closed_caption_xml_size_in_bytes)
        }
        asset->set_language (dcp::LanguageTag("de-DE"));
        asset->write (dir / "subs.mxf");
-       auto reel_asset = make_shared<dcp::ReelClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
+       auto reel_asset = make_shared<dcp::ReelClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 2049 * 24, 0);
        auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
        check_verify_result (
@@ -1323,7 +1324,48 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_subtitle_languages)
                { path },
                {
                        { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs1.mxf") },
-                       { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_SUBTITLE_LANGUAGES },
+                       { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs2.mxf") },
+                       { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_SUBTITLE_LANGUAGES }
+               });
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_multiple_closed_caption_languages_allowed)
+{
+       path path ("build/test/verify_multiple_closed_caption_languages_allowed");
+       auto dcp = make_simple (path, 2, 240);
+       auto cpl = dcp->cpls()[0];
+
+       {
+               auto ccaps = make_shared<dcp::SMPTESubtitleAsset>();
+               ccaps->set_language (dcp::LanguageTag("de-DE"));
+               ccaps->add (simple_subtitle());
+               ccaps->write (path / "subs1.mxf");
+               auto reel_ccaps = make_shared<dcp::ReelClosedCaptionAsset>(ccaps, dcp::Fraction(24, 1), 240, 0);
+               cpl->reels()[0]->add(reel_ccaps);
+       }
+
+       {
+               auto ccaps = make_shared<dcp::SMPTESubtitleAsset>();
+               ccaps->set_language (dcp::LanguageTag("en-US"));
+               ccaps->add (simple_subtitle());
+               ccaps->write (path / "subs2.mxf");
+               auto reel_ccaps = make_shared<dcp::ReelClosedCaptionAsset>(ccaps, dcp::Fraction(24, 1), 240, 0);
+               cpl->reels()[1]->add(reel_ccaps);
+       }
+
+       dcp->write_xml (
+               dcp::Standard::SMPTE,
+               dcp::String::compose("libdcp %1", dcp::version),
+               dcp::String::compose("libdcp %1", dcp::version),
+               dcp::LocalTime().as_string(),
+               "A Test DCP"
+               );
+
+       check_verify_result (
+               { path },
+               {
+                       { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs1.mxf") },
                        { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs2.mxf") }
                });
 }
@@ -1596,6 +1638,29 @@ BOOST_AUTO_TEST_CASE (verify_valid_subtitle_duration)
 }
 
 
+BOOST_AUTO_TEST_CASE (verify_subtitle_overlapping_reel_boundary)
+{
+       auto const dir = path("build/test/verify_subtitle_overlapping_reel_boundary");
+       prepare_directory (dir);
+       auto asset = make_shared<dcp::SMPTESubtitleAsset>();
+       asset->set_start_time (dcp::Time());
+       add_test_subtitle (asset, 0, 4 * 24);
+       asset->set_language (dcp::LanguageTag("de-DE"));
+       asset->write (dir / "subs.mxf");
+
+       auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(24, 1), 3 * 24, 0);
+       auto cpl = write_dcp_with_single_asset (dir, reel_asset);
+       check_verify_result (
+               {dir},
+               {
+                       { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
+                       { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::SUBTITLE_OVERLAPS_REEL_BOUNDARY },
+                       { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+               });
+
+}
+
+
 BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_line_count1)
 {
        auto const dir = path ("build/test/invalid_subtitle_line_count1");
@@ -2188,7 +2253,7 @@ BOOST_AUTO_TEST_CASE (verify_missing_hash)
        {
                BOOST_REQUIRE (cpl->file());
                Editor e(cpl->file().get());
-               e.replace("<Hash>XGhFVrqZqapOJx5Fh2SLjj48Yjg=</Hash>", "");
+               e.replace("<Hash>addO7je2lZSNQp55qjCWo5DLKFQ=</Hash>", "");
        }
 
        check_verify_result (
@@ -2729,3 +2794,40 @@ BOOST_AUTO_TEST_CASE (verify_partially_encrypted)
        check_verify_result ({dir}, {{dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::PARTIALLY_ENCRYPTED}});
 }
 
+
+BOOST_AUTO_TEST_CASE (verify_jpeg2000_codestream_2k)
+{
+       vector<dcp::VerificationNote> notes;
+       dcp::MonoPictureAsset picture (find_file(private_test / "data" / "JourneyToJah_TLR-1_F_EN-DE-FR_CH_51_2K_LOK_20140225_DGL_SMPTE_OV", "j2c.mxf"));
+       auto reader = picture.start_read ();
+       auto frame = reader->get_frame (0);
+       verify_j2k (frame, notes);
+       dump_notes (notes);
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_jpeg2000_codestream_4k)
+{
+       vector<dcp::VerificationNote> notes;
+       dcp::MonoPictureAsset picture (find_file(private_test / "data" / "sul", "TLR"));
+       auto reader = picture.start_read ();
+       auto frame = reader->get_frame (0);
+       verify_j2k (frame, notes);
+       dump_notes (notes);
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_jpeg2000_codestream_libdcp)
+{
+       boost::filesystem::path dir = "build/test/verify_jpeg2000_codestream_libdcp";
+       prepare_directory (dir);
+       auto dcp = make_simple (dir);
+       dcp->write_xml (dcp::Standard::SMPTE);
+       vector<dcp::VerificationNote> notes;
+       dcp::MonoPictureAsset picture (find_file(dir, "video"));
+       auto reader = picture.start_read ();
+       auto frame = reader->get_frame (0);
+       verify_j2k (frame, notes);
+       dump_notes (notes);
+}
+