diff options
Diffstat (limited to 'src/lib/dcp_content.cc')
| -rw-r--r-- | src/lib/dcp_content.cc | 214 |
1 files changed, 109 insertions, 105 deletions
diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc index 6e573c639..b4e979481 100644 --- a/src/lib/dcp_content.cc +++ b/src/lib/dcp_content.cc @@ -139,6 +139,11 @@ DCPContent::DCPContent (cxml::ConstNodePtr node, int version) DCPOMATIC_ASSERT (false); } } + + if (auto encoding = node->optional_string_child("VideoEncoding")) { + _video_encoding = video_encoding_from_string(*encoding); + } + _three_d = node->optional_bool_child("ThreeD").get_value_or (false); auto ck = node->optional_string_child("ContentKind"); @@ -163,6 +168,13 @@ DCPContent::DCPContent (cxml::ConstNodePtr node, int version) } _active_audio_channels = node->optional_number_child<int>("ActiveAudioChannels"); + + for (auto non_zero: node->node_children("HasNonZeroEntryPoint")) { + try { + auto type = string_to_text_type(non_zero->string_attribute("type")); + _has_non_zero_entry_point[type] = non_zero->content() == "1"; + } catch (MetadataError&) {} + } } void @@ -299,6 +311,7 @@ DCPContent::examine (shared_ptr<const Film> film, shared_ptr<Job> job) _needs_assets = examiner->needs_assets (); _kdm_valid = examiner->kdm_valid (); _standard = examiner->standard (); + _video_encoding = examiner->video_encoding(); _three_d = examiner->three_d (); _content_kind = examiner->content_kind (); _cpl = examiner->cpl (); @@ -308,6 +321,7 @@ DCPContent::examine (shared_ptr<const Film> film, shared_ptr<Job> job) } _ratings = examiner->ratings (); _content_versions = examiner->content_versions (); + _has_non_zero_entry_point = examiner->has_non_zero_entry_point(); } if (needed_assets == needs_assets()) { @@ -347,88 +361,99 @@ DCPContent::technical_summary () const return s; } + void -DCPContent::as_xml (xmlpp::Node* node, bool with_paths) const +DCPContent::as_xml(xmlpp::Element* element, bool with_paths) const { - node->add_child("Type")->add_child_text ("DCP"); + cxml::add_text_child(element, "Type", "DCP"); - Content::as_xml (node, with_paths); + Content::as_xml(element, with_paths); if (video) { - video->as_xml (node); + video->as_xml(element); } if (audio) { - audio->as_xml (node); - node->add_child("AudioFrameRate")->add_child_text (raw_convert<string> (audio->stream()->frame_rate())); - node->add_child("AudioLength")->add_child_text (raw_convert<string> (audio->stream()->length())); - audio->stream()->mapping().as_xml (node->add_child("AudioMapping")); + audio->as_xml(element); + cxml::add_text_child(element, "AudioFrameRate", raw_convert<string>(audio->stream()->frame_rate())); + cxml::add_text_child(element, "AudioLength", raw_convert<string>(audio->stream()->length())); + audio->stream()->mapping().as_xml(cxml::add_child(element, "AudioMapping")); } for (auto i: text) { - i->as_xml (node); + i->as_xml(element); } if (atmos) { - atmos->as_xml (node); + atmos->as_xml(element); } boost::mutex::scoped_lock lm (_mutex); - node->add_child("Name")->add_child_text (_name); - node->add_child("Encrypted")->add_child_text (_encrypted ? "1" : "0"); - node->add_child("NeedsAssets")->add_child_text (_needs_assets ? "1" : "0"); + cxml::add_text_child(element, "Name", _name); + cxml::add_text_child(element, "Encrypted", _encrypted ? "1" : "0"); + cxml::add_text_child(element, "NeedsAssets", _needs_assets ? "1" : "0"); if (_kdm) { - node->add_child("KDM")->add_child_text (_kdm->as_xml ()); + cxml::add_text_child(element, "KDM", _kdm->as_xml()); } - node->add_child("KDMValid")->add_child_text (_kdm_valid ? "1" : "0"); - node->add_child("ReferenceVideo")->add_child_text (_reference_video ? "1" : "0"); - node->add_child("ReferenceAudio")->add_child_text (_reference_audio ? "1" : "0"); - node->add_child("ReferenceOpenSubtitle")->add_child_text(_reference_text[TextType::OPEN_SUBTITLE] ? "1" : "0"); - node->add_child("ReferenceClosedCaption")->add_child_text(_reference_text[TextType::CLOSED_CAPTION] ? "1" : "0"); + cxml::add_text_child(element, "KDMValid", _kdm_valid ? "1" : "0"); + cxml::add_text_child(element, "ReferenceVideo", _reference_video ? "1" : "0"); + cxml::add_text_child(element, "ReferenceAudio", _reference_audio ? "1" : "0"); + cxml::add_text_child(element, "ReferenceOpenSubtitle", _reference_text[TextType::OPEN_SUBTITLE] ? "1" : "0"); + cxml::add_text_child(element, "ReferenceClosedCaption", _reference_text[TextType::CLOSED_CAPTION] ? "1" : "0"); if (_standard) { switch (_standard.get ()) { case dcp::Standard::INTEROP: - node->add_child("Standard")->add_child_text ("Interop"); + cxml::add_text_child(element, "Standard", "Interop"); break; case dcp::Standard::SMPTE: - node->add_child("Standard")->add_child_text ("SMPTE"); + cxml::add_text_child(element, "Standard", "SMPTE"); break; default: DCPOMATIC_ASSERT (false); } } - node->add_child("ThreeD")->add_child_text (_three_d ? "1" : "0"); + cxml::add_text_child(element, "VideoEncoding", video_encoding_to_string(_video_encoding)); + cxml::add_text_child(element, "ThreeD", _three_d ? "1" : "0"); if (_content_kind) { - node->add_child("ContentKind")->add_child_text(_content_kind->name()); + cxml::add_text_child(element, "ContentKind", _content_kind->name()); } if (_cpl) { - node->add_child("CPL")->add_child_text (_cpl.get ()); + cxml::add_text_child(element, "CPL", _cpl.get()); } for (auto i: _reel_lengths) { - node->add_child("ReelLength")->add_child_text (raw_convert<string> (i)); + cxml::add_text_child(element, "ReelLength", raw_convert<string>(i)); } for (auto const& i: _markers) { - auto marker = node->add_child("Marker"); + auto marker = cxml::add_child(element, "Marker"); marker->set_attribute("type", dcp::marker_to_string(i.first)); marker->add_child_text(raw_convert<string>(i.second.get())); } for (auto i: _ratings) { - auto rating = node->add_child("Rating"); + auto rating = cxml::add_child(element, "Rating"); i.as_xml (rating); } for (auto i: _content_versions) { - node->add_child("ContentVersion")->add_child_text(i); + cxml::add_text_child(element, "ContentVersion", i); } if (_active_audio_channels) { - node->add_child("ActiveAudioChannels")->add_child_text(raw_convert<string>(*_active_audio_channels)); + cxml::add_text_child(element, "ActiveAudioChannels", raw_convert<string>(*_active_audio_channels)); + } + + for (auto i = 0; i < static_cast<int>(TextType::COUNT); ++i) { + if (_has_non_zero_entry_point[i]) { + auto has = cxml::add_child(element, "HasNonZeroEntryPoint"); + has->add_child_text("1"); + has->set_attribute("type", text_type_to_string(static_cast<TextType>(i))); + } } } + DCPTime DCPContent::full_length (shared_ptr<const Film> film) const { @@ -612,7 +637,7 @@ DCPContent::reel_split_points (shared_ptr<const Film> film) const } bool -DCPContent::can_reference (shared_ptr<const Film> film, function<bool (shared_ptr<const Content>)> part, string overlapping, string& why_not) const +DCPContent::can_reference_anything(shared_ptr<const Film> film, string& why_not) const { /* We must be using the same standard as the film */ if (_standard) { @@ -658,15 +683,16 @@ DCPContent::can_reference (shared_ptr<const Film> film, function<bool (shared_pt } } - auto a = overlaps (film, film->content(), part, position(), end(film)); - if (a.size() != 1 || a.front().get() != this) { - why_not = overlapping; - return false; - } - return true; } +bool +DCPContent::overlaps(shared_ptr<const Film> film, function<bool (shared_ptr<const Content>)> part) const +{ + auto const a = dcpomatic::overlaps(film, film->content(), part, position(), end(film)); + return a.size() != 1 || a.front().get() != this; +} + bool DCPContent::can_reference_video (shared_ptr<const Film> film, string& why_not) const @@ -691,35 +717,23 @@ DCPContent::can_reference_video (shared_ptr<const Film> film, string& why_not) c return false; } - /// TRANSLATORS: this string will follow "Cannot reference this DCP: " - return can_reference( - film, - [](shared_ptr<const Content> c) { - return static_cast<bool>(c->video) && c->video->use(); - }, - _("it overlaps other video content; remove the other content."), - why_not - ); + auto part = [](shared_ptr<const Content> c) { + return static_cast<bool>(c->video) && c->video->use(); + }; + + if (overlaps(film, part)) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("it overlaps other video content."); + return false; + } + + return can_reference_anything(film, why_not); } bool DCPContent::can_reference_audio (shared_ptr<const Film> film, string& why_not) const { - shared_ptr<DCPDecoder> decoder; - try { - decoder = make_shared<DCPDecoder>(film, shared_from_this(), false, film->tolerant(), shared_ptr<DCPDecoder>()); - } catch (dcp::ReadError &) { - /* We couldn't read the DCP, so it's probably missing */ - return false; - } catch (DCPError &) { - /* We couldn't read the DCP, so it's probably missing */ - return false; - } catch (dcp::KDMDecryptionError &) { - /* We have an incorrect KDM */ - return false; - } - if (audio && audio->stream()) { auto const channels = audio->stream()->channels(); if (channels != film->audio_channels()) { @@ -728,51 +742,33 @@ DCPContent::can_reference_audio (shared_ptr<const Film> film, string& why_not) c } } - /// TRANSLATORS: this string will follow "Cannot reference this DCP: " - return can_reference( - film, [](shared_ptr<const Content> c) { - return c->has_mapped_audio(); - }, - _("it overlaps other audio content; remove the other content."), - why_not - ); + auto part = [](shared_ptr<const Content> c) { + return c->has_mapped_audio(); + }; + + if (overlaps(film, part)) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("it overlaps other audio content."); + return false; + } + + return can_reference_anything(film, why_not); } bool DCPContent::can_reference_text (shared_ptr<const Film> film, TextType type, string& why_not) const { - shared_ptr<DCPDecoder> decoder; - try { - decoder = make_shared<DCPDecoder>(film, shared_from_this(), false, film->tolerant(), shared_ptr<DCPDecoder>()); - } catch (dcp::ReadError &) { - /* We couldn't read the DCP, so it's probably missing */ - return false; - } catch (DCPError &) { - /* We couldn't read the DCP, so it's probably missing */ - return false; - } catch (dcp::KDMDecryptionError &) { - /* We have an incorrect KDM */ + if (_has_non_zero_entry_point[TextType::OPEN_SUBTITLE]) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("one of its subtitle reels has a non-zero entry point so it must be re-written."); return false; } - for (auto i: decoder->reels()) { - if (type == TextType::OPEN_SUBTITLE) { - if (i->main_subtitle() && i->main_subtitle()->entry_point().get_value_or(0) != 0) { - /// TRANSLATORS: this string will follow "Cannot reference this DCP: " - why_not = _("one of its subtitle reels has a non-zero entry point so it must be re-written."); - return false; - } - } - if (type == TextType::CLOSED_CAPTION) { - for (auto j: i->closed_captions()) { - if (j->entry_point().get_value_or(0) != 0) { - /// TRANSLATORS: this string will follow "Cannot reference this DCP: " - why_not = _("one of its closed caption has a non-zero entry point so it must be re-written."); - return false; - } - } - } + if (_has_non_zero_entry_point[TextType::CLOSED_CAPTION]) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("one of its closed caption has a non-zero entry point so it must be re-written."); + return false; } if (trim_start() != dcpomatic::ContentTime()) { @@ -781,15 +777,17 @@ DCPContent::can_reference_text (shared_ptr<const Film> film, TextType type, stri return false; } - /// TRANSLATORS: this string will follow "Cannot reference this DCP: " - return can_reference( - film, - [type](shared_ptr<const Content> c) { - return std::find_if(c->text.begin(), c->text.end(), [type](shared_ptr<const TextContent> t) { return t->type() == type; }) != c->text.end(); - }, - _("they overlap other text content; remove the other content."), - why_not - ); + auto part = [type](shared_ptr<const Content> c) { + return std::find_if(c->text.begin(), c->text.end(), [type](shared_ptr<const TextContent> t) { return t->type() == type; }) != c->text.end(); + }; + + if (overlaps(film, part)) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("it overlaps other text content."); + return false; + } + + return can_reference_anything(film, why_not); } void @@ -853,8 +851,14 @@ DCPContent::check_font_ids() return; } + /* This might be called on a TextContent that already has some fonts + * (e.g. if run from a build with a LastWrittenBy containing only a git + * hash, or from a version between 2.16.15 and 2.17.17) so we'll get an + * error if we don't clear them out first. + */ + text[0]->clear_fonts(); DCPExaminer examiner(shared_from_this(), true); - examiner.add_fonts(text.front()); + examiner.add_fonts(text[0]); } |
