diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cpl.h | 1 | ||||
| -rw-r--r-- | src/main_sound_configuration.cc | 305 | ||||
| -rw-r--r-- | src/main_sound_configuration.h | 90 | ||||
| -rw-r--r-- | src/sound_asset_writer.cc | 1 | ||||
| -rw-r--r-- | src/types.cc | 257 | ||||
| -rw-r--r-- | src/types.h | 39 | ||||
| -rw-r--r-- | src/wscript | 2 |
7 files changed, 399 insertions, 296 deletions
@@ -46,6 +46,7 @@ #include "content_kind.h" #include "key.h" #include "language_tag.h" +#include "main_sound_configuration.h" #include "rating.h" #include "verify.h" #include <boost/filesystem.hpp> diff --git a/src/main_sound_configuration.cc b/src/main_sound_configuration.cc new file mode 100644 index 00000000..1a081321 --- /dev/null +++ b/src/main_sound_configuration.cc @@ -0,0 +1,305 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> + + This file is part of libdcp. + + libdcp is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + libdcp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libdcp. If not, see <http://www.gnu.org/licenses/>. + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + + +#include "dcp_assert.h" +#include "exceptions.h" +#include "main_sound_configuration.h" +#include <boost/algorithm/string.hpp> +#include <vector> + + +using std::string; +using std::vector; +using boost::optional; +using namespace dcp; + + + +MainSoundConfiguration::MainSoundConfiguration (string s) +{ + vector<string> parts; + boost::split (parts, s, boost::is_any_of("/")); + if (parts.empty()) { + throw MainSoundConfigurationError(s); + } + + if (parts[0] == "51") { + _field = MCASoundField::FIVE_POINT_ONE; + } else if (parts[0] == "71") { + _field = MCASoundField::SEVEN_POINT_ONE; + } else { + _field = MCASoundField::OTHER; + } + + if (parts.size() < 2) { + /* I think it's OK to just have the sound field descriptor with no channels, though + * to me it's not clear and I might be wrong. + */ + return; + } + + vector<string> channels; + boost::split (channels, parts[1], boost::is_any_of(",")); + + if (channels.size() > 16) { + throw MainSoundConfigurationError (s); + } + + for (auto i: channels) { + if (i == "-") { + _channels.push_back(optional<Channel>()); + } else { + _channels.push_back(mca_id_to_channel(i)); + } + } +} + + +MainSoundConfiguration::MainSoundConfiguration (MCASoundField field, int channels) + : _field (field) +{ + _channels.resize (channels); +} + + +string +MainSoundConfiguration::to_string () const +{ + string c; + switch (_field) { + case MCASoundField::FIVE_POINT_ONE: + c = "51/"; + break; + case MCASoundField::SEVEN_POINT_ONE: + c = "71/"; + break; + default: + DCP_ASSERT(false); + } + + for (auto i: _channels) { + if (!i) { + c += "-,"; + } else { + c += channel_to_mca_id(*i, _field) + ","; + } + } + + if (c.length() > 0) { + c = c.substr(0, c.length() - 1); + } + + return c; +} + + +optional<Channel> +MainSoundConfiguration::mapping (int index) const +{ + DCP_ASSERT (static_cast<size_t>(index) < _channels.size()); + return _channels[index]; +} + + +void +MainSoundConfiguration::set_mapping (int index, Channel c) +{ + DCP_ASSERT (static_cast<size_t>(index) < _channels.size()); + _channels[index] = c; +} + + +Channel +dcp::mca_id_to_channel (string id) +{ + transform(id.begin(), id.end(), id.begin(), ::tolower); + + if (id == "l") { + return Channel::LEFT; + } else if (id == "r") { + return Channel::RIGHT; + } else if (id == "c") { + return Channel::CENTRE; + } else if (id == "lfe") { + return Channel::LFE; + } else if (id == "ls" || id == "lss" || id == "lslss") { + return Channel::LS; + } else if (id == "rs" || id == "rss" || id == "rsrss") { + return Channel::RS; + } else if (id == "hi") { + return Channel::HI; + } else if (id == "vin" || id == "vi-n") { + return Channel::VI; + } else if (id == "lc") { + return Channel::LC; + } else if (id == "rc") { + return Channel::RC; + } else if (id == "lrs" || id == "lsr") { + return Channel::BSL; + } else if (id == "rrs" || id == "rsr") { + return Channel::BSR; + } else if (id == "dbox" || id == "dbox2" || id == "mtn") { + return Channel::MOTION_DATA; + } else if (id == "sync" || id == "fsksync") { + return Channel::SYNC_SIGNAL; + } else if (id == "slvs") { + return Channel::SIGN_LANGUAGE; + } + + throw UnknownChannelIdError (id); +} + + +string +dcp::channel_to_mca_id (Channel c, MCASoundField field) +{ + switch (c) { + case Channel::LEFT: + return "L"; + case Channel::RIGHT: + return "R"; + case Channel::CENTRE: + return "C"; + case Channel::LFE: + return "LFE"; + case Channel::LS: + return field == MCASoundField::FIVE_POINT_ONE ? "Ls" : "Lss"; + case Channel::RS: + return field == MCASoundField::FIVE_POINT_ONE ? "Rs" : "Rss"; + case Channel::HI: + return "HI"; + case Channel::VI: + return "VIN"; + case Channel::BSL: + return "Lrs"; + case Channel::BSR: + return "Rrs"; + case Channel::MOTION_DATA: + return "DBOX"; + case Channel::SYNC_SIGNAL: + return "FSKSync"; + case Channel::SIGN_LANGUAGE: + return "SLVS"; + default: + break; + } + + DCP_ASSERT (false); +} + + +string +dcp::channel_to_mca_name (Channel c, MCASoundField field) +{ + switch (c) { + case Channel::LEFT: + return "Left"; + case Channel::RIGHT: + return "Right"; + case Channel::CENTRE: + return "Center"; + case Channel::LFE: + return "LFE"; + case Channel::LS: + return field == MCASoundField::FIVE_POINT_ONE ? "Left Surround" : "Left Side Surround"; + case Channel::RS: + return field == MCASoundField::FIVE_POINT_ONE ? "Right Surround" : "Right Side Surround"; + case Channel::HI: + return "Hearing Impaired"; + case Channel::VI: + return "Visually Impaired-Narrative"; + case Channel::BSL: + return "Left Rear Surround"; + case Channel::BSR: + return "Right Rear Surround"; + case Channel::MOTION_DATA: + return "D-BOX Motion Code Primary Stream"; + case Channel::SYNC_SIGNAL: + return "FSK Sync"; + case Channel::SIGN_LANGUAGE: + return "Sign Language Video Stream"; + default: + break; + } + + DCP_ASSERT (false); +} + + +ASDCP::UL +dcp::channel_to_mca_universal_label (Channel c, MCASoundField field, ASDCP::Dictionary const* dict) +{ + static byte_t sync_signal[] = { + 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x03, 0x02, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00 + }; + + static byte_t sign_language[] = { + 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x0d, 0x0f, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00 + }; + + switch (c) { + case Channel::LEFT: + return dict->ul(ASDCP::MDD_DCAudioChannel_L); + case Channel::RIGHT: + return dict->ul(ASDCP::MDD_DCAudioChannel_R); + case Channel::CENTRE: + return dict->ul(ASDCP::MDD_DCAudioChannel_C); + case Channel::LFE: + return dict->ul(ASDCP::MDD_DCAudioChannel_LFE); + case Channel::LS: + return dict->ul(field == MCASoundField::FIVE_POINT_ONE ? ASDCP::MDD_DCAudioChannel_Ls : ASDCP::MDD_DCAudioChannel_Lss); + case Channel::RS: + return dict->ul(field == MCASoundField::FIVE_POINT_ONE ? ASDCP::MDD_DCAudioChannel_Rs : ASDCP::MDD_DCAudioChannel_Rss); + case Channel::HI: + return dict->ul(ASDCP::MDD_DCAudioChannel_HI); + case Channel::VI: + return dict->ul(ASDCP::MDD_DCAudioChannel_VIN); + case Channel::BSL: + return dict->ul(ASDCP::MDD_DCAudioChannel_Lrs); + case Channel::BSR: + return dict->ul(ASDCP::MDD_DCAudioChannel_Rrs); + case Channel::MOTION_DATA: + return dict->ul(ASDCP::MDD_DBOXMotionCodePrimaryStream); + case Channel::SYNC_SIGNAL: + return ASDCP::UL(sync_signal); + case Channel::SIGN_LANGUAGE: + return ASDCP::UL(sign_language); + default: + break; + } + + DCP_ASSERT (false); +} + + diff --git a/src/main_sound_configuration.h b/src/main_sound_configuration.h new file mode 100644 index 00000000..d0ddd1f2 --- /dev/null +++ b/src/main_sound_configuration.h @@ -0,0 +1,90 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> + + This file is part of libdcp. + + libdcp is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + libdcp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libdcp. If not, see <http://www.gnu.org/licenses/>. + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + + +#ifndef LIBDCP_MAIN_SOUND_CONFIGURATION_H +#define LIBDCP_MAIN_SOUND_CONFIGURATION_H + +#include "types.h" +#include <string> + + +namespace dcp { + + +enum class MCASoundField +{ + FIVE_POINT_ONE, + SEVEN_POINT_ONE, + OTHER +}; + + +extern std::string channel_to_mca_id (Channel c, MCASoundField field); +extern Channel mca_id_to_channel (std::string); +extern std::string channel_to_mca_name (Channel c, MCASoundField field); +extern ASDCP::UL channel_to_mca_universal_label (Channel c, MCASoundField field, ASDCP::Dictionary const* dict); + + + + +class MainSoundConfiguration +{ +public: + explicit MainSoundConfiguration(std::string); + MainSoundConfiguration (MCASoundField field_, int channels); + + MCASoundField field () const { + return _field; + } + + int channels () const { + return _channels.size(); + } + + boost::optional<Channel> mapping (int index) const; + void set_mapping (int index, Channel channel); + + std::string to_string () const; + +private: + MCASoundField _field; + std::vector<boost::optional<Channel>> _channels; +}; + + +} + + +#endif + diff --git a/src/sound_asset_writer.cc b/src/sound_asset_writer.cc index 3ea2243b..0ebdaa04 100644 --- a/src/sound_asset_writer.cc +++ b/src/sound_asset_writer.cc @@ -43,6 +43,7 @@ #include "dcp_assert.h" #include "exceptions.h" #include "filesystem.h" +#include "main_sound_configuration.h" #include "sound_asset.h" #include "sound_asset_writer.h" #include "warnings.h" diff --git a/src/types.cc b/src/types.cc index a17966b4..bbb66e3a 100644 --- a/src/types.cc +++ b/src/types.cc @@ -410,100 +410,6 @@ dcp::operator== (Luminance const& a, Luminance const& b) } -MainSoundConfiguration::MainSoundConfiguration (string s) -{ - vector<string> parts; - boost::split (parts, s, boost::is_any_of("/")); - if (parts.empty()) { - throw MainSoundConfigurationError(s); - } - - if (parts[0] == "51") { - _field = MCASoundField::FIVE_POINT_ONE; - } else if (parts[0] == "71") { - _field = MCASoundField::SEVEN_POINT_ONE; - } else { - _field = MCASoundField::OTHER; - } - - if (parts.size() < 2) { - /* I think it's OK to just have the sound field descriptor with no channels, though - * to me it's not clear and I might be wrong. - */ - return; - } - - vector<string> channels; - boost::split (channels, parts[1], boost::is_any_of(",")); - - if (channels.size() > 16) { - throw MainSoundConfigurationError (s); - } - - for (auto i: channels) { - if (i == "-") { - _channels.push_back(optional<Channel>()); - } else { - _channels.push_back(mca_id_to_channel(i)); - } - } -} - - -MainSoundConfiguration::MainSoundConfiguration (MCASoundField field, int channels) - : _field (field) -{ - _channels.resize (channels); -} - - -string -MainSoundConfiguration::to_string () const -{ - string c; - switch (_field) { - case MCASoundField::FIVE_POINT_ONE: - c = "51/"; - break; - case MCASoundField::SEVEN_POINT_ONE: - c = "71/"; - break; - default: - DCP_ASSERT(false); - } - - for (auto i: _channels) { - if (!i) { - c += "-,"; - } else { - c += channel_to_mca_id(*i, _field) + ","; - } - } - - if (c.length() > 0) { - c = c.substr(0, c.length() - 1); - } - - return c; -} - - -optional<Channel> -MainSoundConfiguration::mapping (int index) const -{ - DCP_ASSERT (static_cast<size_t>(index) < _channels.size()); - return _channels[index]; -} - - -void -MainSoundConfiguration::set_mapping (int index, Channel c) -{ - DCP_ASSERT (static_cast<size_t>(index) < _channels.size()); - _channels[index] = c; -} - - string dcp::status_to_string (Status s) { @@ -535,169 +441,6 @@ dcp::string_to_status (string s) } -Channel -dcp::mca_id_to_channel (string id) -{ - transform(id.begin(), id.end(), id.begin(), ::tolower); - - if (id == "l") { - return Channel::LEFT; - } else if (id == "r") { - return Channel::RIGHT; - } else if (id == "c") { - return Channel::CENTRE; - } else if (id == "lfe") { - return Channel::LFE; - } else if (id == "ls" || id == "lss" || id == "lslss") { - return Channel::LS; - } else if (id == "rs" || id == "rss" || id == "rsrss") { - return Channel::RS; - } else if (id == "hi") { - return Channel::HI; - } else if (id == "vin" || id == "vi-n") { - return Channel::VI; - } else if (id == "lc") { - return Channel::LC; - } else if (id == "rc") { - return Channel::RC; - } else if (id == "lrs" || id == "lsr") { - return Channel::BSL; - } else if (id == "rrs" || id == "rsr") { - return Channel::BSR; - } else if (id == "dbox" || id == "dbox2" || id == "mtn") { - return Channel::MOTION_DATA; - } else if (id == "sync" || id == "fsksync") { - return Channel::SYNC_SIGNAL; - } else if (id == "slvs") { - return Channel::SIGN_LANGUAGE; - } - - throw UnknownChannelIdError (id); -} - - -string -dcp::channel_to_mca_id (Channel c, MCASoundField field) -{ - switch (c) { - case Channel::LEFT: - return "L"; - case Channel::RIGHT: - return "R"; - case Channel::CENTRE: - return "C"; - case Channel::LFE: - return "LFE"; - case Channel::LS: - return field == MCASoundField::FIVE_POINT_ONE ? "Ls" : "Lss"; - case Channel::RS: - return field == MCASoundField::FIVE_POINT_ONE ? "Rs" : "Rss"; - case Channel::HI: - return "HI"; - case Channel::VI: - return "VIN"; - case Channel::BSL: - return "Lrs"; - case Channel::BSR: - return "Rrs"; - case Channel::MOTION_DATA: - return "DBOX"; - case Channel::SYNC_SIGNAL: - return "FSKSync"; - case Channel::SIGN_LANGUAGE: - return "SLVS"; - default: - break; - } - - DCP_ASSERT (false); -} - - -string -dcp::channel_to_mca_name (Channel c, MCASoundField field) -{ - switch (c) { - case Channel::LEFT: - return "Left"; - case Channel::RIGHT: - return "Right"; - case Channel::CENTRE: - return "Center"; - case Channel::LFE: - return "LFE"; - case Channel::LS: - return field == MCASoundField::FIVE_POINT_ONE ? "Left Surround" : "Left Side Surround"; - case Channel::RS: - return field == MCASoundField::FIVE_POINT_ONE ? "Right Surround" : "Right Side Surround"; - case Channel::HI: - return "Hearing Impaired"; - case Channel::VI: - return "Visually Impaired-Narrative"; - case Channel::BSL: - return "Left Rear Surround"; - case Channel::BSR: - return "Right Rear Surround"; - case Channel::MOTION_DATA: - return "D-BOX Motion Code Primary Stream"; - case Channel::SYNC_SIGNAL: - return "FSK Sync"; - case Channel::SIGN_LANGUAGE: - return "Sign Language Video Stream"; - default: - break; - } - - DCP_ASSERT (false); -} - - -ASDCP::UL -dcp::channel_to_mca_universal_label (Channel c, MCASoundField field, ASDCP::Dictionary const* dict) -{ - static byte_t sync_signal[] = { - 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x03, 0x02, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00 - }; - - static byte_t sign_language[] = { - 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x0d, 0x0f, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00 - }; - - switch (c) { - case Channel::LEFT: - return dict->ul(ASDCP::MDD_DCAudioChannel_L); - case Channel::RIGHT: - return dict->ul(ASDCP::MDD_DCAudioChannel_R); - case Channel::CENTRE: - return dict->ul(ASDCP::MDD_DCAudioChannel_C); - case Channel::LFE: - return dict->ul(ASDCP::MDD_DCAudioChannel_LFE); - case Channel::LS: - return dict->ul(field == MCASoundField::FIVE_POINT_ONE ? ASDCP::MDD_DCAudioChannel_Ls : ASDCP::MDD_DCAudioChannel_Lss); - case Channel::RS: - return dict->ul(field == MCASoundField::FIVE_POINT_ONE ? ASDCP::MDD_DCAudioChannel_Rs : ASDCP::MDD_DCAudioChannel_Rss); - case Channel::HI: - return dict->ul(ASDCP::MDD_DCAudioChannel_HI); - case Channel::VI: - return dict->ul(ASDCP::MDD_DCAudioChannel_VIN); - case Channel::BSL: - return dict->ul(ASDCP::MDD_DCAudioChannel_Lrs); - case Channel::BSR: - return dict->ul(ASDCP::MDD_DCAudioChannel_Rrs); - case Channel::MOTION_DATA: - return dict->ul(ASDCP::MDD_DBOXMotionCodePrimaryStream); - case Channel::SYNC_SIGNAL: - return ASDCP::UL(sync_signal); - case Channel::SIGN_LANGUAGE: - return ASDCP::UL(sign_language); - default: - break; - } - - DCP_ASSERT (false); -} - - vector<dcp::Channel> dcp::used_audio_channels () { diff --git a/src/types.h b/src/types.h index 341236fc..675c0a85 100644 --- a/src/types.h +++ b/src/types.h @@ -114,20 +114,6 @@ enum class Channel { std::vector<dcp::Channel> used_audio_channels (); -enum class MCASoundField -{ - FIVE_POINT_ONE, - SEVEN_POINT_ONE, - OTHER -}; - - -extern std::string channel_to_mca_id (Channel c, MCASoundField field); -extern Channel mca_id_to_channel (std::string); -extern std::string channel_to_mca_name (Channel c, MCASoundField field); -extern ASDCP::UL channel_to_mca_universal_label (Channel c, MCASoundField field, ASDCP::Dictionary const* dict); - - enum class Effect { NONE, @@ -377,31 +363,6 @@ private: bool operator== (Luminance const& a, Luminance const& b); -class MainSoundConfiguration -{ -public: - explicit MainSoundConfiguration(std::string); - MainSoundConfiguration (MCASoundField field_, int channels); - - MCASoundField field () const { - return _field; - } - - int channels () const { - return _channels.size(); - } - - boost::optional<Channel> mapping (int index) const; - void set_mapping (int index, Channel channel); - - std::string to_string () const; - -private: - MCASoundField _field; - std::vector<boost::optional<Channel>> _channels; -}; - - } diff --git a/src/wscript b/src/wscript index 576ca748..8c6ae134 100644 --- a/src/wscript +++ b/src/wscript @@ -73,6 +73,7 @@ def build(bld): language_tag.cc local_time.cc locale_convert.cc + main_sound_configuration.cc metadata.cc modified_gamma_transfer_function.cc mono_j2k_picture_asset.cc @@ -184,6 +185,7 @@ def build(bld): load_font_node.h local_time.h locale_convert.h + main_sound_configuration.h metadata.h mpeg2_picture_asset_writer.h modified_gamma_transfer_function.h |
