diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-10-31 00:03:49 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-11-05 00:43:19 +0100 |
| commit | e8ce097ce705446c27b51199a321a9918deaa0db (patch) | |
| tree | 0a52cbc9c52791d453fa4bd478609aedde98c831 /src/lib | |
| parent | ef65a179e8c907029d0d9254863d4884581f3d60 (diff) | |
Allow specification of which parts of the DCP to encrypt (#3099).
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/copy_dcp_details_to_film.cc | 4 | ||||
| -rw-r--r-- | src/lib/create_cli.cc | 8 | ||||
| -rw-r--r-- | src/lib/dcp_content.cc | 20 | ||||
| -rw-r--r-- | src/lib/dcp_content.h | 25 | ||||
| -rw-r--r-- | src/lib/dcp_examiner.cc | 18 | ||||
| -rw-r--r-- | src/lib/dcp_examiner.h | 16 | ||||
| -rw-r--r-- | src/lib/film.cc | 44 | ||||
| -rw-r--r-- | src/lib/film.h | 25 | ||||
| -rw-r--r-- | src/lib/film_property.h | 4 | ||||
| -rw-r--r-- | src/lib/reel_writer.cc | 8 | ||||
| -rw-r--r-- | src/lib/writer.cc | 2 |
11 files changed, 142 insertions, 32 deletions
diff --git a/src/lib/copy_dcp_details_to_film.cc b/src/lib/copy_dcp_details_to_film.cc index 9e0ad79c1..67a207de1 100644 --- a/src/lib/copy_dcp_details_to_film.cc +++ b/src/lib/copy_dcp_details_to_film.cc @@ -45,7 +45,9 @@ copy_dcp_settings_to_film(shared_ptr<const DCPContent> dcp, shared_ptr<Film> fil if (dcp->content_kind()) { film->set_dcp_content_type(DCPContentType::from_libdcp_kind(dcp->content_kind().get())); } - film->set_encrypted(dcp->encrypted()); + film->set_encrypt_picture(dcp->picture_encrypted()); + film->set_encrypt_sound(dcp->sound_encrypted()); + film->set_encrypt_text(dcp->text_encrypted()); film->set_reel_type(ReelType::BY_VIDEO_CONTENT); film->set_interop(dcp->standard() == dcp::Standard::INTEROP); film->set_three_d(dcp->three_d()); diff --git a/src/lib/create_cli.cc b/src/lib/create_cli.cc index af2e90745..32834be23 100644 --- a/src/lib/create_cli.cc +++ b/src/lib/create_cli.cc @@ -473,9 +473,13 @@ CreateCLI::make_film(function<void (string)> error) const } film->set_use_isdcf_name(!_no_use_isdcf_name); if (_no_encrypt) { - film->set_encrypted(false); + film->set_encrypt_picture(false); + film->set_encrypt_sound(false); + film->set_encrypt_text(false); } else if (_encrypt) { - film->set_encrypted(true); + film->set_encrypt_picture(true); + film->set_encrypt_sound(true); + film->set_encrypt_text(true); } if (_twod) { film->set_three_d(false); diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc index cff14deca..c75babfc6 100644 --- a/src/lib/dcp_content.cc +++ b/src/lib/dcp_content.cc @@ -66,7 +66,9 @@ using namespace dcpomatic; DCPContent::DCPContent(boost::filesystem::path p) - : _encrypted(false) + : _picture_encrypted(false) + , _sound_encrypted(false) + , _text_encrypted(false) , _needs_assets(false) , _kdm_valid(false) , _reference_video(false) @@ -103,7 +105,10 @@ DCPContent::DCPContent(cxml::ConstNodePtr node, boost::optional<boost::filesyste } _name = node->string_child("Name"); - _encrypted = node->bool_child("Encrypted"); + auto encrypted = node->optional_bool_child("Encrypted").get_value_or(false); + _picture_encrypted = node->optional_bool_child("PictureEncrypted").get_value_or(encrypted); + _sound_encrypted = node->optional_bool_child("SoundEncrypted").get_value_or(encrypted); + _text_encrypted = node->optional_bool_child("TextEncrypted").get_value_or(encrypted); _needs_assets = node->optional_bool_child("NeedsAssets").get_value_or(false); if (node->optional_node_child("KDM")) { _kdm = dcp::EncryptedKDM(node->string_child("KDM")); @@ -314,7 +319,9 @@ DCPContent::examine(shared_ptr<const Film> film, shared_ptr<Job> job, bool toler boost::mutex::scoped_lock lm(_mutex); text = new_text; _name = examiner->name(); - _encrypted = examiner->encrypted(); + _picture_encrypted = examiner->picture_encrypted(); + _sound_encrypted = examiner->sound_encrypted(); + _text_encrypted = examiner->text_encrypted(); _needs_assets = examiner->needs_assets(); _kdm_valid = examiner->kdm_valid(); _standard = examiner->standard(); @@ -396,7 +403,10 @@ DCPContent::as_xml(xmlpp::Element* element, bool with_paths, PathBehaviour path_ boost::mutex::scoped_lock lm(_mutex); cxml::add_text_child(element, "Name", _name); - cxml::add_text_child(element, "Encrypted", _encrypted ? "1" : "0"); + cxml::add_text_child(element, "Encrypted", (_picture_encrypted || _sound_encrypted || _text_encrypted) ? "1" : "0"); + cxml::add_text_child(element, "PictureEncrypted", _picture_encrypted ? "1" : "0"); + cxml::add_text_child(element, "SoundEncrypted", _sound_encrypted ? "1" : "0"); + cxml::add_text_child(element, "TextEncrypted", _text_encrypted ? "1" : "0"); cxml::add_text_child(element, "NeedsAssets", _needs_assets ? "1" : "0"); if (_kdm) { cxml::add_text_child(element, "KDM", _kdm->as_xml()); @@ -526,7 +536,7 @@ bool DCPContent::needs_kdm() const { boost::mutex::scoped_lock lm(_mutex); - return _encrypted && !_kdm_valid; + return (_picture_encrypted || _sound_encrypted || _text_encrypted) && !_kdm_valid; } bool diff --git a/src/lib/dcp_content.h b/src/lib/dcp_content.h index 1b58c8efc..97e4b3cc4 100644 --- a/src/lib/dcp_content.h +++ b/src/lib/dcp_content.h @@ -97,7 +97,25 @@ public: bool encrypted() const { boost::mutex::scoped_lock lm(_mutex); - return _encrypted; + return _picture_encrypted || _sound_encrypted || _text_encrypted; + } + + /** @return true if any picture asset in this DCP is encrypted */ + bool picture_encrypted() const { + boost::mutex::scoped_lock lm(_mutex); + return _picture_encrypted; + } + + /** @return true if any sound asset in this DCP is encrypted */ + bool sound_encrypted() const { + boost::mutex::scoped_lock lm(_mutex); + return _sound_encrypted; + } + + /** @return true if any text asset in this DCP is encrypted */ + bool text_encrypted() const { + boost::mutex::scoped_lock lm(_mutex); + return _text_encrypted; } void add_kdm(dcp::EncryptedKDM); @@ -217,8 +235,9 @@ private: bool overlaps(std::shared_ptr<const Film> film, std::function<bool (std::shared_ptr<const Content>)> part) const; std::string _name; - /** true if our DCP is encrypted */ - bool _encrypted; + bool _picture_encrypted; + bool _sound_encrypted; + bool _text_encrypted; /** true if this DCP needs more assets before it can be played */ bool _needs_assets; boost::optional<dcp::EncryptedKDM> _kdm; diff --git a/src/lib/dcp_examiner.cc b/src/lib/dcp_examiner.cc index 59bd47702..b94d88486 100644 --- a/src/lib/dcp_examiner.cc +++ b/src/lib/dcp_examiner.cc @@ -313,7 +313,23 @@ DCPExaminer::DCPExaminer(shared_ptr<const DCPContent> content, bool tolerant) ++reel_index; } - _encrypted = selected_cpl->any_encrypted(); + for (auto reel: selected_cpl->reels()) { + if (reel->main_picture() && reel->main_picture()->encrypted()) { + _picture_encrypted = true; + } + if (reel->main_sound() && reel->main_sound()->encrypted()) { + _sound_encrypted = true; + } + if (reel->main_subtitle() && reel->main_subtitle()->encrypted()) { + _text_encrypted = true; + } + for (auto cc: reel->closed_captions()) { + if (cc->encrypted()) { + _text_encrypted = true; + } + } + } + _kdm_valid = true; LOG_GENERAL_NC("Check that everything encrypted has a key"); diff --git a/src/lib/dcp_examiner.h b/src/lib/dcp_examiner.h index 0a6045ed0..6bc9793aa 100644 --- a/src/lib/dcp_examiner.h +++ b/src/lib/dcp_examiner.h @@ -76,8 +76,16 @@ public: return _name; } - bool encrypted() const { - return _encrypted; + bool picture_encrypted() const { + return _picture_encrypted; + } + + bool sound_encrypted() const { + return _sound_encrypted; + } + + bool text_encrypted() const { + return _text_encrypted; } bool needs_assets() const { @@ -216,7 +224,9 @@ private: std::vector<DCPTextTrack> _dcp_subtitle_tracks; /** the DCPTextTracks for each of our closed captions */ std::vector<DCPTextTrack> _dcp_caption_tracks; - bool _encrypted = false; + bool _picture_encrypted = false; + bool _sound_encrypted = false; + bool _text_encrypted = false; bool _needs_assets = false; bool _kdm_valid = false; boost::optional<dcp::Standard> _standard; diff --git a/src/lib/film.cc b/src/lib/film.cc index 8dc55c590..b8f983add 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -168,7 +168,9 @@ Film::Film(optional<boost::filesystem::path> dir) , _dcp_content_type(DCPContentType::from_isdcf_name("FTR")) , _container(Ratio::from_id("185")) , _resolution(Resolution::TWO_K) - , _encrypted(false) + , _encrypt_picture(false) + , _encrypt_sound(false) + , _encrypt_text(false) , _context_id(dcp::make_uuid()) , _video_frame_rate(24) , _audio_channels(6) @@ -418,7 +420,11 @@ Film::metadata(bool with_content_paths) const cxml::add_text_child(root, "Interop", _interop ? "1" : "0"); cxml::add_text_child(root, "VideoEncoding", video_encoding_to_string(_video_encoding)); cxml::add_text_child(root, "LimitToSMPTEBv20", _limit_to_smpte_bv20 ? "1" : "0"); - cxml::add_text_child(root, "Encrypted", _encrypted ? "1" : "0"); + /* We don't need this any more, but writing it makes the metadata backwards compatible */ + cxml::add_text_child(root, "Encrypted", encrypted() ? "1" : "0"); + cxml::add_text_child(root, "EncryptPicture", _encrypt_picture ? "1" : "0"); + cxml::add_text_child(root, "EncryptSound", _encrypt_sound ? "1" : "0"); + cxml::add_text_child(root, "EncryptText", _encrypt_text ? "1" : "0"); cxml::add_text_child(root, "Key", _key.hex()); cxml::add_text_child(root, "ContextID", _context_id); if (_audio_processor) { @@ -593,7 +599,10 @@ Film::read_metadata(optional<boost::filesystem::path> path) _video_bit_rate[VideoEncoding::MPEG2] = f.optional_number_child<int64_t>("MPEG2VideoBitRate").get_value_or(Config::instance()->default_video_bit_rate(VideoEncoding::MPEG2)); _video_frame_rate = f.number_child<int>("VideoFrameRate"); _audio_frame_rate = f.optional_number_child<int>("AudioFrameRate").get_value_or(48000); - _encrypted = f.bool_child("Encrypted"); + auto encrypted = f.optional_bool_child("Encrypted").get_value_or(false); + _encrypt_picture = f.optional_bool_child("EncryptPicture").get_value_or(encrypted); + _encrypt_sound = f.optional_bool_child("EncryptSound").get_value_or(encrypted); + _encrypt_text = f.optional_bool_child("EncryptText").get_value_or(encrypted); _audio_channels = f.number_child<int>("AudioChannels"); /* We used to allow odd numbers (and zero) channels, but it's just not worth the pain. @@ -1423,12 +1432,29 @@ Film::cpls() const } void -Film::set_encrypted(bool e) +Film::set_encrypt_picture(bool e) { - FilmChangeSignaller ch(this, FilmProperty::ENCRYPTED); - _encrypted = e; + FilmChangeSignaller ch(this, FilmProperty::ENCRYPT_PICTURE); + _encrypt_picture = e; } + +void +Film::set_encrypt_sound(bool e) +{ + FilmChangeSignaller ch(this, FilmProperty::ENCRYPT_SOUND); + _encrypt_sound = e; +} + + +void +Film::set_encrypt_text(bool e) +{ + FilmChangeSignaller ch(this, FilmProperty::ENCRYPT_TEXT); + _encrypt_text = e; +} + + ContentList Film::content() const { @@ -1859,7 +1885,7 @@ Film::active_area() const dcp::DecryptedKDM Film::make_kdm(boost::filesystem::path cpl_file, dcp::LocalTime from, dcp::LocalTime until) const { - if (!_encrypted) { + if (!encrypted()) { throw runtime_error(_("Cannot make a KDM as this project is not encrypted.")); } @@ -2102,7 +2128,9 @@ Film::use_template(optional<string> name) _video_bit_rate[encoding] = _template_film->_video_bit_rate[encoding]; } _video_frame_rate = _template_film->_video_frame_rate; - _encrypted = _template_film->_encrypted; + _encrypt_picture = _template_film->_encrypt_picture; + _encrypt_sound = _template_film->_encrypt_sound; + _encrypt_text = _template_film->_encrypt_text; _audio_channels = _template_film->_audio_channels; _sequence = _template_film->_sequence; _three_d = _template_film->_three_d; diff --git a/src/lib/film.h b/src/lib/film.h index 6d04da9bf..adaff3c52 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -231,7 +231,19 @@ public: } bool encrypted() const { - return _encrypted; + return _encrypt_picture || _encrypt_sound || _encrypt_text; + } + + bool encrypt_picture() const { + return _encrypt_picture; + } + + bool encrypt_sound() const { + return _encrypt_sound; + } + + bool encrypt_text() const { + return _encrypt_text; } dcp::Key key() const { @@ -392,7 +404,9 @@ public: void set_dcp_content_type(DCPContentType const *); void set_container(Ratio c, bool user_explicit = true); void set_resolution(Resolution, bool user_explicit = true); - void set_encrypted(bool); + void set_encrypt_picture(bool); + void set_encrypt_sound(bool); + void set_encrypt_text(bool); void set_video_bit_rate(VideoEncoding encoding, int64_t); void set_video_frame_rate(int rate, bool user_explicit = false); void set_audio_channels(int); @@ -512,7 +526,12 @@ private: Ratio _container; /** DCP resolution (2K or 4K) */ Resolution _resolution; - bool _encrypted; + /** Encrypt picture assets */ + bool _encrypt_picture; + /** Encrypt sound assets */ + bool _encrypt_sound; + /** Encrypt text (subtitle/closed-caption) assets */ + bool _encrypt_text; dcp::Key _key; /** context ID used when encrypting picture assets; we keep it so that we can * re-start picture MXF encodes. diff --git a/src/lib/film_property.h b/src/lib/film_property.h index ebda0e807..5c38ae986 100644 --- a/src/lib/film_property.h +++ b/src/lib/film_property.h @@ -38,7 +38,9 @@ enum class FilmProperty { DCP_CONTENT_TYPE, CONTAINER, RESOLUTION, - ENCRYPTED, + ENCRYPT_PICTURE, + ENCRYPT_SOUND, + ENCRYPT_TEXT, VIDEO_BIT_RATE, VIDEO_FRAME_RATE, AUDIO_FRAME_RATE, diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc index 01a798676..1d5a16075 100644 --- a/src/lib/reel_writer.cc +++ b/src/lib/reel_writer.cc @@ -146,7 +146,7 @@ ReelWriter::ReelWriter( asset->set_size(film()->frame_size()); asset->set_metadata(mxf_metadata()); - if (film()->encrypted()) { + if (film()->encrypt_picture()) { asset->set_key(film()->key()); asset->set_context_id(film()->context_id()); } @@ -218,7 +218,7 @@ ReelWriter::ReelWriter( _sound_asset->set_metadata(mxf_metadata()); - if (film()->encrypted()) { + if (film()->encrypt_sound()) { _sound_asset->set_key(film()->key()); } @@ -310,7 +310,7 @@ ReelWriter::write(shared_ptr<const dcp::AtmosFrame> atmos, AtmosMetadata metadat { if (!_atmos_asset) { _atmos_asset = metadata.create(dcp::Fraction(film()->video_frame_rate(), 1)); - if (film()->encrypted()) { + if (film()->encrypt_sound()) { _atmos_asset->set_key(film()->key()); } _atmos_asset_writer = _atmos_asset->start_write( @@ -820,7 +820,7 @@ ReelWriter::empty_text_asset(TextType type, optional<DCPTextTrack> track, bool w s->set_reel_number(_reel_index + 1); s->set_time_code_rate(film()->video_frame_rate()); s->set_start_time(dcp::Time()); - if (film()->encrypted()) { + if (film()->encrypt_text()) { s->set_key(film()->key()); } asset = s; diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 7121c594b..41e831e94 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -723,7 +723,7 @@ Writer::finish() bool Writer::can_fake_write(Frame frame) const { - if (film()->encrypted()) { + if (film()->encrypt_picture()) { /* We need to re-write the frame because the asset ID is embedded in the HMAC... I think... */ return false; } |
