40 #include "compose.hpp"
46 LIBDCP_DISABLE_WARNINGS
47 #include <libxml++/libxml++.h>
48 LIBDCP_ENABLE_WARNINGS
49 #include <boost/algorithm/string.hpp>
61 using namespace boost;
66 return (a.width == b.width && a.height == b.height);
82 split (b, s, is_any_of (
" "));
84 boost::throw_exception (
XMLError(
"malformed fraction " + s +
" in XML node"));
86 numerator = raw_convert<int> (b[0]);
87 denominator = raw_convert<int> (b[1]);
92 Fraction::as_string ()
const
94 return String::compose (
"%1 %2", numerator, denominator);
101 return (a.numerator == b.numerator && a.denominator == b.denominator);
108 return (a.numerator != b.numerator || a.denominator != b.denominator);
124 if (sscanf (argb_hex.c_str(),
"%2x%2x%2x%2x", &alpha, &
r, &
g, &
b) != 4) {
125 boost::throw_exception (
XMLError (
"could not parse colour string"));
134 snprintf (buffer,
sizeof(buffer),
"FF%02X%02X%02X",
r,
g,
b);
143 snprintf (buffer,
sizeof(buffer),
"%02X%02X%02X",
r,
g,
b);
151 return (a.
r == b.
r && a.
g == b.
g && a.
b == b.
b);
163 dcp::effect_to_string (Effect e)
174 boost::throw_exception (
MiscError(
"unknown effect type"));
179 dcp::string_to_effect (
string s)
183 }
else if (s ==
"border") {
184 return Effect::BORDER;
185 }
else if (s ==
"shadow") {
186 return Effect::SHADOW;
189 boost::throw_exception (
ReadError(
"unknown subtitle effect type"));
207 boost::throw_exception (
MiscError(
"unknown subtitle direction type"));
212 dcp::string_to_direction (
string s)
214 if (s ==
"ltr" || s ==
"horizontal") {
216 }
else if (s ==
"rtl") {
218 }
else if (s ==
"ttb" || s ==
"vertical") {
220 }
else if (s ==
"btt") {
224 boost::throw_exception (
ReadError(
"unknown subtitle direction type"));
263 dcp::marker_from_string (
string s)
267 }
else if (s ==
"LFOC") {
269 }
else if (s ==
"FFTC") {
271 }
else if (s ==
"LFTC") {
273 }
else if (s ==
"FFOI") {
275 }
else if (s ==
"LFOI") {
277 }
else if (s ==
"FFEC") {
279 }
else if (s ==
"LFEC") {
281 }
else if (s ==
"FFMC") {
283 }
else if (s ==
"LFMC") {
285 }
else if (s ==
"FFOB") {
287 }
else if (s ==
"LFOB") {
295 ContentVersion::ContentVersion ()
296 : id (
"urn:uuid:" + make_uuid())
302 ContentVersion::ContentVersion (cxml::ConstNodePtr node)
303 : id(node->string_child(
"Id"))
304 , label_text(node->string_child(
"LabelText"))
310 ContentVersion::ContentVersion (
string label_text_)
311 : id (
"urn:uuid:" + make_uuid())
312 , label_text (label_text_)
319 ContentVersion::as_xml (xmlpp::Element* parent)
const
321 auto cv = cxml::add_child(parent,
"ContentVersion");
322 cxml::add_text_child(cv,
"Id",
id);
323 cxml::add_text_child(cv,
"LabelText", label_text);
327 Luminance::Luminance (cxml::ConstNodePtr node)
329 , _unit(string_to_unit(node->string_attribute(
"units")))
335 Luminance::Luminance (
float value, Unit unit)
343 Luminance::set_value (
float v)
346 throw dcp::MiscError (String::compose(
"Invalid luminance value %1", v));
354 Luminance::as_xml (xmlpp::Element* parent,
string ns)
const
356 auto lum = cxml::add_child(parent,
"Luminance", ns);
357 lum->set_attribute(
"units", unit_to_string(_unit));
358 lum->add_child_text(raw_convert<string>(_value, 3));
363 Luminance::unit_to_string (Unit u)
366 case Unit::CANDELA_PER_SQUARE_METRE:
367 return "candela-per-square-metre";
368 case Unit::FOOT_LAMBERT:
369 return "foot-lambert";
379 Luminance::string_to_unit (
string u)
381 if (u ==
"candela-per-square-metre") {
382 return Unit::CANDELA_PER_SQUARE_METRE;
383 }
else if (u ==
"foot-lambert") {
384 return Unit::FOOT_LAMBERT;
387 throw XMLError (String::compose(
"Invalid luminance unit %1", u));
392 Luminance::value_in_foot_lamberts ()
const
395 case Unit::CANDELA_PER_SQUARE_METRE:
396 return _value / 3.426;
397 case Unit::FOOT_LAMBERT:
408 return fabs(a.value() - b.value()) < 0.001 && a.unit() == b.unit();
412 MainSoundConfiguration::MainSoundConfiguration (
string s)
414 vector<string> parts;
415 boost::split (parts, s, boost::is_any_of(
"/"));
420 if (parts[0] ==
"51") {
421 _field = MCASoundField::FIVE_POINT_ONE;
422 }
else if (parts[0] ==
"71") {
423 _field = MCASoundField::SEVEN_POINT_ONE;
425 _field = MCASoundField::OTHER;
428 if (parts.size() < 2) {
435 vector<string> channels;
436 boost::split (channels, parts[1], boost::is_any_of(
","));
438 if (channels.size() > 16) {
442 for (
auto i: channels) {
444 _channels.push_back(optional<Channel>());
446 _channels.push_back(mca_id_to_channel(i));
452 MainSoundConfiguration::MainSoundConfiguration (MCASoundField field,
int channels)
455 _channels.resize (channels);
460 MainSoundConfiguration::to_string ()
const
464 case MCASoundField::FIVE_POINT_ONE:
467 case MCASoundField::SEVEN_POINT_ONE:
474 for (
auto i: _channels) {
478 c += channel_to_mca_id(*i, _field) +
",";
482 if (c.length() > 0) {
483 c = c.substr(0, c.length() - 1);
491 MainSoundConfiguration::mapping (
int index)
const
493 DCP_ASSERT (
static_cast<size_t>(index) < _channels.size());
494 return _channels[index];
499 MainSoundConfiguration::set_mapping (
int index,
Channel c)
501 DCP_ASSERT (
static_cast<size_t>(index) < _channels.size());
502 _channels[index] = c;
507 dcp::status_to_string (
Status s)
523 dcp::string_to_status (
string s)
527 }
else if (s ==
"temp") {
529 }
else if (s ==
"pre") {
538 dcp::mca_id_to_channel (
string id)
540 transform(
id.begin(),
id.end(),
id.begin(), ::tolower);
544 }
else if (
id ==
"r") {
546 }
else if (
id ==
"c") {
548 }
else if (
id ==
"lfe") {
550 }
else if (
id ==
"ls" ||
id ==
"lss" ||
id ==
"lslss") {
552 }
else if (
id ==
"rs" ||
id ==
"rss" ||
id ==
"rsrss") {
554 }
else if (
id ==
"hi") {
556 }
else if (
id ==
"vin" ||
id ==
"vi-n") {
558 }
else if (
id ==
"lc") {
560 }
else if (
id ==
"rc") {
562 }
else if (
id ==
"lrs" ||
id ==
"lsr") {
564 }
else if (
id ==
"rrs" ||
id ==
"rsr") {
566 }
else if (
id ==
"dbox" ||
id ==
"dbox2" ||
id ==
"mtn") {
567 return Channel::MOTION_DATA;
568 }
else if (
id ==
"sync" ||
id ==
"fsksync") {
569 return Channel::SYNC_SIGNAL;
570 }
else if (
id ==
"slvs") {
571 return Channel::SIGN_LANGUAGE;
579 dcp::channel_to_mca_id (
Channel c, MCASoundField field)
591 return field == MCASoundField::FIVE_POINT_ONE ?
"Ls" :
"Lss";
593 return field == MCASoundField::FIVE_POINT_ONE ?
"Rs" :
"Rss";
602 case Channel::MOTION_DATA:
604 case Channel::SYNC_SIGNAL:
606 case Channel::SIGN_LANGUAGE:
617 dcp::channel_to_mca_name (
Channel c, MCASoundField field)
629 return field == MCASoundField::FIVE_POINT_ONE ?
"Left Surround" :
"Left Side Surround";
631 return field == MCASoundField::FIVE_POINT_ONE ?
"Right Surround" :
"Right Side Surround";
633 return "Hearing Impaired";
635 return "Visually Impaired-Narrative";
637 return "Left Rear Surround";
639 return "Right Rear Surround";
640 case Channel::MOTION_DATA:
641 return "D-BOX Motion Code Primary Stream";
642 case Channel::SYNC_SIGNAL:
644 case Channel::SIGN_LANGUAGE:
645 return "Sign Language Video Stream";
655 dcp::channel_to_mca_universal_label (
Channel c, MCASoundField field, ASDCP::Dictionary
const* dict)
657 static byte_t sync_signal[] = {
658 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x03, 0x02, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00
661 static byte_t sign_language[] = {
662 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x0d, 0x0f, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00
667 return dict->ul(ASDCP::MDD_DCAudioChannel_L);
669 return dict->ul(ASDCP::MDD_DCAudioChannel_R);
671 return dict->ul(ASDCP::MDD_DCAudioChannel_C);
673 return dict->ul(ASDCP::MDD_DCAudioChannel_LFE);
675 return dict->ul(field == MCASoundField::FIVE_POINT_ONE ? ASDCP::MDD_DCAudioChannel_Ls : ASDCP::MDD_DCAudioChannel_Lss);
677 return dict->ul(field == MCASoundField::FIVE_POINT_ONE ? ASDCP::MDD_DCAudioChannel_Rs : ASDCP::MDD_DCAudioChannel_Rss);
679 return dict->ul(ASDCP::MDD_DCAudioChannel_HI);
681 return dict->ul(ASDCP::MDD_DCAudioChannel_VIN);
683 return dict->ul(ASDCP::MDD_DCAudioChannel_Lrs);
685 return dict->ul(ASDCP::MDD_DCAudioChannel_Rrs);
686 case Channel::MOTION_DATA:
687 return dict->ul(ASDCP::MDD_DBOXMotionCodePrimaryStream);
688 case Channel::SYNC_SIGNAL:
689 return ASDCP::UL(sync_signal);
690 case Channel::SIGN_LANGUAGE:
691 return ASDCP::UL(sign_language);
701 dcp::used_audio_channels ()
714 Channel::MOTION_DATA,
715 Channel::SYNC_SIGNAL,
716 Channel::SIGN_LANGUAGE
722 dcp::formulation_to_string (dcp::Formulation formulation)
724 switch (formulation) {
725 case Formulation::MODIFIED_TRANSITIONAL_1:
726 return "modified-transitional-1";
727 case Formulation::MULTIPLE_MODIFIED_TRANSITIONAL_1:
728 return "multiple-modified-transitional-1";
729 case Formulation::DCI_ANY:
731 case Formulation::DCI_SPECIFIC:
732 return "dci-specific";
740 dcp::string_to_formulation (
string formulation)
742 if (formulation ==
"modified-transitional-1") {
743 return Formulation::MODIFIED_TRANSITIONAL_1;
744 }
else if (formulation ==
"multiple-modified-transitional-1") {
745 return Formulation::MULTIPLE_MODIFIED_TRANSITIONAL_1;
746 }
else if (formulation ==
"dci-any") {
747 return Formulation::DCI_ANY;
748 }
else if (formulation ==
"dci-specific") {
749 return Formulation::DCI_SPECIFIC;
int g
green component, from 0 to 255
int b
blue component, from 0 to 255
int r
red component, from 0 to 255
std::string to_argb_string() const
std::string to_rgb_string() const
A fraction (i.e. a thing with an integer numerator and an integer denominator).
A miscellaneous exception.
Any error that occurs when reading data from a DCP.
Exceptions thrown by libdcp.
Namespace for everything in libdcp.
@ FFOB
first frame of ratings band
@ FFOI
first frame of intermission
@ FFEC
first frame of end credits
@ LFMC
last frame of moving credits
@ LFOI
last frame of intermission
@ FFMC
first frame of moving credits
@ FFTC
first frame of title credits
@ LFOC
last frame of composition
@ FFOC
first frame of composition
@ LFOB
last frame of ratings band
@ LFEC
last frame of end credits
@ LFTC
last frame of title credits
@ LFE
low-frequency effects (sub)
@ LC
not used, but referred to in MainSoundConfiguration in some CPLs
@ RC
not used, but referred to in MainSoundConfiguration in some CPLs
P raw_convert(Q, int precision=16, bool fixed=false)
@ TEMP
temporary version (picture/sound unfinished)
@ PRE
pre-release (picture/sound finished)
Methods for conversion to/from string.
The integer, two-dimensional size of something.