#include "openjpeg_image.h"
#include "raw_convert.h"
#include "reel.h"
-#include "reel_closed_caption_asset.h"
+#include "reel_interop_closed_caption_asset.h"
#include "reel_interop_subtitle_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_smpte_closed_caption_asset.h"
#include "reel_smpte_subtitle_asset.h"
#include "smpte_subtitle_asset.h"
#include "stereo_picture_asset.h"
#include <cstdio>
#include <iostream>
+
using std::list;
using std::pair;
using std::string;
static list<pair<string, optional<path>>> stages;
-static string const dcp_test1_pkl_id = "6af1e0c1-c441-47f8-a502-3efd46b1fa4f";
-static string const dcp_test1_pkl = "pkl_" + dcp_test1_pkl_id + ".xml";
-static string const dcp_test1_cpl_id = "81fb54df-e1bf-4647-8788-ea7ba154375b";
-static string const dcp_test1_cpl = "cpl_" + dcp_test1_cpl_id + ".xml";
+
+static string filename_to_id(boost::filesystem::path path)
+{
+ return path.string().substr(4, path.string().length() - 8);
+}
+
+static boost::filesystem::path const dcp_test1_pkl = find_file("test/ref/DCP/dcp_test1", "pkl_").filename();
+static string const dcp_test1_pkl_id = filename_to_id(dcp_test1_pkl);
+
+static boost::filesystem::path const dcp_test1_cpl = find_file("test/ref/DCP/dcp_test1", "cpl_").filename();
+static string const dcp_test1_cpl_id = filename_to_id(dcp_test1_cpl);
+
static string const dcp_test1_asset_map_id = "5d51e8a1-b2a5-4da6-9b66-4615c3609440";
-static string const encryption_test_cpl_id = "81fb54df-e1bf-4647-8788-ea7ba154375b";
-static string const encryption_test_pkl_id = "627ad740-ae36-4c49-92bb-553a9f09c4f8";
+
+static boost::filesystem::path const encryption_test_cpl = find_file("test/ref/DCP/encryption_test", "cpl_").filename();
+static string const encryption_test_cpl_id = filename_to_id(encryption_test_cpl);
+
+static boost::filesystem::path const encryption_test_pkl = find_file("test/ref/DCP/encryption_test", "pkl_").filename();
+static string const encryption_test_pkl_id = filename_to_id(encryption_test_pkl);
static void
stage (string s, optional<path> p)
BOOST_REQUIRE (_content != old_content);
}
+ void delete_first_line_containing (string s)
+ {
+ vector<string> lines;
+ boost::algorithm::split (lines, _content, boost::is_any_of("\r\n"), boost::token_compress_on);
+ auto old_content = _content;
+ _content = "";
+ bool done = false;
+ for (auto i: lines) {
+ if (i.find(s) == string::npos || done) {
+ _content += i + "\n";
+ } else {
+ done = true;
+ }
+ }
+ BOOST_REQUIRE (_content != old_content);
+ }
+
void delete_lines (string from, string to)
{
vector<string> lines;
};
-#if 0
+LIBDCP_DISABLE_WARNINGS
static
void
dump_notes (vector<dcp::VerificationNote> const & notes)
std::cout << dcp::note_to_string(i) << "\n";
}
}
-#endif
+LIBDCP_ENABLE_WARNINGS
static
check_verify_result (vector<path> dir, vector<dcp::VerificationNote> test_notes)
{
auto notes = dcp::verify ({dir}, &stage, &progress, xsd_test);
- BOOST_REQUIRE_EQUAL (notes.size(), test_notes.size());
- for (auto i = 0U; i < notes.size(); ++i) {
- BOOST_REQUIRE_EQUAL (notes[i], test_notes[i]);
+ std::sort (notes.begin(), notes.end());
+ std::sort (test_notes.begin(), test_notes.end());
+
+ string message = "\nVerification notes from test:\n";
+ for (auto i: notes) {
+ message += " " + note_to_string(i) + "\n";
+ }
+ message += "Expected:\n";
+ for (auto i: test_notes) {
+ message += " " + note_to_string(i) + "\n";
}
+
+ BOOST_REQUIRE_MESSAGE (notes == test_notes, message);
}
{ 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 'xSEEi70vx1WQs67bmu2zKvzIkXvY=' 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 'xWU0/u1wM17y7Kriq06+65/ViX1o=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 26 }
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xLq7ot/GobgrqUYdlbR8FCD5APqs=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 26 },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xgVKhC9IkWyzQbgzpFcJ1bpqbtwk=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 19 },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xc1DRq6GaSzV2brF0YnSNed46nqk=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 12 }
});
}
path const dir("build/test/verify_invalid_smpte_subtitles");
prepare_directory (dir);
+ /* This broken_smpte.mxf does not use urn:uuid: for its subtitle ID, which we tolerate (rightly or wrongly) */
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::ReelSMPTESubtitleAsset>(asset, dcp::Fraction(24, 1), 6046, 0);
}
+BOOST_AUTO_TEST_CASE (verify_empty_text_node_in_subtitles)
+{
+ path const dir("build/test/verify_empty_text_node_in_subtitles");
+ prepare_directory (dir);
+ copy_file ("test/data/empty_text.mxf", dir / "subs.mxf");
+ auto asset = make_shared<dcp::SMPTESubtitleAsset>(dir / "subs.mxf");
+ auto reel_asset = make_shared<dcp::ReelSMPTESubtitleAsset>(asset, dcp::Fraction(24, 1), 192, 0);
+ auto cpl = write_dcp_with_single_asset (dir, reel_asset);
+
+ check_verify_result (
+ { dir },
+ {
+ { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_TEXT },
+ { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, canonical(dir / "subs.mxf") },
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ });
+}
+
+
+/** A <Text> node with no content except some <Font> nodes, which themselves do have content */
+BOOST_AUTO_TEST_CASE (verify_empty_text_node_in_subtitles_with_child_nodes)
+{
+ path const dir("build/test/verify_empty_text_node_in_subtitles_with_child_nodes");
+ prepare_directory (dir);
+ copy_file ("test/data/empty_but_with_children.xml", dir / "subs.xml");
+ auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "subs.xml");
+ auto reel_asset = make_shared<dcp::ReelInteropSubtitleAsset>(asset, dcp::Fraction(24, 1), 192, 0);
+ auto cpl = write_dcp_with_single_asset (dir, reel_asset, dcp::Standard::INTEROP);
+
+ check_verify_result (
+ { dir },
+ {
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
+ });
+}
+
+
+/** A <Text> node with no content except some <Font> nodes, which themselves also have no content */
+BOOST_AUTO_TEST_CASE (verify_empty_text_node_in_subtitles_with_empty_child_nodes)
+{
+ path const dir("build/test/verify_empty_text_node_in_subtitles_with_empty_child_nodes");
+ prepare_directory (dir);
+ copy_file ("test/data/empty_with_empty_children.xml", dir / "subs.xml");
+ auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "subs.xml");
+ auto reel_asset = make_shared<dcp::ReelInteropSubtitleAsset>(asset, dcp::Fraction(24, 1), 192, 0);
+ auto cpl = write_dcp_with_single_asset (dir, reel_asset, dcp::Standard::INTEROP);
+
+ check_verify_result (
+ { dir },
+ {
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
+ { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_TEXT },
+ });
+}
+
+
BOOST_AUTO_TEST_CASE (verify_external_asset)
{
path const ov_dir("build/test/verify_external_asset");
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), 6046, 0);
+ auto reel_asset = make_shared<dcp::ReelSMPTEClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 6046, 0);
reel_asset->_language = "badlang";
auto cpl = write_dcp_with_single_asset (dir, reel_asset);
static
void
-add_test_subtitle (shared_ptr<dcp::SubtitleAsset> asset, int start_frame, int end_frame, float v_position = 0, string text = "Hello")
+add_test_subtitle (shared_ptr<dcp::SubtitleAsset> asset, int start_frame, int end_frame, float v_position = 0, dcp::VAlign v_align = dcp::VAlign::CENTER, string text = "Hello")
{
asset->add (
make_shared<dcp::SubtitleString>(
0,
dcp::HAlign::CENTER,
v_position,
- dcp::VAlign::CENTER,
+ v_align,
dcp::Direction::LTR,
text,
dcp::Effect::NONE,
dcp::Colour(),
dcp::Time(),
- dcp::Time()
+ dcp::Time(),
+ 0
)
);
}
}
asset->set_language (dcp::LanguageTag("de-DE"));
asset->write (dir / "subs.mxf");
- auto reel_asset = make_shared<dcp::ReelClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 49148, 0);
+ auto reel_asset = make_shared<dcp::ReelSMPTEClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 49148, 0);
auto cpl = write_dcp_with_single_asset (dir, reel_asset);
check_verify_result (
{
dcp::VerificationNote::Type::BV21_ERROR,
dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES,
- string("413262"),
+ string("372207"),
canonical(dir / "subs.mxf")
},
{ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
check_verify_result (
{ dir },
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121696411"), canonical(dir / "subs.mxf") },
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121695136"), canonical(dir / "subs.mxf") },
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, string("121634816"), canonical(dir / "subs.mxf") },
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
{ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
BOOST_AUTO_TEST_CASE (verify_subtitle_asset_too_large)
{
verify_timed_text_asset_too_large<dcp::ReelSMPTESubtitleAsset>("verify_subtitle_asset_too_large");
- verify_timed_text_asset_too_large<dcp::ReelClosedCaptionAsset>("verify_closed_caption_asset_too_large");
+ verify_timed_text_asset_too_large<dcp::ReelSMPTEClosedCaptionAsset>("verify_closed_caption_asset_too_large");
}
subs->write (dir / "subs.mxf");
auto reel_subs = make_shared<dcp::ReelSMPTESubtitleAsset>(subs, dcp::Fraction(24, 1), 106, 0);
- dcp->cpls().front()->reels().front()->add(reel_subs);
+ dcp->cpls()[0]->reels()[0]->add(reel_subs);
dcp->write_xml (
dcp::String::compose("libdcp %1", dcp::version),
dcp::String::compose("libdcp %1", dcp::version),
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), reel_length, 0);
+ auto reel_ccaps = make_shared<dcp::ReelSMPTEClosedCaptionAsset>(ccaps, dcp::Fraction(24, 1), reel_length, 0);
cpl->reels()[0]->add(reel_ccaps);
}
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), reel_length, 0);
+ auto reel_ccaps = make_shared<dcp::ReelSMPTEClosedCaptionAsset>(ccaps, dcp::Fraction(24, 1), reel_length, 0);
cpl->reels()[1]->add(reel_ccaps);
}
subs->write (dir / "subs.mxf");
auto reel_subs = make_shared<dcp::ReelSMPTESubtitleAsset>(subs, dcp::Fraction(24, 1), 106, 0);
- dcp->cpls().front()->reels().front()->add(reel_subs);
+ dcp->cpls()[0]->reels()[0]->add(reel_subs);
dcp->write_xml (
dcp::String::compose("libdcp %1", dcp::version),
dcp::String::compose("libdcp %1", dcp::version),
class TestText
{
public:
- TestText (int in_, int out_, float v_position_ = 0, string text_ = "Hello")
+ TestText (int in_, int out_, float v_position_ = 0, dcp::VAlign v_align_ = dcp::VAlign::CENTER, string text_ = "Hello")
: in(in_)
, out(out_)
, v_position(v_position_)
+ , v_align(v_align_)
, text(text_)
{}
int in;
int out;
float v_position;
+ dcp::VAlign v_align;
string text;
};
auto asset = make_shared<dcp::SMPTESubtitleAsset>();
asset->set_start_time (dcp::Time());
for (auto i: subs) {
- add_test_subtitle (asset, i.in, i.out, i.v_position, i.text);
+ add_test_subtitle (asset, i.in, i.out, i.v_position, i.v_align, i.text);
}
asset->set_language (dcp::LanguageTag("de-DE"));
asset->write (dir / "subs.mxf");
}
+template <class T>
+shared_ptr<dcp::CPL>
+dcp_with_text_from_file (path dir, boost::filesystem::path subs_xml)
+{
+ prepare_directory (dir);
+ auto asset = make_shared<dcp::SMPTESubtitleAsset>(subs_xml);
+ asset->set_start_time (dcp::Time());
+ asset->set_language (dcp::LanguageTag("de-DE"));
+
+ auto subs_mxf = dir / "subs.mxf";
+ asset->write (subs_mxf);
+
+ /* The call to write() puts the asset into the DCP correctly but it will have
+ * XML re-written by our parser. Overwrite the MXF using the given file's verbatim
+ * contents.
+ */
+ ASDCP::TimedText::MXFWriter writer;
+ ASDCP::WriterInfo writer_info;
+ writer_info.LabelSetType = ASDCP::LS_MXF_SMPTE;
+ unsigned int c;
+ Kumu::hex2bin (asset->id().c_str(), writer_info.AssetUUID, Kumu::UUID_Length, &c);
+ DCP_ASSERT (c == Kumu::UUID_Length);
+ ASDCP::TimedText::TimedTextDescriptor descriptor;
+ descriptor.ContainerDuration = asset->intrinsic_duration();
+ Kumu::hex2bin (asset->xml_id()->c_str(), descriptor.AssetID, ASDCP::UUIDlen, &c);
+ DCP_ASSERT (c == Kumu::UUID_Length);
+ ASDCP::Result_t r = writer.OpenWrite (subs_mxf.string().c_str(), writer_info, descriptor, 16384);
+ BOOST_REQUIRE (!ASDCP_FAILURE(r));
+ r = writer.WriteTimedTextResource (dcp::file_to_string(subs_xml));
+ BOOST_REQUIRE (!ASDCP_FAILURE(r));
+ writer.Finalize ();
+
+ auto reel_asset = make_shared<T>(asset, dcp::Fraction(24, 1), asset->intrinsic_duration(), 0);
+ return write_dcp_with_single_asset (dir, reel_asset);
+}
+
+
BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_first_text_time)
{
auto const dir = path("build/test/verify_invalid_subtitle_first_text_time");
auto cpl = dcp_with_text<dcp::ReelSMPTESubtitleAsset> (
dir,
{
- { 96, 200, 0.0, "We" },
- { 96, 200, 0.1, "have" },
- { 96, 200, 0.2, "four" },
- { 96, 200, 0.3, "lines" }
+ { 96, 200, 0.0, dcp::VAlign::CENTER, "We" },
+ { 96, 200, 0.1, dcp::VAlign::CENTER, "have" },
+ { 96, 200, 0.2, dcp::VAlign::CENTER, "four" },
+ { 96, 200, 0.3, dcp::VAlign::CENTER, "lines" }
});
check_verify_result (
{dir},
auto cpl = dcp_with_text<dcp::ReelSMPTESubtitleAsset> (
dir,
{
- { 96, 200, 0.0, "We" },
- { 96, 200, 0.1, "have" },
- { 96, 200, 0.2, "four" },
+ { 96, 200, 0.0, dcp::VAlign::CENTER, "We" },
+ { 96, 200, 0.1, dcp::VAlign::CENTER, "have" },
+ { 96, 200, 0.2, dcp::VAlign::CENTER, "four" },
});
check_verify_result ({dir}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
}
auto cpl = dcp_with_text<dcp::ReelSMPTESubtitleAsset> (
dir,
{
- { 96, 300, 0.0, "We" },
- { 96, 300, 0.1, "have" },
- { 150, 180, 0.2, "four" },
- { 150, 180, 0.3, "lines" }
+ { 96, 300, 0.0, dcp::VAlign::CENTER, "We" },
+ { 96, 300, 0.1, dcp::VAlign::CENTER, "have" },
+ { 150, 180, 0.2, dcp::VAlign::CENTER, "four" },
+ { 150, 180, 0.3, dcp::VAlign::CENTER, "lines" }
});
check_verify_result (
{dir},
auto cpl = dcp_with_text<dcp::ReelSMPTESubtitleAsset> (
dir,
{
- { 96, 300, 0.0, "We" },
- { 96, 300, 0.1, "have" },
- { 150, 180, 0.2, "four" },
- { 190, 250, 0.3, "lines" }
+ { 96, 300, 0.0, dcp::VAlign::CENTER, "We" },
+ { 96, 300, 0.1, dcp::VAlign::CENTER, "have" },
+ { 150, 180, 0.2, dcp::VAlign::CENTER, "four" },
+ { 190, 250, 0.3, dcp::VAlign::CENTER, "lines" }
});
check_verify_result ({dir}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
}
auto cpl = dcp_with_text<dcp::ReelSMPTESubtitleAsset> (
dir,
{
- { 96, 300, 0.0, "012345678901234567890123456789012345678901234567890123" }
+ { 96, 300, 0.0, dcp::VAlign::CENTER, "012345678901234567890123456789012345678901234567890123" }
});
check_verify_result (
{dir},
auto cpl = dcp_with_text<dcp::ReelSMPTESubtitleAsset> (
dir,
{
- { 96, 300, 0.0, "012345678901234567890123456789012345678901234567890123456789012345678901234567890" }
+ { 96, 300, 0.0, dcp::VAlign::CENTER, "012345678901234567890123456789012345678901234567890123456789012345678901234567890" }
});
check_verify_result (
{dir},
BOOST_AUTO_TEST_CASE (verify_valid_closed_caption_line_count1)
{
auto const dir = path ("build/test/verify_valid_closed_caption_line_count1");
- auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
+ auto cpl = dcp_with_text<dcp::ReelSMPTEClosedCaptionAsset> (
dir,
{
- { 96, 200, 0.0, "We" },
- { 96, 200, 0.1, "have" },
- { 96, 200, 0.2, "four" },
- { 96, 200, 0.3, "lines" }
+ { 96, 200, 0.0, dcp::VAlign::CENTER, "We" },
+ { 96, 200, 0.1, dcp::VAlign::CENTER, "have" },
+ { 96, 200, 0.2, dcp::VAlign::CENTER, "four" },
+ { 96, 200, 0.3, dcp::VAlign::CENTER, "lines" }
});
check_verify_result (
{dir},
BOOST_AUTO_TEST_CASE (verify_valid_closed_caption_line_count2)
{
auto const dir = path ("build/test/verify_valid_closed_caption_line_count2");
- auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
+ auto cpl = dcp_with_text<dcp::ReelSMPTEClosedCaptionAsset> (
dir,
{
- { 96, 200, 0.0, "We" },
- { 96, 200, 0.1, "have" },
- { 96, 200, 0.2, "four" },
+ { 96, 200, 0.0, dcp::VAlign::CENTER, "We" },
+ { 96, 200, 0.1, dcp::VAlign::CENTER, "have" },
+ { 96, 200, 0.2, dcp::VAlign::CENTER, "four" },
});
check_verify_result ({dir}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
}
BOOST_AUTO_TEST_CASE (verify_invalid_closed_caption_line_count3)
{
auto const dir = path ("build/test/verify_invalid_closed_caption_line_count3");
- auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
+ auto cpl = dcp_with_text<dcp::ReelSMPTEClosedCaptionAsset> (
dir,
{
- { 96, 300, 0.0, "We" },
- { 96, 300, 0.1, "have" },
- { 150, 180, 0.2, "four" },
- { 150, 180, 0.3, "lines" }
+ { 96, 300, 0.0, dcp::VAlign::CENTER, "We" },
+ { 96, 300, 0.1, dcp::VAlign::CENTER, "have" },
+ { 150, 180, 0.2, dcp::VAlign::CENTER, "four" },
+ { 150, 180, 0.3, dcp::VAlign::CENTER, "lines" }
});
check_verify_result (
{dir},
BOOST_AUTO_TEST_CASE (verify_valid_closed_caption_line_count4)
{
auto const dir = path ("build/test/verify_valid_closed_caption_line_count4");
- auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
+ auto cpl = dcp_with_text<dcp::ReelSMPTEClosedCaptionAsset> (
dir,
{
- { 96, 300, 0.0, "We" },
- { 96, 300, 0.1, "have" },
- { 150, 180, 0.2, "four" },
- { 190, 250, 0.3, "lines" }
+ { 96, 300, 0.0, dcp::VAlign::CENTER, "We" },
+ { 96, 300, 0.1, dcp::VAlign::CENTER, "have" },
+ { 150, 180, 0.2, dcp::VAlign::CENTER, "four" },
+ { 190, 250, 0.3, dcp::VAlign::CENTER, "lines" }
});
check_verify_result ({dir}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
}
BOOST_AUTO_TEST_CASE (verify_invalid_closed_caption_line_length)
{
auto const dir = path ("build/test/verify_invalid_closed_caption_line_length");
- auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
+ auto cpl = dcp_with_text<dcp::ReelSMPTEClosedCaptionAsset> (
dir,
{
- { 96, 300, 0.0, "0123456789012345678901234567890123" }
+ { 96, 300, 0.0, dcp::VAlign::CENTER, "0123456789012345678901234567890123" }
});
check_verify_result (
{dir},
}
+BOOST_AUTO_TEST_CASE (verify_mismatched_closed_caption_valign1)
+{
+ auto const dir = path ("build/test/verify_mismatched_closed_caption_valign1");
+ auto cpl = dcp_with_text<dcp::ReelSMPTEClosedCaptionAsset> (
+ dir,
+ {
+ { 96, 300, 0.0, dcp::VAlign::TOP, "This" },
+ { 96, 300, 0.1, dcp::VAlign::TOP, "is" },
+ { 96, 300, 0.2, dcp::VAlign::TOP, "fine" },
+ });
+ check_verify_result (
+ {dir},
+ {
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ });
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_mismatched_closed_caption_valign2)
+{
+ auto const dir = path ("build/test/verify_mismatched_closed_caption_valign2");
+ auto cpl = dcp_with_text<dcp::ReelSMPTEClosedCaptionAsset> (
+ dir,
+ {
+ { 96, 300, 0.0, dcp::VAlign::TOP, "This" },
+ { 96, 300, 0.1, dcp::VAlign::TOP, "is" },
+ { 96, 300, 0.2, dcp::VAlign::CENTER, "not fine" },
+ });
+ check_verify_result (
+ {dir},
+ {
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_VALIGN },
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ });
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_incorrect_closed_caption_ordering1)
+{
+ auto const dir = path ("build/test/verify_invalid_incorrect_closed_caption_ordering1");
+ auto cpl = dcp_with_text<dcp::ReelSMPTEClosedCaptionAsset> (
+ dir,
+ {
+ { 96, 300, 0.0, dcp::VAlign::TOP, "This" },
+ { 96, 300, 0.1, dcp::VAlign::TOP, "is" },
+ { 96, 300, 0.2, dcp::VAlign::TOP, "fine" },
+ });
+ check_verify_result (
+ {dir},
+ {
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ });
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_incorrect_closed_caption_ordering2)
+{
+ auto const dir = path ("build/test/verify_invalid_incorrect_closed_caption_ordering2");
+ auto cpl = dcp_with_text<dcp::ReelSMPTEClosedCaptionAsset> (
+ dir,
+ {
+ { 96, 300, 0.2, dcp::VAlign::BOTTOM, "This" },
+ { 96, 300, 0.1, dcp::VAlign::BOTTOM, "is" },
+ { 96, 300, 0.0, dcp::VAlign::BOTTOM, "also fine" },
+ });
+ check_verify_result (
+ {dir},
+ {
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ });
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_incorrect_closed_caption_ordering3)
+{
+ auto const dir = path ("build/test/verify_incorrect_closed_caption_ordering3");
+ auto cpl = dcp_with_text_from_file<dcp::ReelSMPTEClosedCaptionAsset> (dir, "test/data/verify_incorrect_closed_caption_ordering3.xml");
+ check_verify_result (
+ {dir},
+ {
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ORDERING },
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ });
+}
+
+
+BOOST_AUTO_TEST_CASE (verify_incorrect_closed_caption_ordering4)
+{
+ auto const dir = path ("build/test/verify_incorrect_closed_caption_ordering4");
+ auto cpl = dcp_with_text_from_file<dcp::ReelSMPTEClosedCaptionAsset> (dir, "test/data/verify_incorrect_closed_caption_ordering4.xml");
+ check_verify_result (
+ {dir},
+ {
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ });
+}
+
+
+
BOOST_AUTO_TEST_CASE (verify_invalid_sound_frame_rate)
{
path const dir("build/test/verify_invalid_sound_frame_rate");
auto reel_picture = make_shared<dcp::ReelMonoPictureAsset>(picture, 0);
auto reel = make_shared<dcp::Reel>();
reel->add (reel_picture);
- auto sound = simple_sound (dir, "foo", dcp::MXFMetadata(), "de-DE", 24, 96000);
+ auto sound = simple_sound (dir, "foo", dcp::MXFMetadata(), "de-DE", 24, 96000, boost::none);
auto reel_sound = make_shared<dcp::ReelSoundAsset>(sound, 0);
reel->add (reel_sound);
reel->add (simple_markers());
);
for (int i = 0; i < caps_in_reel1; ++i) {
- reel1->add (make_shared<dcp::ReelClosedCaptionAsset>(subs, dcp::Fraction(24, 1), reel_length, 0));
+ reel1->add (make_shared<dcp::ReelSMPTEClosedCaptionAsset>(subs, dcp::Fraction(24, 1), reel_length, 0));
}
auto markers1 = make_shared<dcp::ReelMarkersAsset>(dcp::Fraction(24, 1), reel_length, 0);
);
for (int i = 0; i < caps_in_reel2; ++i) {
- reel2->add (make_shared<dcp::ReelClosedCaptionAsset>(subs, dcp::Fraction(24, 1), reel_length, 0));
+ reel2->add (make_shared<dcp::ReelSMPTEClosedCaptionAsset>(subs, dcp::Fraction(24, 1), reel_length, 0));
}
auto markers2 = make_shared<dcp::ReelMarkersAsset>(dcp::Fraction(24, 1), reel_length, 0);
}
);
- verify_text_entry_point_check<dcp::ReelClosedCaptionAsset> (
+ verify_text_entry_point_check<dcp::ReelSMPTEClosedCaptionAsset> (
"build/test/verify_closed_caption_entry_point_must_be_present",
dcp::VerificationNote::Code::MISSING_CLOSED_CAPTION_ENTRY_POINT,
- [](shared_ptr<dcp::ReelClosedCaptionAsset> asset) {
+ [](shared_ptr<dcp::ReelSMPTEClosedCaptionAsset> asset) {
asset->unset_entry_point ();
}
);
- verify_text_entry_point_check<dcp::ReelClosedCaptionAsset> (
+ verify_text_entry_point_check<dcp::ReelSMPTEClosedCaptionAsset> (
"build/test/verify_closed_caption_entry_point_must_be_zero",
dcp::VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ENTRY_POINT,
- [](shared_ptr<dcp::ReelClosedCaptionAsset> asset) {
+ [](shared_ptr<dcp::ReelSMPTEClosedCaptionAsset> asset) {
asset->set_entry_point (9);
}
);
BOOST_REQUIRE_EQUAL (dcp->cpls().size(), 1U);
auto const cpl = dcp->cpls()[0];
+ BOOST_REQUIRE_EQUAL (cpl->reels().size(), 1U);
+ BOOST_REQUIRE (cpl->reels()[0]->main_picture());
+ auto asset_id = cpl->reels()[0]->main_picture()->id();
{
BOOST_REQUIRE (cpl->file());
Editor e(cpl->file().get());
- e.replace("<Hash>addO7je2lZSNQp55qjCWo5DLKFQ=</Hash>", "");
+ e.delete_first_line_containing("<Hash>");
}
check_verify_result (
{dir},
{
{ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_HASH, string("1fab8bb0-cfaf-4225-ad6d-01768bc10470") }
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_HASH, asset_id }
});
}
"A Test DCP"
);
+ BOOST_REQUIRE_EQUAL (dcp->cpls().size(), 1U);
auto cpl = dcp->cpls()[0];
{
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
});
}
+
+
+/** Check a DCP with a 3D asset marked as 2D */
+BOOST_AUTO_TEST_CASE (verify_threed_marked_as_twod)
+{
+ check_verify_result (
+ { private_test / "data" / "xm" },
+ {
+ {
+ dcp::VerificationNote::Type::WARNING,
+ dcp::VerificationNote::Code::THREED_ASSET_MARKED_AS_TWOD, boost::filesystem::canonical(find_file(private_test / "data" / "xm", "j2c"))
+ },
+ {
+ dcp::VerificationNote::Type::BV21_ERROR,
+ dcp::VerificationNote::Code::INVALID_STANDARD
+ },
+ });
+
+}
+