#include "compose.hpp"
#include "cpl.h"
#include "dcp_assert.h"
+#include "equality_options.h"
+#include "filesystem.h"
#include "local_time.h"
#include "metadata.h"
#include "raw_convert.h"
, _content_kind (ContentKind::FEATURE)
{
cxml::Document f ("CompositionPlaylist");
- f.read_file (file);
+ f.read_file(dcp::filesystem::fix_long_path(file));
if (f.namespace_uri() == cpl_interop_ns) {
_standard = Standard::INTEROP;
void
-CPL::write_xml (boost::filesystem::path file, shared_ptr<const CertificateChain> signer) const
+CPL::write_xml(boost::filesystem::path file, shared_ptr<const CertificateChain> signer, bool include_mca_subdescriptors) const
{
xmlpp::Document doc;
xmlpp::Element* root;
for (auto i: _reels) {
auto asset_list = i->write_to_cpl (reel_list, _standard);
if (first && _standard == Standard::SMPTE) {
- maybe_write_composition_metadata_asset (asset_list);
+ maybe_write_composition_metadata_asset(asset_list, include_mca_subdescriptors);
first = false;
}
}
signer->sign (root, _standard);
}
- doc.write_to_file_formatted (file.string(), "UTF-8");
+ doc.write_to_file_formatted(dcp::filesystem::fix_long_path(file).string(), "UTF-8");
set_file (file);
}
_luminance = Luminance (lum);
}
- _main_sound_configuration = node->optional_string_child("MainSoundConfiguration");
+ if (auto msc = node->optional_string_child("MainSoundConfiguration")) {
+ try {
+ _main_sound_configuration = MainSoundConfiguration(*msc);
+ } catch (MainSoundConfigurationError& e) {
+ /* With Interop DCPs this node may not make any sense, but that's OK */
+ if (_standard == dcp::Standard::SMPTE) {
+ throw e;
+ }
+ }
+ }
auto sr = node->optional_string_child("MainSoundSampleRate");
if (sr) {
}
auto eml = node->optional_node_child ("ExtensionMetadataList");
- if (eml) {
+
+ auto extension_metadata = [eml](string scope, string name, string property) -> boost::optional<std::string> {
+ if (!eml) {
+ return {};
+ }
+
for (auto i: eml->node_children("ExtensionMetadata")) {
- auto name = i->optional_string_child("Name");
- if (name && *name == "Sign Language Video") {
+ auto xml_scope = i->optional_string_attribute("scope");
+ auto xml_name = i->optional_string_child("Name");
+ if (xml_scope && *xml_scope == scope && xml_name && *xml_name == name) {
auto property_list = i->node_child("PropertyList");
for (auto j: property_list->node_children("Property")) {
- auto name = j->optional_string_child("Name");
- auto value = j->optional_string_child("Value");
- if (name && value && *name == "Language Tag") {
- _sign_language_video_language = *value;
+ auto property_name = j->optional_string_child("Name");
+ auto property_value = j->optional_string_child("Value");
+ if (property_name && property_value && *property_name == property) {
+ return property_value;
}
}
}
}
- }
+
+ return {};
+ };
+
+ _sign_language_video_language = extension_metadata("http://isdcf.com/2017/10/SignLanguageVideo", "Sign Language Video", "Language Tag");
+ _dolby_edr_image_transfer_function = extension_metadata("http://www.dolby.com/schemas/2014/EDR-Metadata", "Dolby EDR", "image transfer function");
}
sf->add_child("RFC5646SpokenLanguage", "r1")->add_child_text(buffer);
}
+ /* Find the MCA subdescriptors in the MXF so that we can also write them here */
list<ASDCP::MXF::InterchangeObject*> channels;
auto r = reader->reader()->OP1aHeader().GetMDObjectsByType(
asdcp_smpte_dict->ul(ASDCP::MDD_AudioChannelLabelSubDescriptor),
for (auto i: channels) {
auto channel = reinterpret_cast<ASDCP::MXF::AudioChannelLabelSubDescriptor*>(i);
- if (static_cast<int>(channel->MCAChannelID) > asset->channels()) {
- continue;
- }
auto ch = mca_subs->add_child("AudioChannelLabelSubDescriptor", "r0");
channel->InstanceUID.EncodeString(buffer, sizeof(buffer));
ch->add_child("InstanceID", "r1")->add_child_text("urn:uuid:" + string(buffer));
* is missing this method will do nothing.
*/
void
-CPL::maybe_write_composition_metadata_asset (xmlpp::Element* node) const
+CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_mca_subdescriptors) const
{
if (
!_main_sound_configuration ||
_luminance->as_xml (meta, "meta");
}
- meta->add_child("MainSoundConfiguration", "meta")->add_child_text(*_main_sound_configuration);
+ if (_main_sound_configuration) {
+ meta->add_child("MainSoundConfiguration", "meta")->add_child_text(_main_sound_configuration->to_string());
+ }
meta->add_child("MainSoundSampleRate", "meta")->add_child_text(raw_convert<string>(*_main_sound_sample_rate) + " 1");
auto stored = meta->add_child("MainPictureStoredArea", "meta");
add_extension_metadata ("http://isdcf.com/2017/10/SignLanguageVideo", "Sign Language Video", "Language Tag", *_sign_language_video_language);
}
+ if (_dolby_edr_image_transfer_function) {
+ add_extension_metadata("http://www.dolby.com/schemas/2014/EDR-Metadata", "Dolby EDR", "image transfer function", *_dolby_edr_image_transfer_function);
+ }
+
if (_reels.front()->main_sound()) {
auto asset = _reels.front()->main_sound()->asset();
- if (asset) {
+ if (asset && include_mca_subdescriptors) {
write_mca_subdescriptors(meta, asset);
}
}
bool
-CPL::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const
+CPL::equals(shared_ptr<const Asset> other, EqualityOptions const& opt, NoteHandler note) const
{
auto other_cpl = dynamic_pointer_cast<const CPL>(other);
if (!other_cpl) {