+ /* SMPTE Bv2.1 8.6.3 */
+ auto extension = meta->add_child("ExtensionMetadataList", "meta")->add_child("ExtensionMetadata", "meta");
+ extension->set_attribute("scope", "http://isdcf.com/ns/cplmd/app");
+ extension->add_child("Name", "meta")->add_child_text("Application");
+ auto property = extension->add_child("PropertyList", "meta")->add_child("Property", "meta");
+ property->add_child("Name", "meta")->add_child_text("DCP Constraints Profile");
+ property->add_child("Value", "meta")->add_child_text("SMPTE-RDD-52:2020-Bv2.1");
+
+ if (_reels.front()->main_sound()) {
+ auto asset = _reels.front()->main_sound()->asset();
+ if (asset) {
+ auto reader = asset->start_read ();
+ ASDCP::MXF::SoundfieldGroupLabelSubDescriptor* soundfield;
+ ASDCP::Result_t r = reader->reader()->OP1aHeader().GetMDObjectByType(
+ asdcp_smpte_dict->ul(ASDCP::MDD_SoundfieldGroupLabelSubDescriptor),
+ reinterpret_cast<ASDCP::MXF::InterchangeObject**>(&soundfield)
+ );
+ if (KM_SUCCESS(r)) {
+ auto mca_subs = meta->add_child("mca:MCASubDescriptors");
+ mca_subs->set_namespace_declaration (mca_sub_descriptors_ns, "mca");
+ mca_subs->set_namespace_declaration (smpte_395_ns, "r0");
+ mca_subs->set_namespace_declaration (smpte_335_ns, "r1");
+ auto sf = mca_subs->add_child("SoundfieldGroupLabelSubDescriptor", "r0");
+ char buffer[64];
+ soundfield->InstanceUID.EncodeString(buffer, sizeof(buffer));
+ sf->add_child("InstanceID", "r1")->add_child_text("urn:uuid:" + string(buffer));
+ soundfield->MCALabelDictionaryID.EncodeString(buffer, sizeof(buffer));
+ sf->add_child("MCALabelDictionaryID", "r1")->add_child_text("urn:smpte:ul:" + string(buffer));
+ soundfield->MCALinkID.EncodeString(buffer, sizeof(buffer));
+ sf->add_child("MCALinkID", "r1")->add_child_text("urn:uuid:" + string(buffer));
+ soundfield->MCATagSymbol.EncodeString(buffer, sizeof(buffer));
+ sf->add_child("MCATagSymbol", "r1")->add_child_text(buffer);
+ if (!soundfield->MCATagName.empty()) {
+ soundfield->MCATagName.get().EncodeString(buffer, sizeof(buffer));
+ sf->add_child("MCATagName", "r1")->add_child_text(buffer);
+ }
+ if (!soundfield->RFC5646SpokenLanguage.empty()) {
+ soundfield->RFC5646SpokenLanguage.get().EncodeString(buffer, sizeof(buffer));
+ sf->add_child("RFC5646SpokenLanguage", "r1")->add_child_text(buffer);
+ }
+
+ list<ASDCP::MXF::InterchangeObject*> channels;
+ auto r = reader->reader()->OP1aHeader().GetMDObjectsByType(
+ asdcp_smpte_dict->ul(ASDCP::MDD_AudioChannelLabelSubDescriptor),
+ channels
+ );
+
+ for (auto i: channels) {
+ auto channel = reinterpret_cast<ASDCP::MXF::AudioChannelLabelSubDescriptor*>(i);
+ 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));
+ channel->MCALabelDictionaryID.EncodeString(buffer, sizeof(buffer));
+ ch->add_child("MCALabelDictionaryID", "r1")->add_child_text("urn:smpte:ul:" + string(buffer));
+ channel->MCALinkID.EncodeString(buffer, sizeof(buffer));
+ ch->add_child("MCALinkID", "r1")->add_child_text("urn:uuid:" + string(buffer));
+ channel->MCATagSymbol.EncodeString(buffer, sizeof(buffer));
+ ch->add_child("MCATagSymbol", "r1")->add_child_text(buffer);
+ if (!channel->MCATagName.empty()) {
+ channel->MCATagName.get().EncodeString(buffer, sizeof(buffer));
+ ch->add_child("MCATagName", "r1")->add_child_text(buffer);
+ }
+ if (!channel->MCAChannelID.empty()) {
+ ch->add_child("MCAChannelID", "r1")->add_child_text(raw_convert<string>(channel->MCAChannelID.get()));
+ }
+ if (!channel->RFC5646SpokenLanguage.empty()) {
+ channel->RFC5646SpokenLanguage.get().EncodeString(buffer, sizeof(buffer));
+ ch->add_child("RFC5646SpokenLanguage", "r1")->add_child_text(buffer);
+ }
+ if (!channel->SoundfieldGroupLinkID.empty()) {
+ channel->SoundfieldGroupLinkID.get().EncodeString(buffer, sizeof(buffer));
+ ch->add_child("SoundfieldGroupLinkID", "r1")->add_child_text("urn:uuid:" + string(buffer));
+ }
+ }
+ }
+ }
+ }
+}
+
+
+template <class T>
+void
+add_file_assets (vector<shared_ptr<T>>& assets, vector<shared_ptr<Reel>> reels)
+{
+ for (auto i: reels) {
+ if (i->main_picture ()) {
+ assets.push_back (i->main_picture());
+ }
+ if (i->main_sound ()) {
+ assets.push_back (i->main_sound());
+ }
+ if (i->main_subtitle ()) {
+ assets.push_back (i->main_subtitle());
+ }
+ for (auto j: i->closed_captions()) {
+ assets.push_back (j);
+ }
+ if (i->atmos ()) {
+ assets.push_back (i->atmos());
+ }
+ }
+}
+
+
+vector<shared_ptr<ReelFileAsset>>
+CPL::reel_file_assets ()
+{
+ vector<shared_ptr<ReelFileAsset>> c;
+ add_file_assets (c, _reels);
+ return c;
+}
+
+
+vector<shared_ptr<const ReelFileAsset>>
+CPL::reel_file_assets () const
+{
+ vector<shared_ptr<const ReelFileAsset>> c;
+ add_file_assets (c, _reels);
+ return c;
+}
+
+
+template <class T>
+void
+add_encryptable_assets (vector<shared_ptr<T>>& assets, vector<shared_ptr<Reel>> reels)
+{
+ for (auto i: reels) {
+ if (i->main_picture ()) {
+ assets.push_back (i->main_picture());
+ }
+ if (i->main_sound ()) {
+ assets.push_back (i->main_sound());
+ }
+ if (i->main_subtitle ()) {
+ if (auto enc = dynamic_pointer_cast<ReelEncryptableAsset>(i->main_subtitle())) {
+ assets.push_back (enc);
+ }
+ }
+ for (auto j: i->closed_captions()) {
+ assets.push_back (j);
+ }
+ if (i->atmos ()) {
+ assets.push_back (i->atmos());
+ }
+ }
+}
+
+
+vector<shared_ptr<ReelEncryptableAsset>>
+CPL::reel_encryptable_assets ()
+{
+ vector<shared_ptr<ReelEncryptableAsset>> c;
+ add_encryptable_assets (c, _reels);