summaryrefslogtreecommitdiff
path: root/src/mca_sub_descriptor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mca_sub_descriptor.cc')
-rw-r--r--src/mca_sub_descriptor.cc106
1 files changed, 104 insertions, 2 deletions
diff --git a/src/mca_sub_descriptor.cc b/src/mca_sub_descriptor.cc
index 34bde9f8..a2341f9a 100644
--- a/src/mca_sub_descriptor.cc
+++ b/src/mca_sub_descriptor.cc
@@ -33,14 +33,19 @@
#include "dcp_assert.h"
+#include "main_sound_configuration.h"
#include "mca_sub_descriptor.h"
#include "util.h"
+#include <fmt/format.h>
LIBDCP_DISABLE_WARNINGS
#include <libxml++/libxml++.h>
LIBDCP_ENABLE_WARNINGS
+using std::pair;
using std::string;
+using std::vector;
+using boost::optional;
using namespace dcp;
@@ -48,7 +53,7 @@ MCASubDescriptor::MCASubDescriptor(cxml::ConstNodePtr node)
{
tag = node->name();
instance_id = remove_urn_uuid(node->string_child("InstanceID"));
- mca_label_dictionary_id = node->string_child("MCALabelDictionaryID");
+ mca_label_dictionary_id = remove_urn_smpte_ul(node->string_child("MCALabelDictionaryID"));
mca_link_id = remove_urn_uuid(node->string_child("MCALinkID"));
mca_tag_symbol = node->string_child("MCATagSymbol");
mca_tag_name = node->optional_string_child("MCATagName");
@@ -60,12 +65,20 @@ MCASubDescriptor::MCASubDescriptor(cxml::ConstNodePtr node)
}
+MCASubDescriptor::MCASubDescriptor(std::string tag_)
+ : tag(std::move(tag_))
+ , instance_id(make_uuid())
+{
+
+}
+
+
void
MCASubDescriptor::as_xml(xmlpp::Element* parent) const
{
auto node = cxml::add_child(parent, tag, string("r0"));
cxml::add_child(node, "InstanceID", string("r1"))->add_child_text("urn:uuid:" + instance_id);
- cxml::add_child(node, "MCALabelDictionaryID", string("r1"))->add_child_text(mca_label_dictionary_id);
+ cxml::add_child(node, "MCALabelDictionaryID", string("r1"))->add_child_text("urn:smpte:ul:" + mca_label_dictionary_id);
cxml::add_child(node, "MCALinkID", string("r1"))->add_child_text("urn:uuid:" + mca_link_id);
cxml::add_child(node, "MCATagSymbol", string("r1"))->add_child_text(mca_tag_symbol);
if (mca_tag_name) {
@@ -82,3 +95,92 @@ MCASubDescriptor::as_xml(xmlpp::Element* parent) const
}
}
+
+pair<MCASubDescriptor, vector<MCASubDescriptor>>
+dcp::create_mca_subdescriptors(vector<dcp::Channel> const& extra_active_channels, int total_channels, optional<string> language)
+{
+ /* We always make a descriptor for these channels if they are present in the asset;
+ * there's no way for the caller to tell us whether they are active or not.
+ */
+ std::vector<dcp::Channel> dcp_channels = {
+ Channel::LEFT,
+ Channel::RIGHT,
+ Channel::CENTRE,
+ Channel::LFE,
+ Channel::LS,
+ Channel::RS
+ };
+
+ /* We add descriptors for some extra channels that the caller gave us (we made sure earlier
+ * that nothing "bad" is in this list).
+ */
+ std::copy(extra_active_channels.begin(), extra_active_channels.end(), back_inserter(dcp_channels));
+
+ /* Remove duplicates */
+ std::sort(dcp_channels.begin(), dcp_channels.end());
+ dcp_channels.erase(std::unique(dcp_channels.begin(), dcp_channels.end()), dcp_channels.end());
+
+ /* Remove channels that aren't actually in this MXF at all */
+ dcp_channels.erase(
+ std::remove_if(dcp_channels.begin(), dcp_channels.end(), [total_channels](dcp::Channel channel) {
+ return static_cast<int>(channel) >= total_channels;
+ }),
+ dcp_channels.end()
+ );
+
+ MCASoundField const field =
+ (
+ find(extra_active_channels.begin(), extra_active_channels.end(), dcp::Channel::BSL) != extra_active_channels.end() ||
+ find(extra_active_channels.begin(), extra_active_channels.end(), dcp::Channel::BSR) != extra_active_channels.end()
+ ) ? MCASoundField::SEVEN_POINT_ONE : MCASoundField::FIVE_POINT_ONE;
+
+ auto group = MCASubDescriptor("SoundfieldGroupLabelSubDescriptor");
+ byte_t const* id = nullptr;
+ group.mca_link_id = make_uuid();
+ switch (field) {
+ case MCASoundField::SEVEN_POINT_ONE:
+ id = asdcp_smpte_dict->ul(ASDCP::MDD_DCAudioSoundfield_71);
+ group.mca_tag_symbol = "sg71";
+ group.mca_tag_name = "7.1DS";
+ break;
+ case MCASoundField::FIVE_POINT_ONE:
+ id = asdcp_smpte_dict->ul(ASDCP::MDD_DCAudioSoundfield_51);
+ group.mca_tag_symbol = "sg51";
+ group.mca_tag_name = "5.1";
+ break;
+ case MCASoundField::OTHER:
+ break;
+ }
+
+ if (id) {
+ group.mca_label_dictionary_id = fmt::format(
+ "{:02x}{:02x}{:02x}{:02x}.{:02x}{:02x}{:02x}{:02x}.{:02x}{:02x}{:02x}{:02x}.{:02x}{:02x}{:02x}{:02x}",
+ id[0], id[1], id[2], id[3],
+ id[4], id[5], id[6], id[7],
+ id[8], id[9], id[10], id[11],
+ id[12], id[13], id[14], id[15]
+ );
+ }
+
+ vector<MCASubDescriptor> channels;
+ for (auto dcp_channel: dcp_channels) {
+ auto channel = MCASubDescriptor("AudioChannelLabelSubDescriptor");
+ channel.soundfield_group_link_id = group.mca_link_id;
+ channel.mca_channel_id = fmt::to_string(static_cast<int>(dcp_channel) + 1);
+ channel.mca_tag_symbol = "ch" + channel_to_mca_id(dcp_channel, field);
+ channel.mca_tag_name = channel_to_mca_name(dcp_channel, field);
+ channel.rfc5646_spoken_language = language;
+ auto label = channel_to_mca_universal_label(dcp_channel, field, asdcp_smpte_dict).Value();
+ channel.mca_label_dictionary_id = fmt::format(
+ "{:02x}{:02x}{:02x}{:02x}.{:02x}{:02x}{:02x}{:02x}.{:02x}{:02x}{:02x}{:02x}.{:02x}{:02x}{:02x}{:02x}",
+ label[0], label[1], label[2], label[3],
+ label[4], label[5], label[6], label[7],
+ label[8], label[9], label[10], label[11],
+ label[12], label[13], label[14], label[15]
+ );
+ channels.push_back(channel);
+ }
+
+ return { group, channels };
+}
+