bool result = true;
+#ifdef LIBDCP_OPENMP
#pragma omp parallel for
+#endif
+
for (int i = 0; i < _intrinsic_duration; ++i) {
if (i >= other_picture->intrinsic_duration()) {
result = false;
result = false;
}
+#ifdef LIBDCP_OPENMP
#pragma omp critical
+#endif
{
note (DCP_PROGRESS, String::compose ("Compared video frame %1 of %2", i, _intrinsic_duration));
for (list<pair<NoteType, string> >::const_iterator i = notes.begin(); i != notes.end(); ++i) {
#include <boost/noncopyable.hpp>
#include <string>
-class write_subtitle_test;
+class write_interop_subtitle_test;
+class write_smpte_subtitle_test;
namespace dcp {
}
protected:
- friend class ::write_subtitle_test;
+ friend class ::write_interop_subtitle_test;
+ friend class ::write_smpte_subtitle_test;
/** ID */
std::string _id;
_language = l;
}
+ void set_issue_date (LocalTime t) {
+ _issue_date = t;
+ }
+
void set_reel_number (int r) {
_reel_number = r;
}
effective_text.h_align,
effective_text.v_position,
effective_text.v_align,
+ effective_text.direction,
text,
effective_font.effect.get_value_or (NONE),
effective_font.effect_colour.get_value_or (dcp::Colour (0, 0, 0)),
}
xmlpp::Element* text = subtitle_element->add_child ("Text", xmlns);
+
if (i.h_align() != HALIGN_CENTER) {
if (standard == SMPTE) {
text->set_attribute ("Halign", halign_to_string (i.h_align ()));
text->set_attribute ("HAlign", halign_to_string (i.h_align ()));
}
}
+
if (i.h_position() > ALIGN_EPSILON) {
if (standard == SMPTE) {
text->set_attribute ("Hposition", raw_convert<string> (i.h_position() * 100, 6));
text->set_attribute ("HPosition", raw_convert<string> (i.h_position() * 100, 6));
}
}
+
if (standard == SMPTE) {
text->set_attribute ("Valign", valign_to_string (i.v_align()));
} else {
text->set_attribute ("VAlign", valign_to_string (i.v_align()));
}
+
if (i.v_position() > ALIGN_EPSILON) {
if (standard == SMPTE) {
text->set_attribute ("Vposition", raw_convert<string> (i.v_position() * 100, 6));
text->set_attribute ("VPosition", "0");
}
}
+
+ /* Interop only supports "horizontal" or "vertical" for direction, so only write this
+ for SMPTE.
+ */
+ if (i.direction() != DIRECTION_LTR && standard == SMPTE) {
+ text->set_attribute ("Direction", direction_to_string (i.direction ()));
+ }
+
text->add_child_text (i.text());
}
}
HAlign h_align,
float v_position,
VAlign v_align,
+ Direction direction,
string text,
Effect effect,
Colour effect_colour,
, _h_align (h_align)
, _v_position (v_position)
, _v_align (v_align)
+ , _direction (direction)
, _text (text)
, _effect (effect)
, _effect_colour (effect_colour)
a.h_align() == b.h_align() &&
a.v_position() == b.v_position() &&
a.v_align() == b.v_align() &&
+ a.direction() == b.direction() &&
a.text() == b.text() &&
a.effect() == b.effect() &&
a.effect_colour() == b.effect_colour() &&
s << "size " << sub.size() << ", aspect " << sub.aspect_adjust() << ", colour " << sub.colour()
<< ", vpos " << sub.v_position() << ", valign " << ((int) sub.v_align())
<< ", hpos " << sub.h_position() << ", halign " << ((int) sub.h_align())
+ << ", direction " << ((int) sub.direction())
<< ", effect " << ((int) sub.effect()) << ", effect colour " << sub.effect_colour();
return s;
HAlign h_align,
float v_position,
VAlign v_align,
+ Direction direction,
std::string text,
Effect effect,
Colour effect_colour,
return _v_align;
}
+ Direction direction () const {
+ return _direction;
+ }
+
Effect effect () const {
return _effect;
}
*/
float _v_position;
VAlign _v_align;
+ Direction _direction;
std::string _text;
Effect _effect;
Colour _effect_colour;
, h_align (HALIGN_CENTER)
, v_position (0)
, v_align (VALIGN_CENTER)
+ , direction (DIRECTION_LTR)
{
text = node->content ();
v_align = string_to_valign (va.get ());
}
+ optional<string> d = node->optional_string_attribute ("Direction");
+ if (d) {
+ direction = string_to_direction (d.get ());
+ }
+
list<cxml::NodePtr> f = node->node_children ("Font");
BOOST_FOREACH (cxml::NodePtr& i, f) {
font_nodes.push_back (shared_ptr<FontNode> (new FontNode (i, tcr, font_id_attribute)));
, h_align (HALIGN_LEFT)
, v_position (0)
, v_align (VALIGN_TOP)
+ , direction (DIRECTION_LTR)
{}
TextNode (boost::shared_ptr<const cxml::Node> node, int tcr, std::string font_id_attribute);
HAlign h_align;
float v_position;
VAlign v_align;
+ Direction direction;
std::string text;
std::list<boost::shared_ptr<FontNode> > font_nodes;
};
boost::throw_exception (DCPReadError ("unknown subtitle valign type"));
}
+
+string
+dcp::direction_to_string (Direction v)
+{
+ switch (v) {
+ case DIRECTION_LTR:
+ return "ltr";
+ case DIRECTION_RTL:
+ return "rtl";
+ case DIRECTION_TTB:
+ return "ttb";
+ case DIRECTION_BTT:
+ return "btt";
+ }
+
+ boost::throw_exception (MiscError ("unknown subtitle direction type"));
+}
+
+Direction
+dcp::string_to_direction (string s)
+{
+ if (s == "ltr") {
+ return DIRECTION_LTR;
+ } else if (s == "rtl") {
+ return DIRECTION_RTL;
+ } else if (s == "ttb") {
+ return DIRECTION_TTB;
+ } else if (s == "btt") {
+ return DIRECTION_BTT;
+ }
+
+ boost::throw_exception (DCPReadError ("unknown subtitle direction type"));
+}
extern std::string valign_to_string (VAlign a);
extern VAlign string_to_valign (std::string s);
+/** Direction for subtitle test */
+enum Direction
+{
+ DIRECTION_LTR, ///< left-to-right
+ DIRECTION_RTL, ///< right-to-left
+ DIRECTION_TTB, ///< top-to-bottom
+ DIRECTION_BTT ///< bottom-to-top
+};
+
+extern std::string direction_to_string (Direction a);
+extern Direction string_to_direction (std::string s);
+
enum Eye
{
EYE_LEFT,
</Subtitle>
<Subtitle SpotNumber="4" TimeIn="00:01:15:042" TimeOut="00:01:16:042" FadeUpTime="0" FadeDownTime="0">
<Font Italic="yes">
- <Text HAlign="center" HPosition="0" VAlign="top" VPosition="89" ZPosition="0.5">With the legendary Miss Enid Blyton</Text>
+ <Text HAlign="center" HPosition="0" VAlign="top" VPosition="89" ZPosition="0.5" Direction="rtl">With the legendary Miss Enid Blyton</Text>
</Font>
<Font Italic="yes">
- <Text HAlign="center" HPosition="0" VAlign="top" VPosition="95" ZPosition="0.5">She said "you be Noddy</Text>
+ <Text HAlign="center" HPosition="0" VAlign="top" VPosition="95" ZPosition="0.5" Direction="ttb">She said "you be Noddy</Text>
</Font>
</Subtitle>
<Subtitle SpotNumber="5" TimeIn="00:01:20:219" TimeOut="00:01:22:073" FadeUpTime="0" FadeDownTime="0">
</Subtitle>
<Subtitle SpotNumber="6" TimeIn="00:01:27:115" TimeOut="00:01:28:208" FadeUpTime="0" FadeDownTime="0">
<Font Italic="yes">
- <Text HAlign="center" HPosition="0" VAlign="top" VPosition="89" ZPosition="0.5">That curious creature the Sphinx</Text>
+ <Text HAlign="center" HPosition="0" VAlign="top" VPosition="89" ZPosition="0.5" Direction="btt">That curious creature the Sphinx</Text>
</Font>
<Font Italic="yes">
<Text HAlign="center" HPosition="0" VAlign="top" VPosition="95" ZPosition="0.5">Is smarter than anyone thinks</Text>
#include <boost/bind.hpp>
#include <boost/test/unit_test.hpp>
#include <sys/time.h>
-#include <iostream>
void progress (float)
{
data.write ("build/test/random");
/* Hash it */
- struct timeval A;
- gettimeofday (&A, 0);
- for (int i = 0; i < 64; ++i) {
- BOOST_CHECK_EQUAL (dcp::make_digest ("build/test/random", boost::bind (&progress, _1)), "GKbk/V3fcRtP5MaPdSmAGNbKkaU=");
- }
- struct timeval B;
- gettimeofday (&B, 0);
-
- std::cout << ((B.tv_sec + B.tv_usec / 1e6) - (A.tv_sec + A.tv_usec / 1e6)) << "\n";
+ BOOST_CHECK_EQUAL (dcp::make_digest ("build/test/random", boost::bind (&progress, _1)), "GKbk/V3fcRtP5MaPdSmAGNbKkaU=");
}
dcp::HALIGN_CENTER,
0.15,
dcp::VALIGN_BOTTOM,
+ dcp::DIRECTION_LTR,
"My jacket was Idi Amin's",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.21,
dcp::VALIGN_BOTTOM,
+ dcp::DIRECTION_LTR,
"My corset was H.M. The Queen's",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.15,
dcp::VALIGN_BOTTOM,
+ dcp::DIRECTION_LTR,
"My large wonderbra",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.15,
dcp::VALIGN_BOTTOM,
+ dcp::DIRECTION_LTR,
"Once belonged to the Shah",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.15,
dcp::VALIGN_BOTTOM,
+ dcp::DIRECTION_LTR,
"And these are Roy Hattersley's jeans",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.89,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"At afternoon tea with John Peel",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.95,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"I enquired if his accent was real",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.89,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"He said \"out of the house",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.95,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"I'm incredibly scouse",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.89,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"At home it depends how I feel.\"",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.95,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"I spent a long weekend in Brighton",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.89,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_RTL,
"With the legendary Miss Enid Blyton",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.95,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_TTB,
"She said \"you be Noddy",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.89,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_BTT,
"That curious creature the Sphinx",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.95,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"Is smarter than anyone thinks",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.89,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"It sits there and smirks",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.95,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"And you don't think it works",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.89,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"Then when you're not looking, it winks.",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.95,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"When it snows you will find Sister Sledge",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.89,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"Out mooning, at night, on the ledge",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.95,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"One storey down",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.89,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"HELLO",
dcp::BORDER,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.95,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"WORLD",
dcp::BORDER,
dcp::Colour (0, 0, 0),
/*
- Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2015-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
#include "interop_subtitle_asset.h"
+#include "smpte_subtitle_asset.h"
#include "subtitle_string.h"
#include "test.h"
#include <boost/test/unit_test.hpp>
using boost::shared_ptr;
/* Write some subtitle content as Interop XML and check that it is right */
-BOOST_AUTO_TEST_CASE (write_subtitle_test)
+BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
{
dcp::InteropSubtitleAsset c;
c.set_reel_number ("1");
dcp::HALIGN_CENTER,
0.8,
dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
"Hello world",
dcp::NONE,
dcp::Colour (0, 0, 0),
dcp::HALIGN_CENTER,
0.4,
dcp::VALIGN_BOTTOM,
+ dcp::DIRECTION_LTR,
"What's going on",
dcp::BORDER,
dcp::Colour (1, 2, 3),
list<string> ()
);
}
+
+/* Write some subtitle content as SMPTE XML and check that it is right */
+BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test)
+{
+ dcp::SMPTESubtitleAsset c;
+ c.set_reel_number (1);
+ c.set_language ("EN");
+ c.set_content_title_text ("Test");
+ c.set_issue_date (dcp::LocalTime ("2016-04-01T03:52:00+00:00"));
+
+ c.add (
+ dcp::SubtitleString (
+ string ("Frutiger"),
+ false,
+ false,
+ dcp::Colour (255, 255, 255),
+ 48,
+ 1.0,
+ dcp::Time (0, 4, 9, 22, 24),
+ dcp::Time (0, 4, 11, 22, 24),
+ 0,
+ dcp::HALIGN_CENTER,
+ 0.8,
+ dcp::VALIGN_TOP,
+ dcp::DIRECTION_LTR,
+ "Hello world",
+ dcp::NONE,
+ dcp::Colour (0, 0, 0),
+ dcp::Time (0, 0, 0, 0, 24),
+ dcp::Time (0, 0, 0, 0, 24)
+ )
+ );
+
+ c.add (
+ dcp::SubtitleString (
+ boost::optional<string> (),
+ true,
+ true,
+ dcp::Colour (128, 0, 64),
+ 91,
+ 1.0,
+ dcp::Time (5, 41, 0, 21, 24),
+ dcp::Time (6, 12, 15, 21, 24),
+ 0,
+ dcp::HALIGN_CENTER,
+ 0.4,
+ dcp::VALIGN_BOTTOM,
+ dcp::DIRECTION_RTL,
+ "What's going on",
+ dcp::BORDER,
+ dcp::Colour (1, 2, 3),
+ dcp::Time (1, 2, 3, 4, 24),
+ dcp::Time (5, 6, 7, 8, 24)
+ )
+ );
+
+ c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
+
+ check_xml (
+ c.xml_as_string (),
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<dcst:SubtitleReel xmlns:dcst=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+ " <dcst:Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</dcst:Id>\n"
+ " <dcst:ContentTitleText>Test</dcst:ContentTitleText>\n"
+ " <dcst:IssueDate>2016-04-01T03:52:00.000+00:00</dcst:IssueDate>\n"
+ " <dcst:ReelNumber>1</dcst:ReelNumber>\n"
+ " <dcst:Language>EN</dcst:Language>\n"
+ " <dcst:EditRate>24 1</dcst:EditRate>\n"
+ " <dcst:TimeCodeRate>24</dcst:TimeCodeRate>\n"
+ " <dcst:SubtitleList>\n"
+ " <dcst:Font ID=\"Frutiger\" Italic=\"no\" Color=\"FFFFFFFF\" Size=\"48\" Effect=\"none\" EffectColor=\"FF000000\" Script=\"normal\" Underline=\"no\" Weight=\"normal\">\n"
+ " <dcst:Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:22\" TimeOut=\"00:04:11:22\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">\n"
+ " <dcst:Text Valign=\"top\" Vposition=\"80\">Hello world</dcst:Text>\n"
+ " </dcst:Subtitle>\n"
+ " </dcst:Font>\n"
+ " <dcst:Font Italic=\"yes\" Color=\"FF800040\" Size=\"91\" Effect=\"border\" EffectColor=\"FF010203\" Script=\"normal\" Underline=\"no\" Weight=\"bold\">\n"
+ " <dcst:Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:21\" TimeOut=\"06:12:15:21\" FadeUpTime=\"01:02:03:04\" FadeDownTime=\"05:06:07:08\">\n"
+ " <dcst:Text Valign=\"bottom\" Vposition=\"40\" Direction=\"rtl\">What's going on</dcst:Text>\n"
+ " </dcst:Subtitle>\n"
+ " </dcst:Font>\n"
+ " </dcst:SubtitleList>\n"
+ "</dcst:SubtitleReel>\n",
+ list<string> ()
+ );
+}
conf.env.append_value('CXXFLAGS', ['-Wno-unused-result', '-Wno-unused-parameter', '-Wno-unused-local-typedef'])
if conf.options.enable_openmp:
- conf.env.append_value('CXXFLAGS', '-fopenmp')
+ conf.env.append_value('CXXFLAGS', ['-fopenmp', '-DLIBDCP_OPENMP'])
conf.env.LIB_OPENMP = ['gomp']
conf.check_cfg(package='openssl', args='--cflags --libs', uselib_store='OPENSSL', mandatory=True)