From e40f5c5923d72b42d7b1c617a6e459569d584e8c Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 21 Sep 2020 22:33:43 +0200 Subject: [PATCH] Fix crashes when static linking due to tricky lifetime management of ASDCP::DefaultSMPTEDict(). --- src/cpl.cc | 5 +++-- src/sound_asset.cc | 3 ++- src/sound_asset_writer.cc | 20 +++++++------------- src/util.cc | 11 ++++++++++- src/util.h | 1 + tools/dcpdecryptmxf.cc | 2 ++ tools/dcpdiff.cc | 2 ++ tools/dcpdumpsub.cc | 2 ++ tools/dcpinfo.cc | 2 ++ tools/dcpkdm.cc | 2 ++ tools/dcprecover.cc | 2 ++ tools/dcpthumb.cc | 2 ++ tools/dcpverify.cc | 2 ++ 13 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/cpl.cc b/src/cpl.cc index 711c9e1b..246ca21a 100644 --- a/src/cpl.cc +++ b/src/cpl.cc @@ -72,6 +72,7 @@ static string const mca_sub_descriptors_ns = "http://isdcf.com/ns/cplmd/mca"; static string const smpte_395_ns = "http://www.smpte-ra.org/reg/395/2014/13/1/aaf"; static string const smpte_335_ns = "http://www.smpte-ra.org/reg/335/2012"; + CPL::CPL (string annotation_text, ContentKind content_kind) /* default _content_title_text to annotation_text */ : _issuer ("libdcp" LIBDCP_VERSION) @@ -405,7 +406,7 @@ CPL::maybe_write_composition_metadata_asset (xmlpp::Element* node) const shared_ptr reader = asset->start_read (); ASDCP::MXF::SoundfieldGroupLabelSubDescriptor* soundfield; ASDCP::Result_t r = reader->reader()->OP1aHeader().GetMDObjectByType( - ASDCP::DefaultSMPTEDict().ul(ASDCP::MDD_SoundfieldGroupLabelSubDescriptor), + asdcp_smpte_dict->ul(ASDCP::MDD_SoundfieldGroupLabelSubDescriptor), reinterpret_cast(&soundfield) ); if (KM_SUCCESS(r)) { @@ -434,7 +435,7 @@ CPL::maybe_write_composition_metadata_asset (xmlpp::Element* node) const list channels; ASDCP::Result_t r = reader->reader()->OP1aHeader().GetMDObjectsByType( - ASDCP::DefaultSMPTEDict().ul(ASDCP::MDD_AudioChannelLabelSubDescriptor), + asdcp_smpte_dict->ul(ASDCP::MDD_AudioChannelLabelSubDescriptor), channels ); diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 15626b9a..6752d9b1 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -57,6 +57,7 @@ using boost::shared_ptr; using boost::dynamic_pointer_cast; using namespace dcp; + SoundAsset::SoundAsset (boost::filesystem::path file) : Asset (file) /* XXX: this is a fallback language, which will be used if we can't find the RFC5646SpokenLanguage @@ -89,7 +90,7 @@ SoundAsset::SoundAsset (boost::filesystem::path file) ASDCP::MXF::SoundfieldGroupLabelSubDescriptor* soundfield; ASDCP::Result_t rr = reader.OP1aHeader().GetMDObjectByType( - ASDCP::DefaultSMPTEDict().ul(ASDCP::MDD_SoundfieldGroupLabelSubDescriptor), + asdcp_smpte_dict->ul(ASDCP::MDD_SoundfieldGroupLabelSubDescriptor), reinterpret_cast(&soundfield) ); diff --git a/src/sound_asset_writer.cc b/src/sound_asset_writer.cc index 3980dc62..aaa35116 100644 --- a/src/sound_asset_writer.cc +++ b/src/sound_asset_writer.cc @@ -51,12 +51,6 @@ using std::vector; using namespace dcp; -/* Some ASDCP objects store this as a *&, for reasons which are not - * at all clear, so we have to keep this around forever. - */ -static ASDCP::Dictionary const* smpte_dict = &ASDCP::DefaultSMPTEDict(); - - struct SoundAssetWriter::ASDCPState { ASDCP::PCM::MXFWriter mxf_writer; @@ -124,12 +118,12 @@ SoundAssetWriter::start () ASDCP::MXF::WaveAudioDescriptor* essence_descriptor = 0; _state->mxf_writer.OP1aHeader().GetMDObjectByType( - smpte_dict->ul(ASDCP::MDD_WaveAudioDescriptor), reinterpret_cast(&essence_descriptor) + asdcp_smpte_dict->ul(ASDCP::MDD_WaveAudioDescriptor), reinterpret_cast(&essence_descriptor) ); DCP_ASSERT (essence_descriptor); - essence_descriptor->ChannelAssignment = smpte_dict->ul(ASDCP::MDD_DCAudioChannelCfg_MCA); + essence_descriptor->ChannelAssignment = asdcp_smpte_dict->ul(ASDCP::MDD_DCAudioChannelCfg_MCA); - ASDCP::MXF::SoundfieldGroupLabelSubDescriptor* soundfield = new ASDCP::MXF::SoundfieldGroupLabelSubDescriptor(smpte_dict); + ASDCP::MXF::SoundfieldGroupLabelSubDescriptor* soundfield = new ASDCP::MXF::SoundfieldGroupLabelSubDescriptor(asdcp_smpte_dict); GenRandomValue (soundfield->MCALinkID); soundfield->RFC5646SpokenLanguage = _asset->language().to_string(); @@ -138,25 +132,25 @@ SoundAssetWriter::start () if (field == SEVEN_POINT_ONE) { soundfield->MCATagSymbol = "sg71"; soundfield->MCATagName = "7.1DS"; - soundfield->MCALabelDictionaryID = smpte_dict->ul(ASDCP::MDD_DCAudioSoundfield_71); + soundfield->MCALabelDictionaryID = asdcp_smpte_dict->ul(ASDCP::MDD_DCAudioSoundfield_71); } else { soundfield->MCATagSymbol = "sg51"; soundfield->MCATagName = "5.1"; - soundfield->MCALabelDictionaryID = smpte_dict->ul(ASDCP::MDD_DCAudioSoundfield_51); + soundfield->MCALabelDictionaryID = asdcp_smpte_dict->ul(ASDCP::MDD_DCAudioSoundfield_51); } _state->mxf_writer.OP1aHeader().AddChildObject(soundfield); essence_descriptor->SubDescriptors.push_back(soundfield->InstanceUID); BOOST_FOREACH (Channel i, _active_channels) { - ASDCP::MXF::AudioChannelLabelSubDescriptor* channel = new ASDCP::MXF::AudioChannelLabelSubDescriptor(smpte_dict); + ASDCP::MXF::AudioChannelLabelSubDescriptor* channel = new ASDCP::MXF::AudioChannelLabelSubDescriptor(asdcp_smpte_dict); GenRandomValue (channel->MCALinkID); channel->SoundfieldGroupLinkID = soundfield->MCALinkID; channel->MCAChannelID = static_cast(i) + 1; channel->MCATagSymbol = "ch" + channel_to_mca_id(i, field); channel->MCATagName = channel_to_mca_name(i, field); channel->RFC5646SpokenLanguage = _asset->language().to_string(); - channel->MCALabelDictionaryID = channel_to_mca_universal_label(i, field, smpte_dict); + channel->MCALabelDictionaryID = channel_to_mca_universal_label(i, field, asdcp_smpte_dict); _state->mxf_writer.OP1aHeader().AddChildObject(channel); essence_descriptor->SubDescriptors.push_back(channel->InstanceUID); } diff --git a/src/util.cc b/src/util.cc index c7d090ea..009d5bae 100644 --- a/src/util.cc +++ b/src/util.cc @@ -76,6 +76,13 @@ using boost::function; using boost::algorithm::trim; using namespace dcp; + +/* Some ASDCP objects store this as a *&, for reasons which are not + * at all clear, so we have to keep this around forever. + */ +ASDCP::Dictionary const* dcp::asdcp_smpte_dict = 0; + + /** Create a UUID. * @return UUID. */ @@ -164,7 +171,7 @@ dcp::empty_or_white_space (string s) return true; } -/** Set up various bits that the library needs. Should be called one +/** Set up various bits that the library needs. Should be called once * by client applications. */ void @@ -189,6 +196,8 @@ dcp::init () } OpenSSL_add_all_algorithms(); + + asdcp_smpte_dict = &ASDCP::DefaultSMPTEDict(); } /** Decode a base64 string. The base64 decode routine in KM_util.cpp diff --git a/src/util.h b/src/util.h index a14d7364..959cbbca 100644 --- a/src/util.h +++ b/src/util.h @@ -82,6 +82,7 @@ extern void indent (xmlpp::Element* element, int initial); extern bool day_less_than_or_equal (LocalTime a, LocalTime b); extern bool day_greater_than_or_equal (LocalTime a, LocalTime b); extern std::string unique_string (std::list existing, std::string base); +extern ASDCP::Dictionary const* asdcp_smpte_dict; class ASDCPErrorSuspender diff --git a/tools/dcpdecryptmxf.cc b/tools/dcpdecryptmxf.cc index 34ebf436..a2998697 100644 --- a/tools/dcpdecryptmxf.cc +++ b/tools/dcpdecryptmxf.cc @@ -66,6 +66,8 @@ help (string n) int main (int argc, char* argv[]) { + dcp::init (); + optional output_file; optional kdm_file; optional private_key_file; diff --git a/tools/dcpdiff.cc b/tools/dcpdiff.cc index 976a2919..80d4b049 100644 --- a/tools/dcpdiff.cc +++ b/tools/dcpdiff.cc @@ -119,6 +119,8 @@ load_dcp (boost::filesystem::path path, bool ignore_missing_assets, optional kdm_file; optional private_key_file; diff --git a/tools/dcpinfo.cc b/tools/dcpinfo.cc index 38e43eb1..3afff7f0 100644 --- a/tools/dcpinfo.cc +++ b/tools/dcpinfo.cc @@ -283,6 +283,8 @@ main_subtitle (vector const& only, shared_ptr reel, bool list_subt int main (int argc, char* argv[]) { + dcp::init (); + bool subtitles = false; bool picture = false; bool decompress = false; diff --git a/tools/dcpkdm.cc b/tools/dcpkdm.cc index c34454be..ef889f48 100644 --- a/tools/dcpkdm.cc +++ b/tools/dcpkdm.cc @@ -64,6 +64,8 @@ int main (int argc, char* argv[]) try { + dcp::init (); + optional private_key_file; int option_index = 0; diff --git a/tools/dcprecover.cc b/tools/dcprecover.cc index caf0e0fe..65240ae8 100644 --- a/tools/dcprecover.cc +++ b/tools/dcprecover.cc @@ -65,6 +65,8 @@ void progress (float f) int main (int argc, char* argv[]) { + dcp::init (); + int option_index = 0; optional output; while (true) { diff --git a/tools/dcpthumb.cc b/tools/dcpthumb.cc index 7d90c2ef..2adccfd0 100644 --- a/tools/dcpthumb.cc +++ b/tools/dcpthumb.cc @@ -53,6 +53,8 @@ help (string n) int main (int argc, char* argv[]) { + dcp::init (); + int option_index = 0; while (true) { struct option long_options[] = { diff --git a/tools/dcpverify.cc b/tools/dcpverify.cc index 968c4710..c484516e 100644 --- a/tools/dcpverify.cc +++ b/tools/dcpverify.cc @@ -83,6 +83,8 @@ progress () int main (int argc, char* argv[]) { + dcp::init (); + bool ignore_missing_assets = false; bool quiet = false; -- 2.30.2