43 #include "mono_picture_asset.h"
53 #include "reel_smpte_subtitle_asset.h"
55 #include "reel_markers_asset.h"
62 #include <libxml++/nodes/element.h>
69 using std::make_shared;
70 using std::shared_ptr;
71 using std::dynamic_pointer_cast;
76 Reel::Reel (std::shared_ptr<const cxml::Node> node, dcp::Standard standard)
77 :
Object (remove_urn_uuid (node->string_child (
"Id")))
79 auto asset_list = node->node_child (
"AssetList");
81 auto main_picture = asset_list->optional_node_child (
"MainPicture");
83 _main_picture = make_shared<ReelMonoPictureAsset>(main_picture);
86 auto main_stereoscopic_picture = asset_list->optional_node_child (
"MainStereoscopicPicture");
87 if (main_stereoscopic_picture) {
88 _main_picture = make_shared<ReelStereoPictureAsset>(main_stereoscopic_picture);
91 auto main_sound = asset_list->optional_node_child (
"MainSound");
93 _main_sound = make_shared<ReelSoundAsset>(main_sound);
96 auto main_subtitle = asset_list->optional_node_child (
"MainSubtitle");
99 case Standard::INTEROP:
100 _main_subtitle = make_shared<ReelInteropSubtitleAsset>(main_subtitle);
102 case Standard::SMPTE:
103 _main_subtitle = make_shared<ReelSMPTESubtitleAsset>(main_subtitle);
108 auto main_markers = asset_list->optional_node_child (
"MainMarkers");
110 _main_markers = make_shared<ReelMarkersAsset>(main_markers);
115 auto closed_captions = asset_list->node_children (
"MainClosedCaption");
116 if (closed_captions.empty()) {
117 closed_captions = asset_list->node_children (
"ClosedCaption");
119 for (
auto i: closed_captions) {
121 case Standard::INTEROP:
122 _closed_captions.push_back (make_shared<ReelInteropClosedCaptionAsset>(i));
124 case Standard::SMPTE:
125 _closed_captions.push_back (make_shared<ReelSMPTEClosedCaptionAsset>(i));
130 auto atmos = asset_list->optional_node_child (
"AuxData");
132 _atmos = make_shared<ReelAtmosAsset>(atmos);
135 node->ignore_child (
"AnnotationText");
141 Reel::write_to_cpl (xmlpp::Element* node, Standard standard)
const
143 auto reel = node->add_child (
"Reel");
144 reel->add_child(
"Id")->add_child_text(
"urn:uuid:" + _id);
145 xmlpp::Element* asset_list = reel->add_child (
"AssetList");
148 _main_markers->write_to_cpl (asset_list, standard);
151 if (_main_picture && dynamic_pointer_cast<ReelMonoPictureAsset> (_main_picture)) {
153 _main_picture->write_to_cpl (asset_list, standard);
157 _main_sound->write_to_cpl (asset_list, standard);
160 if (_main_subtitle) {
161 _main_subtitle->write_to_cpl (asset_list, standard);
164 for (
auto i: _closed_captions) {
165 i->write_to_cpl (asset_list, standard);
168 if (_main_picture && dynamic_pointer_cast<ReelStereoPictureAsset> (_main_picture)) {
170 _main_picture->write_to_cpl (asset_list, standard);
174 _atmos->write_to_cpl (asset_list, standard);
182 Reel::equals (std::shared_ptr<const Reel> other,
EqualityOptions opt, NoteHandler note)
const
184 if ((_main_picture && !other->_main_picture) || (!_main_picture && other->_main_picture)) {
185 note (NoteType::ERROR,
"Reel: picture assets differ");
189 if (_main_picture && !_main_picture->equals (other->_main_picture, opt, note)) {
193 if ((_main_sound && !other->_main_sound) || (!_main_sound && other->_main_sound)) {
194 note (NoteType::ERROR,
"Reel: sound assets differ");
198 if (_main_sound && !_main_sound->equals (other->_main_sound, opt, note)) {
202 if ((_main_subtitle && !other->_main_subtitle) || (!_main_subtitle && other->_main_subtitle)) {
203 note (NoteType::ERROR,
"Reel: subtitle assets differ");
207 bool same_type =
false;
210 auto interop = dynamic_pointer_cast<ReelInteropSubtitleAsset>(_main_subtitle);
211 auto interop_other = dynamic_pointer_cast<ReelInteropSubtitleAsset>(other->_main_subtitle);
212 if (interop && interop_other) {
214 if (!interop->equals(interop_other, opt, note)) {
221 auto smpte = dynamic_pointer_cast<ReelSMPTESubtitleAsset>(_main_subtitle);
222 auto smpte_other = dynamic_pointer_cast<ReelSMPTESubtitleAsset>(other->_main_subtitle);
223 if (smpte && smpte_other) {
225 if (!smpte->equals(smpte_other, opt, note)) {
231 if ((_main_subtitle || other->_main_subtitle) && !same_type) {
235 if ((_main_markers && !other->_main_markers) || (!_main_markers && other->_main_markers)) {
236 note (NoteType::ERROR,
"Reel: one has markers and the other does not");
240 if (_main_markers && !_main_markers->equals(other->_main_markers, opt, note)) {
241 note (NoteType::ERROR,
"Reel: marker assets differ");
245 if (_closed_captions.size() != other->_closed_captions.size()) {
249 auto i = _closed_captions.begin();
250 auto j = other->_closed_captions.begin();
251 while (i != _closed_captions.end()) {
252 if (!(*i)->equals(*j, opt, note)) {
259 if ((_atmos && !other->_atmos) || (!_atmos && other->_atmos)) {
260 note (NoteType::ERROR,
"Reel: atmos assets differ");
264 if (_atmos && !_atmos->equals (other->_atmos, opt, note)) {
273 Reel::any_encrypted ()
const
276 for (
auto i: _closed_captions) {
277 if (i->encrypted()) {
283 (_main_picture && _main_picture->encrypted()) ||
284 (_main_sound && _main_sound->encrypted()) ||
285 (_main_subtitle && _main_subtitle->encrypted()) ||
287 (_atmos && _atmos->encrypted())
293 Reel::all_encrypted ()
const
296 for (
auto i: _closed_captions) {
297 if (!i->encrypted()) {
303 (!_main_picture || _main_picture->encrypted()) &&
304 (!_main_sound || _main_sound->encrypted()) &&
305 (!_main_subtitle || _main_subtitle->encrypted()) &&
307 (!_atmos || _atmos->encrypted())
315 give_kdm_to_assets (kdm);
320 _kdms.push_back (kdm);
327 for (
auto const& i: kdm.
keys()) {
328 if (_main_picture && i.id() == _main_picture->key_id() && _main_picture->asset_ref().resolved()) {
329 _main_picture->asset()->set_key (i.key());
331 if (_main_sound && i.id() == _main_sound->key_id() && _main_sound->asset_ref().resolved()) {
332 _main_sound->asset()->set_key (i.key());
334 if (_main_subtitle) {
335 auto smpte = dynamic_pointer_cast<ReelSMPTESubtitleAsset>(_main_subtitle);
336 if (smpte && i.id() == smpte->key_id() && smpte->asset_ref().resolved()) {
337 smpte->smpte_asset()->set_key(i.key());
340 for (
auto j: _closed_captions) {
341 auto smpte = dynamic_pointer_cast<ReelSMPTESubtitleAsset>(j);
342 if (smpte && i.id() == smpte->key_id() && smpte->asset_ref().resolved()) {
343 smpte->smpte_asset()->set_key(i.key());
346 if (_atmos && i.id() == _atmos->key_id() && _atmos->asset_ref().resolved()) {
347 _atmos->asset()->set_key (i.key());
354 Reel::add (shared_ptr<ReelAsset> asset)
356 auto p = dynamic_pointer_cast<ReelPictureAsset> (asset);
357 auto so = dynamic_pointer_cast<ReelSoundAsset> (asset);
358 auto su = dynamic_pointer_cast<ReelSubtitleAsset> (asset);
359 auto m = dynamic_pointer_cast<ReelMarkersAsset> (asset);
360 auto c = dynamic_pointer_cast<ReelClosedCaptionAsset> (asset);
361 auto a = dynamic_pointer_cast<ReelAtmosAsset> (asset);
371 _closed_captions.push_back (c);
378 vector<shared_ptr<ReelAsset>>
379 Reel::assets ()
const
381 vector<shared_ptr<ReelAsset>> a;
383 a.push_back (_main_picture);
386 a.push_back (_main_sound);
388 if (_main_subtitle) {
389 a.push_back (_main_subtitle);
391 std::copy (_closed_captions.begin(), _closed_captions.end(), back_inserter(a));
393 a.push_back (_atmos);
400 Reel::resolve_refs (vector<shared_ptr<Asset>> assets)
403 _main_picture->asset_ref().resolve(assets);
407 _main_sound->asset_ref().resolve(assets);
410 if (_main_subtitle) {
411 _main_subtitle->asset_ref().resolve(assets);
414 if (_main_subtitle->asset_ref().resolved()) {
415 auto iop = dynamic_pointer_cast<InteropSubtitleAsset> (_main_subtitle->asset_ref().asset());
417 iop->resolve_fonts (assets);
422 for (
auto i: _closed_captions) {
423 i->asset_ref().resolve(assets);
426 if (i->asset_ref().resolved()) {
427 auto iop = dynamic_pointer_cast<InteropSubtitleAsset> (i->asset_ref().asset());
429 iop->resolve_fonts (assets);
435 _atmos->asset_ref().resolve (assets);
438 for (
auto const& i: _kdms) {
439 give_kdm_to_assets (i);
445 Reel::duration ()
const
448 return _main_picture->actual_duration();
451 int64_t d = INT64_MAX;
454 d = min (d, _main_sound->actual_duration());
456 if (_main_subtitle) {
457 d = min (d, _main_subtitle->actual_duration());
460 d = min (d, _main_markers->actual_duration());
462 for (
auto i: _closed_captions) {
463 d = min (d, i->actual_duration());
466 d = min (d, _atmos->actual_duration());
469 DCP_ASSERT (d < INT64_MAX);
std::vector< DecryptedKDMKey > keys() const
Some part of a DCP that has a UUID.
InteropSubtitleAsset class.
Namespace for everything in libdcp.
ReelClosedCaptionAsset class.
ReelInteropClosedCaptionAsset class.
ReelInteropSubtitleAsset class.
ReelMonoPictureAsset class.
ReelSMPTEClosedCaptionAsset class.
ReelStereoPictureAsset class.
SMPTESubtitleAsset class.
StereoPictureAsset class.
A class to describe what "equality" means for a particular test.
Utility methods and classes.