+
+static
+shared_ptr<dcp::OpenJPEGImage>
+black_image ()
+{
+ shared_ptr<dcp::OpenJPEGImage> image(new dcp::OpenJPEGImage(dcp::Size(1998, 1080)));
+ int const pixels = 1998 * 1080;
+ for (int i = 0; i < 3; ++i) {
+ memset (image->data(i), 0, pixels * sizeof(int));
+ }
+ return image;
+}
+
+
+static
+void
+dcp_from_frame (dcp::Data const& frame, boost::filesystem::path dir)
+{
+ shared_ptr<dcp::MonoPictureAsset> asset(new dcp::MonoPictureAsset(dcp::Fraction(24, 1), dcp::SMPTE));
+ boost::filesystem::create_directories (dir);
+ shared_ptr<dcp::PictureAssetWriter> writer = asset->start_write (dir / "pic.mxf", true);
+ for (int i = 0; i < 24; ++i) {
+ writer->write (frame.data().get(), frame.size());
+ }
+ writer->finalize ();
+
+ shared_ptr<dcp::ReelAsset> reel_asset(new dcp::ReelMonoPictureAsset(asset, 0));
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (reel_asset);
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+ dcp->add (cpl);
+ dcp->write_xml (dcp::SMPTE);
+}
+
+
+/* DCP with an over-sized JPEG2000 frame */
+BOOST_AUTO_TEST_CASE (verify_test15)
+{
+ int const too_big = 1302083 * 2;
+
+ /* Compress a black image */
+ shared_ptr<dcp::OpenJPEGImage> image = black_image ();
+ dcp::Data frame = dcp::compress_j2k (image, 100000000, 24, false, false);
+ BOOST_REQUIRE (frame.size() < too_big);
+
+ /* Place it in a bigger block with some zero padding at the end */
+ dcp::Data oversized_frame(too_big);
+ memcpy (oversized_frame.data().get(), frame.data().get(), frame.size());
+ memset (oversized_frame.data().get() + frame.size(), 0, too_big - frame.size());
+
+ boost::filesystem::path const dir("build/test/verify_test15");
+ boost::filesystem::remove_all (dir);
+ dcp_from_frame (oversized_frame, dir);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
+ BOOST_REQUIRE_EQUAL (notes.size(), 1);
+ BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::PICTURE_FRAME_TOO_LARGE);
+}
+
+
+/* DCP with a nearly over-sized JPEG2000 frame */
+BOOST_AUTO_TEST_CASE (verify_test16)
+{
+ int const nearly_too_big = 1302083 * 0.98;
+
+ /* Compress a black image */
+ shared_ptr<dcp::OpenJPEGImage> image = black_image ();
+ dcp::Data frame = dcp::compress_j2k (image, 100000000, 24, false, false);
+ BOOST_REQUIRE (frame.size() < nearly_too_big);
+
+ /* Place it in a bigger block with some zero padding at the end */
+ dcp::Data oversized_frame(nearly_too_big);
+ memcpy (oversized_frame.data().get(), frame.data().get(), frame.size());
+ memset (oversized_frame.data().get() + frame.size(), 0, nearly_too_big - frame.size());
+
+ boost::filesystem::path const dir("build/test/verify_test16");
+ boost::filesystem::remove_all (dir);
+ dcp_from_frame (oversized_frame, dir);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
+ BOOST_REQUIRE_EQUAL (notes.size(), 1);
+ BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::PICTURE_FRAME_NEARLY_TOO_LARGE);
+}
+
+
+/* DCP with a within-range JPEG2000 frame */
+BOOST_AUTO_TEST_CASE (verify_test17)
+{
+ /* Compress a black image */
+ shared_ptr<dcp::OpenJPEGImage> image = black_image ();
+ dcp::Data frame = dcp::compress_j2k (image, 100000000, 24, false, false);
+ BOOST_REQUIRE (frame.size() < 230000000 / (24 * 8));
+
+ boost::filesystem::path const dir("build/test/verify_test17");
+ boost::filesystem::remove_all (dir);
+ dcp_from_frame (frame, dir);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
+ BOOST_REQUIRE_EQUAL (notes.size(), 0);
+}
+
+
+/* DCP with valid Interop subtitles */
+BOOST_AUTO_TEST_CASE (verify_test18)
+{
+ boost::filesystem::path const dir("build/test/verify_test18");
+ boost::filesystem::remove_all (dir);
+ boost::filesystem::create_directories (dir);
+ boost::filesystem::copy_file ("test/data/subs1.xml", dir / "subs.xml");
+ shared_ptr<dcp::InteropSubtitleAsset> asset(new dcp::InteropSubtitleAsset(dir / "subs.xml"));
+ shared_ptr<dcp::ReelAsset> reel_asset(new dcp::ReelSubtitleAsset(asset, dcp::Fraction(24, 1), 16 * 24, 0));
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (reel_asset);
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+ dcp->add (cpl);
+ dcp->write_xml (dcp::INTEROP);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
+ BOOST_REQUIRE_EQUAL (notes.size(), 0);
+}
+
+
+/* DCP with broken Interop subtitles */
+BOOST_AUTO_TEST_CASE (verify_test19)
+{
+ boost::filesystem::path const dir("build/test/verify_test19");
+ boost::filesystem::remove_all (dir);
+ boost::filesystem::create_directories (dir);
+ boost::filesystem::copy_file ("test/data/subs1.xml", dir / "subs.xml");
+ shared_ptr<dcp::InteropSubtitleAsset> asset(new dcp::InteropSubtitleAsset(dir / "subs.xml"));
+ shared_ptr<dcp::ReelAsset> reel_asset(new dcp::ReelSubtitleAsset(asset, dcp::Fraction(24, 1), 16 * 24, 0));
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (reel_asset);
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+ dcp->add (cpl);
+ dcp->write_xml (dcp::INTEROP);
+
+ {
+ Editor e (dir / "subs.xml");
+ e.replace ("</ReelNumber>", "</ReelNumber><Foo></Foo>");
+ }
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
+ dump_notes(notes);
+ BOOST_REQUIRE_EQUAL (notes.size(), 2);
+ BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::XML_VALIDATION_ERROR);
+ BOOST_CHECK_EQUAL (notes.back().code(), dcp::VerificationNote::XML_VALIDATION_ERROR);
+}
+
+
+/* DCP with valid SMPTE subtitles */
+BOOST_AUTO_TEST_CASE (verify_test20)
+{
+ boost::filesystem::path const dir("build/test/verify_test20");
+ boost::filesystem::remove_all (dir);
+ boost::filesystem::create_directories (dir);
+ boost::filesystem::copy_file ("test/data/subs.mxf", dir / "subs.mxf");
+ shared_ptr<dcp::SMPTESubtitleAsset> asset(new dcp::SMPTESubtitleAsset(dir / "subs.mxf"));
+ shared_ptr<dcp::ReelAsset> reel_asset(new dcp::ReelSubtitleAsset(asset, dcp::Fraction(24, 1), 16 * 24, 0));
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (reel_asset);
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+ dcp->add (cpl);
+ dcp->write_xml (dcp::SMPTE);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
+ dump_notes (notes);
+ BOOST_REQUIRE_EQUAL (notes.size(), 0);
+}
+
+
+/* DCP with broken SMPTE subtitles */
+BOOST_AUTO_TEST_CASE (verify_test21)
+{
+ boost::filesystem::path const dir("build/test/verify_test21");
+ boost::filesystem::remove_all (dir);
+ boost::filesystem::create_directories (dir);
+ boost::filesystem::copy_file ("test/data/broken_smpte.mxf", dir / "subs.mxf");
+ shared_ptr<dcp::SMPTESubtitleAsset> asset(new dcp::SMPTESubtitleAsset(dir / "subs.mxf"));
+ shared_ptr<dcp::ReelAsset> reel_asset(new dcp::ReelSubtitleAsset(asset, dcp::Fraction(24, 1), 16 * 24, 0));
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (reel_asset);
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+ dcp->add (cpl);
+ dcp->write_xml (dcp::SMPTE);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
+ dump_notes (notes);
+ BOOST_REQUIRE_EQUAL (notes.size(), 2);
+ BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::XML_VALIDATION_ERROR);
+ BOOST_CHECK_EQUAL (notes.back().code(), dcp::VerificationNote::XML_VALIDATION_ERROR);
+}
+
+
+/* VF */
+BOOST_AUTO_TEST_CASE (verify_test22)
+{
+ boost::filesystem::path const ov_dir("build/test/verify_test22_ov");
+ boost::filesystem::remove_all (ov_dir);
+ boost::filesystem::create_directories (ov_dir);
+
+ shared_ptr<dcp::OpenJPEGImage> image = black_image ();
+ dcp::Data frame = dcp::compress_j2k (image, 100000000, 24, false, false);
+ BOOST_REQUIRE (frame.size() < 230000000 / (24 * 8));
+ dcp_from_frame (frame, ov_dir);
+
+ dcp::DCP ov (ov_dir);
+ ov.read ();
+
+ boost::filesystem::path const vf_dir("build/test/verify_test22_vf");
+ boost::filesystem::remove_all (vf_dir);
+ boost::filesystem::create_directories (vf_dir);
+
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (ov.cpls().front()->reels().front()->main_picture());
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ dcp::DCP vf (vf_dir);
+ vf.add (cpl);
+ vf.write_xml (dcp::SMPTE);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (vf_dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, xsd_test);
+ dump_notes (notes);
+ BOOST_REQUIRE_EQUAL (notes.size(), 1);
+ BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::EXTERNAL_ASSET);
+}
+
+