diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-12-16 17:45:46 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-12-18 01:10:32 +0100 |
| commit | c3c127e0bdb988696d16f47ea8080df3eff38420 (patch) | |
| tree | ecdff8d299152eef491f1946e6ccb4f6d9cf8e71 | |
| parent | 45ed3bf55175a8555123b320b366efb69b1ba629 (diff) | |
Add can_be_read() to ReelFileAsset and subclasses.
29 files changed, 577 insertions, 3 deletions
diff --git a/src/atmos_asset.cc b/src/atmos_asset.cc index 09a22c1e..9c4b1c80 100644 --- a/src/atmos_asset.cc +++ b/src/atmos_asset.cc @@ -122,3 +122,25 @@ AtmosAsset::start_write (boost::filesystem::path file) /* Can't use make_shared here since the constructor is protected */ return shared_ptr<AtmosAssetWriter>(new AtmosAssetWriter(this, file)); } + + +bool +AtmosAsset::can_be_read() const +{ + if (!MXF::can_be_read()) { + return false; + } + + try { + auto reader = start_read(); + reader->set_check_hmac(false); + reader->get_frame(0); + } catch (dcp::ReadError&) { + return false; + } catch (dcp::MiscError&) { + return false; + } + + return true; +} + diff --git a/src/atmos_asset.h b/src/atmos_asset.h index a682ae60..9fcd359f 100644 --- a/src/atmos_asset.h +++ b/src/atmos_asset.h @@ -61,6 +61,8 @@ public: AtmosAsset (Fraction edit_rate, int first_frame, int max_channel_count, int max_object_count, int atmos_version); explicit AtmosAsset (boost::filesystem::path file); + bool can_be_read() const override; + std::shared_ptr<AtmosAssetWriter> start_write (boost::filesystem::path file); std::shared_ptr<AtmosAssetReader> start_read () const; diff --git a/src/mono_j2k_picture_asset.cc b/src/mono_j2k_picture_asset.cc index b1f311d6..4a8a3219 100644 --- a/src/mono_j2k_picture_asset.cc +++ b/src/mono_j2k_picture_asset.cc @@ -207,3 +207,25 @@ MonoJ2KPictureAsset::cpl_node_name () const { return "MainPicture"; } + + +bool +MonoJ2KPictureAsset::can_be_read() const +{ + if (!MXF::can_be_read()) { + return false; + } + + try { + auto reader = start_read(); + reader->set_check_hmac(false); + reader->get_frame(0)->xyz_image(); + } catch (dcp::ReadError&) { + return false; + } catch (dcp::MiscError&) { + return false; + } + + return true; +} + diff --git a/src/mono_j2k_picture_asset.h b/src/mono_j2k_picture_asset.h index d716b8ff..f790e543 100644 --- a/src/mono_j2k_picture_asset.h +++ b/src/mono_j2k_picture_asset.h @@ -68,6 +68,8 @@ public: */ MonoJ2KPictureAsset(Fraction edit_rate, Standard standard); + bool can_be_read() const override; + /** Start a progressive write to a MonoJ2KPictureAsset. * @path file File to write to. * @path behaviour OVERWRITE_EXISTING to overwrite and potentially add to an existing file diff --git a/src/mono_mpeg2_picture_asset.cc b/src/mono_mpeg2_picture_asset.cc index 380da0fe..9a879f0b 100644 --- a/src/mono_mpeg2_picture_asset.cc +++ b/src/mono_mpeg2_picture_asset.cc @@ -36,6 +36,7 @@ #include "mono_mpeg2_picture_asset.h" #include "mono_mpeg2_picture_asset_reader.h" #include "mono_mpeg2_picture_asset_writer.h" +#include "mpeg2_transcode.h" #include <asdcp/AS_DCP.h> @@ -84,3 +85,26 @@ MonoMPEG2PictureAsset::start_write(boost::filesystem::path file, Behaviour behav /* Can't use make_shared here as the MonoJ2KPictureAssetWriter constructor is private */ return shared_ptr<MonoMPEG2PictureAssetWriter>(new MonoMPEG2PictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING)); } + + +bool +MonoMPEG2PictureAsset::can_be_read() const +{ + if (!MXF::can_be_read()) { + return false; + } + + try { + auto reader = start_read(); + reader->set_check_hmac(false); + dcp::MPEG2Decompressor decompressor; + decompressor.decompress_frame(reader->get_frame(0)); + } catch (dcp::ReadError&) { + return false; + } catch (dcp::MiscError&) { + return false; + } + + return true; +} + diff --git a/src/mono_mpeg2_picture_asset.h b/src/mono_mpeg2_picture_asset.h index 8ef3653e..dc2637e7 100644 --- a/src/mono_mpeg2_picture_asset.h +++ b/src/mono_mpeg2_picture_asset.h @@ -61,6 +61,8 @@ public: explicit MonoMPEG2PictureAsset(boost::filesystem::path file); + bool can_be_read() const override; + std::shared_ptr<MPEG2PictureAssetWriter> start_write(boost::filesystem::path file, Behaviour behaviour) override; std::shared_ptr<MonoMPEG2PictureAssetReader> start_read() const; }; @@ -146,3 +146,10 @@ MXF::read_writer_info (ASDCP::WriterInfo const & info) Kumu::bin2UUIDhex (info.AssetUUID, ASDCP::UUIDlen, buffer, sizeof (buffer)); return buffer; } + + +bool +MXF::can_be_read() const +{ + return !encrypted() || key(); +} @@ -76,6 +76,8 @@ public: MXF (Standard standard); virtual ~MXF () {} + virtual bool can_be_read() const; + /** @return true if the data is encrypted */ bool encrypted () const { return static_cast<bool>(_key_id); diff --git a/src/reel_atmos_asset.cc b/src/reel_atmos_asset.cc index fcecb548..ae7be33a 100644 --- a/src/reel_atmos_asset.cc +++ b/src/reel_atmos_asset.cc @@ -104,3 +104,15 @@ ReelAtmosAsset::equals(shared_ptr<const ReelAtmosAsset> other, EqualityOptions c return true; } + + +bool +ReelAtmosAsset::can_be_read() const +{ + if (!ReelFileAsset::can_be_read()) { + return false; + } + + return asset()->can_be_read(); +} + diff --git a/src/reel_atmos_asset.h b/src/reel_atmos_asset.h index ab18d1ab..ed525bae 100644 --- a/src/reel_atmos_asset.h +++ b/src/reel_atmos_asset.h @@ -60,6 +60,8 @@ public: ReelAtmosAsset (std::shared_ptr<AtmosAsset> asset, int64_t entry_point); explicit ReelAtmosAsset (std::shared_ptr<const cxml::Node>); + bool can_be_read() const override; + std::shared_ptr<const AtmosAsset> asset () const { return asset_of_type<const AtmosAsset>(); } diff --git a/src/reel_file_asset.cc b/src/reel_file_asset.cc index 8fed8012..ad534ebd 100644 --- a/src/reel_file_asset.cc +++ b/src/reel_file_asset.cc @@ -107,3 +107,10 @@ ReelFileAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const return asset; } + +bool +ReelFileAsset::can_be_read() const +{ + return asset_ref().resolved(); +} + diff --git a/src/reel_file_asset.h b/src/reel_file_asset.h index 48fdf215..2412ac2b 100644 --- a/src/reel_file_asset.h +++ b/src/reel_file_asset.h @@ -57,6 +57,7 @@ public: explicit ReelFileAsset (std::shared_ptr<const cxml::Node> node); virtual xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const override; + virtual bool can_be_read() const; /** @return a Ref to our actual asset */ Ref const & asset_ref () const { diff --git a/src/reel_mono_picture_asset.cc b/src/reel_mono_picture_asset.cc index 5dbf85d2..9cbeb7e1 100644 --- a/src/reel_mono_picture_asset.cc +++ b/src/reel_mono_picture_asset.cc @@ -42,8 +42,9 @@ #include <libcxml/cxml.h> -using std::string; +using std::dynamic_pointer_cast; using std::shared_ptr; +using std::string; using namespace dcp; @@ -66,3 +67,14 @@ ReelMonoPictureAsset::cpl_node_name() const { return "MainPicture"; } + + +bool +ReelMonoPictureAsset::can_be_read() const +{ + if (!ReelFileAsset::can_be_read()) { + return false; + } + + return asset()->can_be_read(); +} diff --git a/src/reel_mono_picture_asset.h b/src/reel_mono_picture_asset.h index 0c468e0e..29df2d14 100644 --- a/src/reel_mono_picture_asset.h +++ b/src/reel_mono_picture_asset.h @@ -61,6 +61,8 @@ public: ReelMonoPictureAsset(std::shared_ptr<PictureAsset> asset, int64_t entry_point); explicit ReelMonoPictureAsset (std::shared_ptr<const cxml::Node>); + bool can_be_read() const override; + /** @return the MonoJ2KPictureAsset that this object refers to, if applicable */ std::shared_ptr<const MonoJ2KPictureAsset> mono_j2k_asset() const { return asset_of_type<const MonoJ2KPictureAsset>(); diff --git a/src/reel_smpte_text_asset.cc b/src/reel_smpte_text_asset.cc index b1ce34cb..30a4d443 100644 --- a/src/reel_smpte_text_asset.cc +++ b/src/reel_smpte_text_asset.cc @@ -116,3 +116,14 @@ ReelSMPTETextAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const } + +bool +ReelSMPTETextAsset::can_be_read() const +{ + if (!ReelFileAsset::can_be_read()) { + return false; + } + + return smpte_asset()->can_be_read(); +} + diff --git a/src/reel_smpte_text_asset.h b/src/reel_smpte_text_asset.h index b3c2f655..68459c30 100644 --- a/src/reel_smpte_text_asset.h +++ b/src/reel_smpte_text_asset.h @@ -56,6 +56,8 @@ public: ReelSMPTETextAsset(TextType type, std::shared_ptr<SMPTETextAsset> asset, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point); explicit ReelSMPTETextAsset(std::shared_ptr<const cxml::Node>); + bool can_be_read() const override; + std::shared_ptr<const SMPTETextAsset> smpte_asset() const { return asset_of_type<const SMPTETextAsset>(); } diff --git a/src/reel_sound_asset.cc b/src/reel_sound_asset.cc index dbac6cb3..3c11f666 100644 --- a/src/reel_sound_asset.cc +++ b/src/reel_sound_asset.cc @@ -93,3 +93,15 @@ ReelSoundAsset::equals(shared_ptr<const ReelSoundAsset> other, EqualityOptions c return true; } + + +bool +ReelSoundAsset::can_be_read() const +{ + if (!ReelFileAsset::can_be_read()) { + return false; + } + + return asset()->can_be_read(); +} + diff --git a/src/reel_sound_asset.h b/src/reel_sound_asset.h index 6537ab5c..ac157bdb 100644 --- a/src/reel_sound_asset.h +++ b/src/reel_sound_asset.h @@ -55,6 +55,8 @@ public: ReelSoundAsset (std::shared_ptr<dcp::SoundAsset> content, int64_t entry_point); explicit ReelSoundAsset (std::shared_ptr<const cxml::Node>); + bool can_be_read() const override; + /** @return the SoundAsset that this object refers to */ std::shared_ptr<const SoundAsset> asset () const { return asset_of_type<const SoundAsset>(); diff --git a/src/reel_stereo_picture_asset.cc b/src/reel_stereo_picture_asset.cc index 2ee452d9..53abb8d6 100644 --- a/src/reel_stereo_picture_asset.cc +++ b/src/reel_stereo_picture_asset.cc @@ -42,10 +42,11 @@ #include <libcxml/cxml.h> -using std::string; -using std::pair; +using std::dynamic_pointer_cast; using std::make_pair; +using std::pair; using std::shared_ptr; +using std::string; using namespace dcp; @@ -82,3 +83,15 @@ ReelStereoPictureAsset::cpl_node_attribute (Standard standard) const DCP_ASSERT (false); } + + +bool +ReelStereoPictureAsset::can_be_read() const +{ + if (!ReelFileAsset::can_be_read()) { + return false; + } + + return asset()->can_be_read(); +} + diff --git a/src/reel_stereo_picture_asset.h b/src/reel_stereo_picture_asset.h index 0dd726a4..9e5b30cf 100644 --- a/src/reel_stereo_picture_asset.h +++ b/src/reel_stereo_picture_asset.h @@ -60,6 +60,8 @@ public: ReelStereoPictureAsset (std::shared_ptr<StereoJ2KPictureAsset> content, int64_t entry_point); explicit ReelStereoPictureAsset (std::shared_ptr<const cxml::Node>); + bool can_be_read() const override; + /** @return the StereoJ2KPictureAsset that this object refers to */ std::shared_ptr<const StereoJ2KPictureAsset> stereo_asset () const { return asset_of_type<const StereoJ2KPictureAsset>(); diff --git a/src/smpte_text_asset.cc b/src/smpte_text_asset.cc index 63e8c8ab..84624171 100644 --- a/src/smpte_text_asset.cc +++ b/src/smpte_text_asset.cc @@ -615,3 +615,24 @@ SMPTETextAsset::schema_namespace() const DCP_ASSERT(false); } + + + +bool +SMPTETextAsset::can_be_read() const +{ + if (!MXF::can_be_read()) { + return false; + } + + try { + texts(); + } catch (dcp::ReadError&) { + return false; + } catch (dcp::MiscError&) { + return false; + } + + return true; +} + diff --git a/src/smpte_text_asset.h b/src/smpte_text_asset.h index 6a08ffe4..9b7f09a6 100644 --- a/src/smpte_text_asset.h +++ b/src/smpte_text_asset.h @@ -82,6 +82,8 @@ public: */ explicit SMPTETextAsset(boost::filesystem::path file); + bool can_be_read() const override; + bool equals ( std::shared_ptr<const Asset>, EqualityOptions const&, diff --git a/src/sound_asset.cc b/src/sound_asset.cc index f671a58a..614f6165 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -294,3 +294,24 @@ SoundAsset::active_channels() const return _active_channels.get_value_or(_channels); } + +bool +SoundAsset::can_be_read() const +{ + if (!MXF::can_be_read()) { + return false; + } + + try { + auto reader = start_read(); + reader->set_check_hmac(false); + reader->get_frame(0); + } catch (dcp::ReadError&) { + return false; + } catch (dcp::MiscError&) { + return false; + } + + return true; +} + diff --git a/src/sound_asset.h b/src/sound_asset.h index e5acb119..64bc0a03 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -84,6 +84,8 @@ public: DISABLED }; + bool can_be_read() const override; + /** @param extra_active_channels list of channels that are active in the asset, other than the basic 5.1 * which are assumed always to be active. */ diff --git a/src/stereo_j2k_picture_asset.cc b/src/stereo_j2k_picture_asset.cc index 6a5e7d79..d403ed41 100644 --- a/src/stereo_j2k_picture_asset.cc +++ b/src/stereo_j2k_picture_asset.cc @@ -181,3 +181,25 @@ StereoJ2KPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions con return result; } + + +bool +StereoJ2KPictureAsset::can_be_read() const +{ + if (!MXF::can_be_read()) { + return false; + } + + try { + auto reader = start_read(); + reader->set_check_hmac(false); + reader->get_frame(0)->xyz_image(Eye::LEFT); + } catch (dcp::ReadError&) { + return false; + } catch (dcp::MiscError&) { + return false; + } + + return true; +} + diff --git a/src/stereo_j2k_picture_asset.h b/src/stereo_j2k_picture_asset.h index 7ef86ec5..6c870d59 100644 --- a/src/stereo_j2k_picture_asset.h +++ b/src/stereo_j2k_picture_asset.h @@ -57,6 +57,8 @@ public: explicit StereoJ2KPictureAsset (boost::filesystem::path file); explicit StereoJ2KPictureAsset (Fraction edit_rate, Standard standard); + bool can_be_read() const override; + /** Start a progressive write to a StereoJ2KPictureAsset */ std::shared_ptr<J2KPictureAssetWriter> start_write(boost::filesystem::path file, Behaviour behaviour) override; std::shared_ptr<StereoJ2KPictureAssetReader> start_read () const; diff --git a/test/can_be_read_test.cc b/test/can_be_read_test.cc new file mode 100644 index 00000000..76615b24 --- /dev/null +++ b/test/can_be_read_test.cc @@ -0,0 +1,152 @@ +/* + Copyright (C) 2025 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 "encrypted_kdm.h" +#include "mono_j2k_picture_asset.h" +#include "reel_atmos_asset.h" +#include "reel_mono_picture_asset.h" +#include "reel_sound_asset.h" +#include "reel_text_asset.h" +#include <libcxml/cxml.h> +#include <boost/test/unit_test.hpp> +#include "test.h" + + +using std::function; +using std::shared_ptr; + + +BOOST_AUTO_TEST_CASE(can_be_read_in_reel_mono_picture_asset_unencrypted) +{ + cxml::Document doc("Dummy"); + doc.read_string( + "<Dummy>" + "<MainPicture>" + "<Id>urn:uuid:5407b210-4441-4e97-8b16-8bdc7c12da54</Id>" + "<EditRate>25 1</EditRate>" + "<IntrinsicDuration>2508</IntrinsicDuration>" + "<EntryPoint>225</EntryPoint>" + "<Duration>2283</Duration>" + "<Hash>hcE3Lb8IEDIre9qXNEt64Z5RcNw=</Hash>" + "<FrameRate>25 1</FrameRate>" + "<ScreenAspectRatio>1998 1080</ScreenAspectRatio>" + "</MainPicture>" + "</Dummy>" + ); + + dcp::ReelMonoPictureAsset reel_asset(doc.node_child("MainPicture")); + + /* Unresolved */ + BOOST_CHECK(!reel_asset.can_be_read()); + + auto asset = std::make_shared<dcp::MonoJ2KPictureAsset>("test/data/DCP/video.mxf"); + reel_asset.asset_ref().resolve({asset}); + + /* Resolved */ + BOOST_CHECK(reel_asset.can_be_read()); +} + + +BOOST_AUTO_TEST_CASE(can_be_read_in_reel_sound_asset_unencrypted) +{ + cxml::Document doc("Dummy"); + doc.read_string( + "<Dummy>" + "<MainSound>" + "<Id>urn:uuid:97f0f352-5b77-48ee-a558-9df37717f4fa</Id>" + "<EditRate>25 1</EditRate>" + "<IntrinsicDuration>2508</IntrinsicDuration>" + "<EntryPoint>225</EntryPoint>" + "<Duration>2283</Duration>" + "<Hash>hcE3Lb8IEDIre9qXNEt64Z5RcNw=</Hash>" + "</MainSound>" + "</Dummy>" + ); + + dcp::ReelSoundAsset reel_asset(doc.node_child("MainSound")); + + /* Unresolved */ + BOOST_CHECK(!reel_asset.can_be_read()); + + auto asset = std::make_shared<dcp::SoundAsset>("test/data/DCP/audio.mxf"); + reel_asset.asset_ref().resolve({asset}); + + /* Resolved */ + BOOST_CHECK(reel_asset.can_be_read()); +} + + +static void +can_be_read_in_reel_encrypted_one(function<shared_ptr<dcp::ReelFileAsset> (shared_ptr<const dcp::Reel>)> get_asset) +{ + auto dcp = dcp::DCP(private_test / "data" / "encrypted_dcp_with_subs_and_atmos"); + dcp.read(); + + BOOST_REQUIRE_EQUAL(dcp.cpls().size(), 1U); + BOOST_REQUIRE_EQUAL(dcp.cpls()[0]->reels().size(), 1U); + auto reel_asset = get_asset(dcp.cpls()[0]->reels()[0]); + + /* Encrypted */ + BOOST_CHECK(!reel_asset->can_be_read()); + + dcp::DecryptedKDM wrong_kdm( + dcp::EncryptedKDM( + dcp::file_to_string("test/data/other_kdm.xml") + ), + dcp::file_to_string("test/data/private.key") + ); + dcp.add(wrong_kdm); + + /* Wrong KDM */ + BOOST_CHECK(!reel_asset->can_be_read()); + + dcp::DecryptedKDM right_kdm( + dcp::EncryptedKDM(dcp::file_to_string(private_test / "encrypted_dcp_with_subs_and_atmos.xml")), + dcp::file_to_string("test/data/private.key") + ); + dcp.add(right_kdm); + + /* Right KDM */ + BOOST_CHECK(reel_asset->can_be_read()); +} + + +BOOST_AUTO_TEST_CASE(can_be_read_in_reel_encrypted) +{ + can_be_read_in_reel_encrypted_one([](shared_ptr<const dcp::Reel> reel) { return reel->main_picture(); }); + can_be_read_in_reel_encrypted_one([](shared_ptr<const dcp::Reel> reel) { return reel->main_sound(); }); + can_be_read_in_reel_encrypted_one([](shared_ptr<const dcp::Reel> reel) { return reel->main_subtitle(); }); + can_be_read_in_reel_encrypted_one([](shared_ptr<const dcp::Reel> reel) { return reel->atmos(); }); +} + diff --git a/test/data/other_kdm.xml b/test/data/other_kdm.xml new file mode 100644 index 00000000..d7b2a22f --- /dev/null +++ b/test/data/other_kdm.xml @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="UTF-8"?> +<DCinemaSecurityMessage xmlns="http://www.smpte-ra.org/schemas/430-3/2006/ETM" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:enc="http://www.w3.org/2001/04/xmlenc#"> + <AuthenticatedPublic Id="ID_AuthenticatedPublic"> + <MessageId>urn:uuid:30b00f08-6fcf-414a-8924-831fd4daf05d</MessageId> + <MessageType>http://www.smpte-ra.org/430-1/2006/KDM#kdm-key-type</MessageType> + <AnnotationText>Test_FTR-1_F-133_EN-XX_MOS_2K_20251217_SMPTE_OV</AnnotationText> + <IssueDate>2025-12-17T23:46:43+01:00</IssueDate> + <Signer> + <ds:X509IssuerName>dnQualifier=63rNM95i2Qy0MmrcDFMXewtrA\+c=,CN=.dcpomatic.smpte-430-2.INTERMEDIATE,OU=dcpomatic.com,O=dcpomatic.com</ds:X509IssuerName> + <ds:X509SerialNumber>7</ds:X509SerialNumber> + </Signer> + <RequiredExtensions> + <KDMRequiredExtensions xmlns="http://www.smpte-ra.org/schemas/430-1/2006/KDM"> + <Recipient> + <X509IssuerSerial> + <ds:X509IssuerName>dnQualifier=enjbKYhZ9JszBVjy71Lg9QrYmV4=,CN=.smpte-430-2.INTERMEDIATE.NOT_FOR_PRODUCTION,OU=example.org,O=example.org</ds:X509IssuerName> + <ds:X509SerialNumber>7</ds:X509SerialNumber> + </X509IssuerSerial> + <X509SubjectName>dnQualifier=MekIXGBkYdh28siMnnF/Zs2JeK8=,CN=CS.smpte-430-2.LEAF.NOT_FOR_PRODUCTION,OU=example.org,O=example.org</X509SubjectName> + </Recipient> + <CompositionPlaylistId>urn:uuid:67334526-342c-475d-bb64-d8fd8318f954</CompositionPlaylistId> + <ContentTitleText>Test_FTR-1_F-133_EN-XX_MOS_2K_20251217_SMPTE_OV</ContentTitleText> + <ContentKeysNotValidBefore>2018-04-17T17:46:18+00:00</ContentKeysNotValidBefore> + <ContentKeysNotValidAfter>2028-04-10T17:46:18+00:00</ContentKeysNotValidAfter> + <AuthorizedDeviceInfo> + <DeviceListIdentifier>urn:uuid:bf5b481b-1516-40f2-ba6c-4eca275083bc</DeviceListIdentifier> + <DeviceListDescription>smpte-430-2.LEAF.NOT_FOR_PRODUCTION</DeviceListDescription> + <DeviceList> + <CertificateThumbprint>2jmj7l5rSw0yVb/vlWAYkK/YBwk=</CertificateThumbprint> + </DeviceList> + </AuthorizedDeviceInfo> + <KeyIdList> + <TypedKeyId> + <KeyType scope="http://www.smpte-ra.org/430-1/2006/KDM#kdm-key-type">MDIK</KeyType> + <KeyId>urn:uuid:8380c321-7412-405b-a725-e9251f2de4a5</KeyId> + </TypedKeyId> + <TypedKeyId> + <KeyType scope="http://www.smpte-ra.org/430-1/2006/KDM#kdm-key-type">MDAK</KeyType> + <KeyId>urn:uuid:79d60a9e-382f-4fc0-963f-5d643cd8fa7d</KeyId> + </TypedKeyId> + </KeyIdList> + <ForensicMarkFlagList> + <ForensicMarkFlag>http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-picture-disable</ForensicMarkFlag> + <ForensicMarkFlag>http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-audio-disable</ForensicMarkFlag> + </ForensicMarkFlagList> + </KDMRequiredExtensions> + </RequiredExtensions> + <NonCriticalExtensions/> + </AuthenticatedPublic> + <AuthenticatedPrivate Id="ID_AuthenticatedPrivate"> + <enc:EncryptedKey xmlns:enc="http://www.w3.org/2001/04/xmlenc#"> + <enc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"> + <ds:DigestMethod xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + </enc:EncryptionMethod> + <enc:CipherData> + <enc:CipherValue>LJE29EIGAw9gJ8s+jGuBuIn6Sh/lbVo75bWbiD1ejoIafXHHigRLbjlnIaNtJZeY +SqpAWjDk5hCq0wouwu16xub1dCkUCHiKyWpnuaHG+hpInyn+2kAHdrwTp1yIZ1yO +wnIBwljlnyuqjrFs/CZCpc+LfBxDdRwKkY287XlikGtsFlt2zf97ETAfJBtttumE +biZe7+DW+He1sgOdu8Oljcxn1NqOpzn4cIeZMQ/JSoucmuVFpB1PvXG9qlQAoeSH +iBfQXopF1HQsAuAQIvuDdtSISzAslLTu3epg95hR60QYyOjL0zljpkl9pK+Y8ubJ +cfrGVP7OBgLv2Wxop02CYA==</enc:CipherValue> + </enc:CipherData> + </enc:EncryptedKey> + <enc:EncryptedKey xmlns:enc="http://www.w3.org/2001/04/xmlenc#"> + <enc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"> + <ds:DigestMethod xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + </enc:EncryptionMethod> + <enc:CipherData> + <enc:CipherValue>H7zg5PJxKCINheJo9uEdxS7FIayhO0OsKmOgcud9kEFWT39Z3l/IPsdEdenLH+4E +dU6wo8UmW2MsC+o9DvNVVedUPialaE2GxUEifXstB47U513tQth00OCogWXFmsv4 +KlMGk9pvhlUBz9XcykXfWYuFa7uYDGrtuFWvWZbqLAQ4vAnl16Gms2NzCDZgbVzI +6dhI5U6maGWPRl3KFKiTiPahOHciI56B+lgxDUzGfOThzPrYGYHRBpYOt7f4hPIu +N8UuSHxsT2fZGjWeYjOX0IRU0zeUkt7oZmzJ5ZfYByp+YQGjIFzczmuDca44/DtV +2QZhSQ4EpYRPPPzaS32hOw==</enc:CipherValue> + </enc:CipherData> + </enc:EncryptedKey> + </AuthenticatedPrivate> + <ds:Signature> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#ID_AuthenticatedPublic"> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>HaW+lb5HQwllprsijEzwKyBd/XSI5Bnbh20hpu9syC8=</ds:DigestValue> + </ds:Reference> + <ds:Reference URI="#ID_AuthenticatedPrivate"> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>1IDrybztmDAN1aweduNBecVn2sohLHdvrXnlbyG/AkY=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>UvRcABlbB+dyRFiaiYl3p6bbU2DOD+brzKeX2ky1eRcEyYQhhDbOD5GlHj+yyjXm +LZXaOY392T9QIS0Qq92KxD4XWmFnzeX+q/KdaQtFYzHtQxINRjhfD6CdXLIBg/O3 +zc+s0jUaneLAo3ZEI1v+dxinglLAB1CVdZMhOOYNK1Kk3oE9X+YQFSumhUmBGHnA +IdGAQnVEem+qMoFUuEt+emtqnvzdwuv2Xw2xB/f4LqMA3nBRt/Zkn6sqKZ8QwphM +nnCQlY35/CJdzX7BcCi/agU1hai9Q4UHmDcwwk4+PYL0BQYFQjTssv9R2fht2EBn +zT4uAQ37egPSTEulTc0llw==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509IssuerSerial> + <ds:X509IssuerName>dnQualifier=63rNM95i2Qy0MmrcDFMXewtrA\+c=,CN=.dcpomatic.smpte-430-2.INTERMEDIATE,OU=dcpomatic.com,O=dcpomatic.com</ds:X509IssuerName> + <ds:X509SerialNumber>7</ds:X509SerialNumber> + </ds:X509IssuerSerial> + <ds:X509Certificate>MIIEaTCCA1GgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBhTEWMBQGA1UEChMNZGNw +b21hdGljLmNvbTEWMBQGA1UECxMNZGNwb21hdGljLmNvbTEsMCoGA1UEAxMjLmRj +cG9tYXRpYy5zbXB0ZS00MzAtMi5JTlRFUk1FRElBVEUxJTAjBgNVBC4THDYzck5N +OTVpMlF5ME1tcmNERk1YZXd0ckErYz0wHhcNMTgwNDE2MTc0NjE4WhcNMjgwNDEx +MTc0NjE4WjB/MRYwFAYDVQQKEw1kY3BvbWF0aWMuY29tMRYwFAYDVQQLEw1kY3Bv +bWF0aWMuY29tMSYwJAYDVQQDEx1DUy5kY3BvbWF0aWMuc21wdGUtNDMwLTIuTEVB +RjElMCMGA1UELhMcWHVpL25wcjE3NlJxaENXTmhINUsra3dEMDZVPTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAML7KTWdJSRq9HDqGoN2fUY6c8fO0wvW +inwR8qcQE2qZXt2swwRJD6pfIzZLHrD/WxNfOne8/+bU1S8OxECZaRDkkW9kReP8 +vSvksFJsAnhenP7KT4VaoCX6D2CTHQYvLGwdQcg0UmRKFbmPxiMcyxO6UCAyYFw+ +kRoeqk7pHwSxhqLCwPiOwiy+3Cv8cygNo3i+yeZTAi0YGOeMD8aEBRfohIlmdOeP +d38pLAJhERH2aOXqTVEEXE6w3d+JzitNpicwi8miSD71wxKi0XNrH47HFhCgE5Wj +KyoFXzAHVZTujTc1MpzBaGoEFiBIVOkp1KDEmnxtOC2NaOjx37/BDrECAwEAAaOB +6DCB5TAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIFoDAdBgNVHQ4EFgQUXui/npr1 +76RqhCWNhH5K+kwD06UwgagGA1UdIwSBoDCBnYAU63rNM95i2Qy0MmrcDFMXewtr +A+ehgYGkfzB9MRYwFAYDVQQKEw1kY3BvbWF0aWMuY29tMRYwFAYDVQQLEw1kY3Bv +bWF0aWMuY29tMSQwIgYDVQQDExsuZGNwb21hdGljLnNtcHRlLTQzMC0yLlJPT1Qx +JTAjBgNVBC4THEJKSzZSMjcrWkYzNTR1NFM0ZitCMFpQclBFTT2CAQYwDQYJKoZI +hvcNAQELBQADggEBAC9NX+aZ5JfOooUDyEpCTdyk7KJsHt7Ye7bxt2IXXgerfPfO +zoBua54GORUtjcWpvXMqzhbfD1mAJu2FwhtbF2MQF2d1sowwWhMa9cnwfqsmDylz +yMFk+meHXTjfZ7AeC6IGnUJOXM1wPCaG3A39rQhP8mWbk1jloF221Gx4Fd4s53t4 +h/zv0ObkP9XiDUhsvqu1/oyysuyLscCXQZL1aWLsKxSfOqunaZjP16MFUyst0GJV +JuoaqQ260nM/wQO7ieE+c80eGu28ov5W3kjtqowjvM8UB4ep3NrJxZ1y/Xypjnyh +WsbVStLDVPHxlorfibB4EzSEKyIDBVVPhXs/hGE=</ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509IssuerSerial> + <ds:X509IssuerName>dnQualifier=BJK6R27\+ZF354u4S4f\+B0ZPrPEM=,CN=.dcpomatic.smpte-430-2.ROOT,OU=dcpomatic.com,O=dcpomatic.com</ds:X509IssuerName> + <ds:X509SerialNumber>6</ds:X509SerialNumber> + </ds:X509IssuerSerial> + <ds:X509Certificate>MIIEbTCCA1WgAwIBAgIBBjANBgkqhkiG9w0BAQsFADB9MRYwFAYDVQQKEw1kY3Bv +bWF0aWMuY29tMRYwFAYDVQQLEw1kY3BvbWF0aWMuY29tMSQwIgYDVQQDExsuZGNw +b21hdGljLnNtcHRlLTQzMC0yLlJPT1QxJTAjBgNVBC4THEJKSzZSMjcrWkYzNTR1 +NFM0ZitCMFpQclBFTT0wHhcNMTgwNDE2MTc0NjE3WhcNMjgwNDEyMTc0NjE3WjCB +hTEWMBQGA1UEChMNZGNwb21hdGljLmNvbTEWMBQGA1UECxMNZGNwb21hdGljLmNv +bTEsMCoGA1UEAxMjLmRjcG9tYXRpYy5zbXB0ZS00MzAtMi5JTlRFUk1FRElBVEUx +JTAjBgNVBC4THDYzck5NOTVpMlF5ME1tcmNERk1YZXd0ckErYz0wggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwPTjVL6DwnBgMdGYgIT5nwRA/TtOAOeU5 +Irqqgjj8wKRLa1H5jBxtEHMLwf2jMiR2aXAiorWLUvdiGhC23KV4bTOy4jGgjNNV +3Ij6TnKKqhF7NTfLshh7WO4wQqgChDV5smu2wJL2vHYEhmlJp5BUibyyNJiJc7Vw +223cqJRvIHXFYeclOxlZQnGuU4gDwHZk7hyYxCwdvyr8qt/VBb7oaCvVNw2r/pPB +DDDzWoANOIHaLufaidauCIm8+pH4TER2qNguRvZi8PwSNYpgiePWvpWDTiUUsOge +yknoceg9rAdGNQujUgqJPeKmoxGbTlcw5TdzkCfqBmAGFgcjZrGBAgMBAAGjge4w +geswEgYDVR0TAQH/BAgwBgEB/wIBAjALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFOt6 +zTPeYtkMtDJq3AxTF3sLawPnMIGoBgNVHSMEgaAwgZ2AFASSukdu/mRd+eLuEuH/ +gdGT6zxDoYGBpH8wfTEWMBQGA1UEChMNZGNwb21hdGljLmNvbTEWMBQGA1UECxMN +ZGNwb21hdGljLmNvbTEkMCIGA1UEAxMbLmRjcG9tYXRpYy5zbXB0ZS00MzAtMi5S +T09UMSUwIwYDVQQuExxCSks2UjI3K1pGMzU0dTRTNGYrQjBaUHJQRU09ggEFMA0G +CSqGSIb3DQEBCwUAA4IBAQCjMLdot0fGH4n8ZPbCJX5OLXWm6EXdClsjZlngMTAx +ENB2nvEOxkBte7C400mLFDlFhnGhWJ8boSrN7sEYuFitXA/X5tI50XfHWzl9o/+2 +VWUsEa1D4e+kCmA8kjwf/lzlMnmsdhlPUdsEFEWNbyh4qAC5smhuXKsZxbqZEizA +NK1oJ+Np0Hv4g7tX69uQvw5iWQMGYV/RCxh915ILHWeoKG22Tlcf7AxU5VhkOw5F +Muqu5wgZXbpQ2Mj1ajeL/kwGGI1YbCWm/zHc8jw/LFRWEnCo1wBSkXBHToQVoJF1 +GTtWUcT84jioqTojoFPp1jiOw8oQu8KAFNV9cBH8xShW</ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509IssuerSerial> + <ds:X509IssuerName>dnQualifier=BJK6R27\+ZF354u4S4f\+B0ZPrPEM=,CN=.dcpomatic.smpte-430-2.ROOT,OU=dcpomatic.com,O=dcpomatic.com</ds:X509IssuerName> + <ds:X509SerialNumber>5</ds:X509SerialNumber> + </ds:X509IssuerSerial> + <ds:X509Certificate>MIIEZDCCA0ygAwIBAgIBBTANBgkqhkiG9w0BAQsFADB9MRYwFAYDVQQKEw1kY3Bv +bWF0aWMuY29tMRYwFAYDVQQLEw1kY3BvbWF0aWMuY29tMSQwIgYDVQQDExsuZGNw +b21hdGljLnNtcHRlLTQzMC0yLlJPT1QxJTAjBgNVBC4THEJKSzZSMjcrWkYzNTR1 +NFM0ZitCMFpQclBFTT0wHhcNMTgwNDE2MTc0NjE2WhcNMjgwNDEzMTc0NjE2WjB9 +MRYwFAYDVQQKEw1kY3BvbWF0aWMuY29tMRYwFAYDVQQLEw1kY3BvbWF0aWMuY29t +MSQwIgYDVQQDExsuZGNwb21hdGljLnNtcHRlLTQzMC0yLlJPT1QxJTAjBgNVBC4T +HEJKSzZSMjcrWkYzNTR1NFM0ZitCMFpQclBFTT0wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDeT0ysrx62MNINCICJeUY6GxAJrScKNE0qa3ahRKeslA6n +K4TIpS2uciAFrmvcqpge5HgoMaR3R+mmJGElWruz4gTh/fYU/Lva2EGmwH4UA803 +u0W1HoWqeut11oAUAx3dCmJFORtlOwj+S7sHlyPP3UJLWjIFnemOK3DORNnjlUw1 +sLAaXoi56xHpJysnNzVhXQeVvzT/7njELsxI85UfSZEpUJ3rSQPRl4nrVep5qGug +pFO6prbA8w+SIJ9trTBlmSG8In2QlajQnFsO2Y9wYj8kaLewQco1Prb1qODt/h3m +aeh/+IHjsE494s//zzBNWXbtB5pdKcuVcjnqwELVAgMBAAGjge4wgeswEgYDVR0T +AQH/BAgwBgEB/wIBAzALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFASSukdu/mRd+eLu +EuH/gdGT6zxDMIGoBgNVHSMEgaAwgZ2AFASSukdu/mRd+eLuEuH/gdGT6zxDoYGB +pH8wfTEWMBQGA1UEChMNZGNwb21hdGljLmNvbTEWMBQGA1UECxMNZGNwb21hdGlj +LmNvbTEkMCIGA1UEAxMbLmRjcG9tYXRpYy5zbXB0ZS00MzAtMi5ST09UMSUwIwYD +VQQuExxCSks2UjI3K1pGMzU0dTRTNGYrQjBaUHJQRU09ggEFMA0GCSqGSIb3DQEB +CwUAA4IBAQCgHdUDSWR+8yN+GDKUpXdrhFylFsiP/QWoOS5qSM7QTP7pihEcB2QF +Ay4Z9mn1ZIcUFUund4EKaJTRXNZ8341Tm7wyHbrHTy9rb9c/VFIXDnOJMBi8Ac9O +EM1Z0ZwdBAhmtbm9zUddeHe/lZlPLKTHd+NZ7Pa1hxaamIeCfAiWS5Cmmd7CAOmS +xnaGf0k/0tCDEp86rWdVW1q0JT/0fbh1IO/rtNrHP1Kz86A5Bc4bYsdMTiqkjcFR +KwDhgmLrsGYibIgZ0kmcIaP2pd06zRqWa+fgzH+KQI0Lvk7hjqX5qKWxwpLjES1Q +Kp+MTXgFCZK3CSvMvnmTL9qC5zd3SulH</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> +</DCinemaSecurityMessage> diff --git a/test/wscript b/test/wscript index b4f526bf..3eaef516 100644 --- a/test/wscript +++ b/test/wscript @@ -69,6 +69,7 @@ def build(bld): obj.source = """ asset_test.cc atmos_test.cc + can_be_read_test.cc certificates_test.cc colour_test.cc colour_conversion_test.cc |
