diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-07-07 00:39:15 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-07-07 00:39:15 +0100 |
| commit | 932b942a51bef4e2dd2de9f83aa5b68ad07f60f9 (patch) | |
| tree | 40f81e0b4b2e04f46bab243e9c94ff24b8bcb2ef | |
| parent | 4313456938d34d93239194e914b82e7a5ae14c1c (diff) | |
Working decryption via KDM.
| -rw-r--r-- | src/cpl.cc | 62 | ||||
| -rw-r--r-- | src/cpl.h | 15 | ||||
| -rw-r--r-- | src/dcp.cc | 29 | ||||
| -rw-r--r-- | src/dcp.h | 7 | ||||
| -rw-r--r-- | src/kdm.cc | 6 | ||||
| -rw-r--r-- | src/kdm.h | 16 | ||||
| -rw-r--r-- | src/mxf_asset.cc | 12 | ||||
| -rw-r--r-- | src/mxf_asset.h | 9 | ||||
| -rw-r--r-- | src/picture_asset.cc | 2 | ||||
| -rw-r--r-- | src/picture_frame.cc | 4 | ||||
| -rw-r--r-- | src/picture_frame.h | 2 | ||||
| -rw-r--r-- | src/reel.cc | 20 | ||||
| -rw-r--r-- | src/reel.h | 19 | ||||
| -rw-r--r-- | test/decryption_test.cc | 61 | ||||
| -rw-r--r-- | test/kdm_test.cc | 4 | ||||
| -rw-r--r-- | test/read_dcp_test.cc | 2 | ||||
| -rw-r--r-- | test/rewrite_subs.cc | 8 | ||||
| -rw-r--r-- | test/wscript | 1 | ||||
| -rw-r--r-- | tools/dcpinfo.cc | 8 |
19 files changed, 223 insertions, 64 deletions
@@ -48,7 +48,7 @@ CPL::CPL (string directory, string name, ContentKind content_kind, int length, i , _length (length) , _fps (frames_per_second) { - _uuid = make_uuid (); + _id = make_uuid (); } /** Construct a CPL object from a XML file. @@ -76,6 +76,9 @@ CPL::CPL (string directory, string file, shared_ptr<const libdcp::parse::AssetMa _name = cpl->annotation_text; _content_kind = cpl->content_kind; + /* Trim urn:uuid: off the front */ + _id = cpl->id.substr (9); + for (list<shared_ptr<libdcp::parse::Reel> >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) { shared_ptr<parse::Picture> p; @@ -110,7 +113,10 @@ CPL::CPL (string directory, string file, shared_ptr<const libdcp::parse::AssetMa picture->set_entry_point (p->entry_point); picture->set_duration (p->duration); - picture->set_key_id (p->key_id); + if (p->key_id.length() > 9) { + /* Trim urn:uuid: */ + picture->set_key_id (p->key_id.substr (9)); + } } catch (MXFFileError) { if (require_mxfs) { throw; @@ -129,7 +135,10 @@ CPL::CPL (string directory, string file, shared_ptr<const libdcp::parse::AssetMa picture->set_entry_point (p->entry_point); picture->set_duration (p->duration); - picture->set_key_id (p->key_id); + if (p->key_id.length() > 9) { + /* Trim urn:uuid: */ + picture->set_key_id (p->key_id.substr (9)); + } } catch (MXFFileError) { if (require_mxfs) { @@ -148,9 +157,14 @@ CPL::CPL (string directory, string file, shared_ptr<const libdcp::parse::AssetMa ) ); - sound->set_entry_point ((*i)->asset_list->main_sound->entry_point); - sound->set_duration ((*i)->asset_list->main_sound->duration); - sound->set_key_id ((*i)->asset_list->main_sound->key_id); + shared_ptr<parse::MainSound> s = (*i)->asset_list->main_sound; + + sound->set_entry_point (s->entry_point); + sound->set_duration (s->duration); + if (s->key_id.length() > 9) { + /* Trim urn:uuid: */ + sound->set_key_id (s->key_id.substr (9)); + } } catch (MXFFileError) { if (require_mxfs) { throw; @@ -175,7 +189,7 @@ CPL::CPL (string directory, string file, shared_ptr<const libdcp::parse::AssetMa } void -CPL::add_reel (shared_ptr<const Reel> reel) +CPL::add_reel (shared_ptr<Reel> reel) { _reels.push_back (reel); } @@ -186,7 +200,7 @@ CPL::write_xml (XMLMetadata const & metadata, shared_ptr<Encryption> crypt) cons boost::filesystem::path p; p /= _directory; stringstream s; - s << _uuid << "_cpl.xml"; + s << _id << "_cpl.xml"; p /= s.str(); xmlpp::Document doc; @@ -196,7 +210,7 @@ CPL::write_xml (XMLMetadata const & metadata, shared_ptr<Encryption> crypt) cons root->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig"); } - root->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + root->add_child("Id")->add_child_text ("urn:uuid:" + _id); root->add_child("AnnotationText")->add_child_text (_name); root->add_child("IssueDate")->add_child_text (metadata.issue_date); root->add_child("Creator")->add_child_text (metadata.creator); @@ -204,14 +218,14 @@ CPL::write_xml (XMLMetadata const & metadata, shared_ptr<Encryption> crypt) cons root->add_child("ContentKind")->add_child_text (content_kind_to_string (_content_kind)); { xmlpp::Node* cv = root->add_child ("ContentVersion"); - cv->add_child ("Id")->add_child_text ("urn:uri:" + _uuid + "_" + metadata.issue_date); - cv->add_child ("LabelText")->add_child_text (_uuid + "_" + metadata.issue_date); + cv->add_child ("Id")->add_child_text ("urn:uri:" + _id + "_" + metadata.issue_date); + cv->add_child ("LabelText")->add_child_text (_id + "_" + metadata.issue_date); } root->add_child("RatingList"); xmlpp::Node* reel_list = root->add_child ("ReelList"); - for (list<shared_ptr<const Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { + for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { (*i)->write_to_cpl (reel_list); } @@ -229,7 +243,7 @@ void CPL::write_to_pkl (xmlpp::Node* node) const { xmlpp::Node* asset = node->add_child ("Asset"); - asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _id); asset->add_child("Hash")->add_child_text (_digest); asset->add_child("Size")->add_child_text (lexical_cast<string> (_length)); asset->add_child("Type")->add_child_text ("text/xml"); @@ -239,7 +253,7 @@ list<shared_ptr<const Asset> > CPL::assets () const { list<shared_ptr<const Asset> > a; - for (list<shared_ptr<const Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { + for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { if ((*i)->main_picture ()) { a.push_back ((*i)->main_picture ()); } @@ -258,10 +272,10 @@ void CPL::write_to_assetmap (xmlpp::Node* node) const { xmlpp::Node* asset = node->add_child ("Asset"); - asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _id); xmlpp::Node* chunk_list = asset->add_child ("ChunkList"); xmlpp::Node* chunk = chunk_list->add_child ("Chunk"); - chunk->add_child("Path")->add_child_text (_uuid + "_cpl.xml"); + chunk->add_child("Path")->add_child_text (_id + "_cpl.xml"); chunk->add_child("VolumeIndex")->add_child_text ("1"); chunk->add_child("Offset")->add_child_text("0"); chunk->add_child("Length")->add_child_text(lexical_cast<string> (_length)); @@ -301,8 +315,8 @@ CPL::equals (CPL const & other, EqualityOptions opt, boost::function<void (NoteT return false; } - list<shared_ptr<const Reel> >::const_iterator a = _reels.begin (); - list<shared_ptr<const Reel> >::const_iterator b = other._reels.begin (); + list<shared_ptr<Reel> >::const_iterator a = _reels.begin (); + list<shared_ptr<Reel> >::const_iterator b = other._reels.begin (); while (a != _reels.end ()) { if (!(*a)->equals (*b, opt, note)) { @@ -375,7 +389,7 @@ CPL::make_kdm ( recipient->add_child("X509SubjectName")->add_child_text (Certificate::name_for_xml (recipient_cert->subject())); } - kdm_required_extensions->add_child("CompositionPlaylistId")->add_child_text("urn:uuid:" + _uuid); + kdm_required_extensions->add_child("CompositionPlaylistId")->add_child_text("urn:uuid:" + _id); kdm_required_extensions->add_child("ContentTitleText")->add_child_text(_name); kdm_required_extensions->add_child("ContentAuthenticator")->add_child_text(certificates.leaf()->thumbprint()); kdm_required_extensions->add_child("ContentKeysNotValidBefore")->add_child_text("XXX"); @@ -473,7 +487,7 @@ CPL::make_kdm ( bool CPL::encrypted () const { - for (list<shared_ptr<const Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { + for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { if ((*i)->encrypted ()) { return true; } @@ -481,3 +495,11 @@ CPL::encrypted () const return false; } + +void +CPL::add_kdm (KDM const & kdm) +{ + for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { + (*i)->add_kdm (kdm); + } +} @@ -36,6 +36,7 @@ class Reel; class XMLMetadata; class MXFMetadata; class Encryption; +class KDM; /** @brief A CPL within a DCP */ class CPL @@ -44,7 +45,7 @@ public: CPL (std::string directory, std::string name, ContentKind content_kind, int length, int frames_per_second); CPL (std::string directory, std::string file, boost::shared_ptr<const parse::AssetMap> asset_map, bool require_mxfs = true); - void add_reel (boost::shared_ptr<const Reel> reel); + void add_reel (boost::shared_ptr<Reel> reel); /** @return the length in frames */ int length () const { @@ -58,7 +59,7 @@ public: return _content_kind; } - std::list<boost::shared_ptr<const Reel> > reels () const { + std::list<boost::shared_ptr<Reel> > reels () const { return _reels; } @@ -77,6 +78,10 @@ public: std::list<boost::shared_ptr<const Asset> > assets () const; bool encrypted () const; + + std::string id () const { + return _id; + } bool equals (CPL const & other, EqualityOptions options, boost::function<void (NoteType, std::string)> note) const; @@ -93,6 +98,8 @@ public: MXFMetadata const &, XMLMetadata const & ) const; + + void add_kdm (KDM const &); private: std::string _directory; @@ -105,10 +112,10 @@ private: /** frames per second */ int _fps; /** reels */ - std::list<boost::shared_ptr<const Reel> > _reels; + std::list<boost::shared_ptr<Reel> > _reels; /** our UUID */ - std::string _uuid; + std::string _id; /** a SHA1 digest of our XML */ mutable std::string _digest; }; @@ -46,6 +46,7 @@ #include "reel.h" #include "cpl.h" #include "encryption.h" +#include "kdm.h" using std::string; using std::list; @@ -65,7 +66,7 @@ DCP::DCP (string directory) void DCP::write_xml (XMLMetadata const & metadata, shared_ptr<Encryption> crypt) const { - for (list<shared_ptr<const CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { + for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { (*i)->write_xml (metadata, crypt); } @@ -106,7 +107,7 @@ DCP::write_pkl (string pkl_uuid, XMLMetadata const & metadata, shared_ptr<Encryp (*i)->write_to_pkl (asset_list); } - for (list<shared_ptr<const CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { + for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { (*i)->write_to_pkl (asset_list); } @@ -158,7 +159,7 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, XMLMetadata const & metada chunk->add_child("Offset")->add_child_text ("0"); chunk->add_child("Length")->add_child_text (lexical_cast<string> (pkl_length)); - for (list<shared_ptr<const CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { + for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { (*i)->write_to_assetmap (asset_list); } @@ -261,8 +262,8 @@ DCP::equals (DCP const & other, EqualityOptions opt, boost::function<void (NoteT return false; } - list<shared_ptr<const CPL> >::const_iterator a = _cpls.begin (); - list<shared_ptr<const CPL> >::const_iterator b = other._cpls.begin (); + list<shared_ptr<CPL> >::const_iterator a = _cpls.begin (); + list<shared_ptr<CPL> >::const_iterator b = other._cpls.begin (); while (a != _cpls.end ()) { if (!(*a)->equals (*b->get(), opt, note)) { @@ -293,7 +294,7 @@ list<shared_ptr<const Asset> > DCP::assets () const { list<shared_ptr<const Asset> > a; - for (list<shared_ptr<const CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { + for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { list<shared_ptr<const Asset> > t = (*i)->assets (); a.merge (t); } @@ -306,7 +307,7 @@ DCP::assets () const bool DCP::encrypted () const { - for (list<shared_ptr<const CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { + for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { if ((*i)->encrypted ()) { return true; } @@ -314,3 +315,17 @@ DCP::encrypted () const return false; } + +void +DCP::add_kdm (KDM const & kdm) +{ + list<KDMCipher> ciphers = kdm.ciphers (); + + for (list<shared_ptr<CPL> >::iterator i = _cpls.begin(); i != _cpls.end(); ++i) { + for (list<KDMCipher>::iterator j = ciphers.begin(); j != ciphers.end(); ++j) { + if (j->cpl_id() == (*i)->id()) { + (*i)->add_kdm (kdm); + } + } + } +} @@ -48,6 +48,7 @@ class Reel; class CPL; class XMLMetadata; class Encryption; +class KDM; /** @class DCP * @brief A class to create or read a DCP. @@ -92,12 +93,14 @@ public: void add_cpl (boost::shared_ptr<CPL> cpl); /** @return The list of CPLs in this DCP */ - std::list<boost::shared_ptr<const CPL> > cpls () const { + std::list<boost::shared_ptr<CPL> > cpls () const { return _cpls; } bool encrypted () const; + void add_kdm (KDM const &); + /** Emitted with a parameter between 0 and 1 to indicate progress * for long jobs. */ @@ -131,7 +134,7 @@ private: /** the directory that we are writing to */ std::string _directory; /** our CPLs */ - std::list<boost::shared_ptr<const CPL> > _cpls; + std::list<boost::shared_ptr<CPL> > _cpls; }; } @@ -94,7 +94,8 @@ KDMCipher::KDMCipher (unsigned char const * raw, int len) _key_id = get_uuid (&raw, 16); _not_valid_before = get (&raw, 25); _not_valid_after = get (&raw, 25); - _key_data = get_hex (&raw, 16); + memcpy (_key_raw, raw, 16); + _key_string = get_hex (&raw, 16); break; case 138: /* SMPTE */ @@ -105,7 +106,8 @@ KDMCipher::KDMCipher (unsigned char const * raw, int len) _key_id = get_uuid (&raw, 16); _not_valid_before = get (&raw, 25); _not_valid_after = get (&raw, 25); - _key_data = get_hex (&raw, 16); + memcpy (_key_raw, raw, 16); + _key_string = get_hex (&raw, 16); break; default: assert (false); @@ -17,6 +17,9 @@ */ +#ifndef LIBDCP_KDM_H +#define LIBDCP_KDM_H + #include <boost/filesystem.hpp> namespace libdcp { @@ -54,8 +57,12 @@ public: return _not_valid_after; } - std::string key_data () const { - return _key_data; + std::string key_string () const { + return _key_string; + } + + unsigned char const * key_raw () const { + return _key_raw; } private: @@ -70,7 +77,8 @@ private: std::string _key_id; std::string _not_valid_before; std::string _not_valid_after; - std::string _key_data; + std::string _key_string; + unsigned char _key_raw[16]; }; class KDM @@ -89,4 +97,4 @@ private: } - +#endif diff --git a/src/mxf_asset.cc b/src/mxf_asset.cc index 3cb13250..1c45dcbc 100644 --- a/src/mxf_asset.cc +++ b/src/mxf_asset.cc @@ -33,6 +33,7 @@ #include "util.h" #include "metadata.h" #include "exceptions.h" +#include "kdm.h" using std::string; using std::list; @@ -46,6 +47,7 @@ MXFAsset::MXFAsset (string directory, string file_name) , _progress (0) , _encrypted (false) , _encryption_context (0) + , _decryption_context (0) { } @@ -55,6 +57,7 @@ MXFAsset::MXFAsset (string directory, string file_name, boost::signals2::signal< , _progress (progress) , _encrypted (encrypted) , _encryption_context (0) + , _decryption_context (0) { if (_encrypted) { _key_id = make_uuid (); @@ -150,3 +153,12 @@ MXFAsset::write_to_cpl (xmlpp::Node* node) const a->add_child("KeyId")->add_child_text ("urn:uuid:" + _key_id); } } + +void +MXFAsset::set_kdm_cipher (KDMCipher cipher) +{ + _decryption_context = new ASDCP::AESDecContext; + if (ASDCP_FAILURE (_decryption_context->InitKey (cipher.key_raw ()))) { + throw MiscError ("could not set up decryption context"); + } +} diff --git a/src/mxf_asset.h b/src/mxf_asset.h index 1e4d362c..7a20e465 100644 --- a/src/mxf_asset.h +++ b/src/mxf_asset.h @@ -21,6 +21,7 @@ #define LIBDCP_MXF_ASSET_H #include <boost/signals2.hpp> +#include "AS_DCP.h" #include "asset.h" namespace ASDCP { @@ -31,6 +32,7 @@ namespace libdcp { class MXFMetadata; +class KDMCipher; /** @brief Parent class for assets which have MXF files */ class MXFAsset : public Asset @@ -69,6 +71,10 @@ public: void add_typed_key_id (xmlpp::Element *) const; + std::string key_id () const { + return _key_id; + } + void set_key_id (std::string k) { _key_id = k; } @@ -76,6 +82,8 @@ public: bool encrypted () const { return !_key_id.empty (); } + + void set_kdm_cipher (KDMCipher); protected: virtual std::string key_type () const = 0; @@ -87,6 +95,7 @@ protected: ASDCP::AESEncContext* _encryption_context; std::string _key_value; std::string _key_id; + ASDCP::AESDecContext* _decryption_context; }; } diff --git a/src/picture_asset.cc b/src/picture_asset.cc index c9e1da45..eb17813e 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -259,7 +259,7 @@ MonoPictureAsset::path_from_list (int f, vector<string> const & files) const shared_ptr<const MonoPictureFrame> MonoPictureAsset::get_frame (int n) const { - return shared_ptr<const MonoPictureFrame> (new MonoPictureFrame (path().string(), n)); + return shared_ptr<const MonoPictureFrame> (new MonoPictureFrame (path().string(), n, _decryption_context)); } diff --git a/src/picture_frame.cc b/src/picture_frame.cc index 7e6bc1f8..b4d72f6f 100644 --- a/src/picture_frame.cc +++ b/src/picture_frame.cc @@ -37,7 +37,7 @@ using namespace libdcp; * @param mxf_path Path to the asset's MXF file. * @param n Frame within the asset, not taking EntryPoint into account. */ -MonoPictureFrame::MonoPictureFrame (string mxf_path, int n) +MonoPictureFrame::MonoPictureFrame (string mxf_path, int n, ASDCP::AESDecContext* c) { ASDCP::JP2K::MXFReader reader; if (ASDCP_FAILURE (reader.OpenRead (mxf_path.c_str()))) { @@ -47,7 +47,7 @@ MonoPictureFrame::MonoPictureFrame (string mxf_path, int n) /* XXX: unfortunate guesswork on this buffer size */ _buffer = new ASDCP::JP2K::FrameBuffer (4 * Kumu::Megabyte); - if (ASDCP_FAILURE (reader.ReadFrame (n, *_buffer))) { + if (ASDCP_FAILURE (reader.ReadFrame (n, *_buffer, c))) { boost::throw_exception (DCPReadError ("could not read video frame")); } } diff --git a/src/picture_frame.h b/src/picture_frame.h index 42c5d629..c48b5213 100644 --- a/src/picture_frame.h +++ b/src/picture_frame.h @@ -37,7 +37,7 @@ class ARGBFrame; class MonoPictureFrame { public: - MonoPictureFrame (std::string mxf_path, int n); + MonoPictureFrame (std::string mxf_path, int n, ASDCP::AESDecContext *); ~MonoPictureFrame (); boost::shared_ptr<ARGBFrame> argb_frame (int reduce = 0, float srgb_gamma = 2.4) const; diff --git a/src/reel.cc b/src/reel.cc index 4a266fda..c8ea54eb 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -23,8 +23,12 @@ #include "picture_asset.h" #include "sound_asset.h" #include "subtitle_asset.h" +#include "kdm.h" -using namespace std; +using std::string; +using std::list; +using std::cout; +using boost::shared_ptr; using namespace libdcp; void @@ -86,3 +90,17 @@ Reel::encrypted () const return ((_main_picture && _main_picture->encrypted ()) || (_main_sound && _main_sound->encrypted ())); } +void +Reel::add_kdm (KDM const & kdm) +{ + list<KDMCipher> ciphers = kdm.ciphers (); + + for (list<KDMCipher>::iterator i = ciphers.begin(); i != ciphers.end(); ++i) { + if (i->key_id() == _main_picture->key_id()) { + _main_picture->set_kdm_cipher (*i); + } + if (i->key_id() == _main_sound->key_id()) { + _main_sound->set_kdm_cipher (*i); + } + } +} @@ -30,17 +30,18 @@ namespace xmlpp { namespace libdcp { class PictureAsset; -class SoundAsset; -class SubtitleAsset; +class SoundAsset; +class SubtitleAsset; +class KDM; /** @brief A reel within a DCP; the part which actually contains picture, sound and subtitle data */ class Reel { public: Reel ( - boost::shared_ptr<const PictureAsset> picture, - boost::shared_ptr<const SoundAsset> sound, - boost::shared_ptr<const SubtitleAsset> subtitle + boost::shared_ptr<PictureAsset> picture, + boost::shared_ptr<SoundAsset> sound, + boost::shared_ptr<SubtitleAsset> subtitle ) : _main_picture (picture) , _main_sound (sound) @@ -65,10 +66,12 @@ public: bool equals (boost::shared_ptr<const Reel> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> notes) const; + void add_kdm (KDM const &); + private: - boost::shared_ptr<const PictureAsset> _main_picture; - boost::shared_ptr<const SoundAsset> _main_sound; - boost::shared_ptr<const SubtitleAsset> _main_subtitle; + boost::shared_ptr<PictureAsset> _main_picture; + boost::shared_ptr<SoundAsset> _main_sound; + boost::shared_ptr<SubtitleAsset> _main_subtitle; }; } diff --git a/test/decryption_test.cc b/test/decryption_test.cc index 6870a286..507d2efd 100644 --- a/test/decryption_test.cc +++ b/test/decryption_test.cc @@ -17,7 +17,14 @@ */ -BOOST_AUTO_TEST_CASE (is_encrypted_test) +#include <tiffio.h> +#include "kdm.h" +#include "picture_frame.h" +#include "argb_frame.h" + +using boost::dynamic_pointer_cast; + +BOOST_AUTO_TEST_CASE (decryption_test) { boost::filesystem::path plaintext_path = test_corpus; plaintext_path /= "TONEPLATES-SMPTE-PLAINTEXT_TST_F_XX-XX_ITL-TD_51-XX_2K_WOE_20111001_WOE_OV"; @@ -30,4 +37,56 @@ BOOST_AUTO_TEST_CASE (is_encrypted_test) libdcp::DCP encrypted (encrypted_path.string ()); encrypted.read (); BOOST_CHECK_EQUAL (encrypted.encrypted (), true); + + libdcp::KDM kdm ( + "test/data/kdm_TONEPLATES-SMPTE-ENC_.smpte-430-2.ROOT.NOT_FOR_PRODUCTION_20130706_20230702_CAR_OV_t1_8971c838.xml", + "test/data/private.key" + ); + + encrypted.add_kdm (kdm); + + shared_ptr<const libdcp::Reel> encrypted_reel = encrypted.cpls().front()->reels().front (); + shared_ptr<const libdcp::PictureAsset> encrypted_picture = encrypted_reel->main_picture (); + BOOST_CHECK (encrypted_picture); + + shared_ptr<const libdcp::MonoPictureAsset> encrypted_mono_picture = dynamic_pointer_cast<const libdcp::MonoPictureAsset> (encrypted_picture); + shared_ptr<const libdcp::MonoPictureFrame> j2k_frame = encrypted_mono_picture->get_frame (0); + + shared_ptr<const libdcp::ARGBFrame> argb_frame = j2k_frame->argb_frame (); + + + + uint8_t* tiff_frame = new uint8_t[1998 * 3 * 1080]; + + uint8_t* t = tiff_frame; + uint8_t* r = argb_frame->data (); + for (int y = 0; y < 1080; ++y) { + for (int x = 0; x < 1998; ++x) { + /* Our data is first-byte blue, second-byte green, third-byte red, fourth-byte alpha, + so we need to twiddle here. + */ + + t[0] = r[2]; // red + t[1] = r[1]; // green + t[2] = r[0]; // blue + t += 3; + r += 4; + } + } + + TIFF* output = TIFFOpen ("foo.tiff", "w"); + BOOST_CHECK (output); + + TIFFSetField (output, TIFFTAG_IMAGEWIDTH, 1998); + TIFFSetField (output, TIFFTAG_IMAGELENGTH, 1080); + TIFFSetField (output, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + TIFFSetField (output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField (output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField (output, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField (output, TIFFTAG_SAMPLESPERPIXEL, 3); + + BOOST_CHECK (TIFFWriteEncodedStrip (output, 0, tiff_frame, 1998 * 1080 * 3)); + TIFFClose (output); + + delete[] tiff_frame; } diff --git a/test/kdm_test.cc b/test/kdm_test.cc index 172661e3..f536e189 100644 --- a/test/kdm_test.cc +++ b/test/kdm_test.cc @@ -34,11 +34,11 @@ BOOST_AUTO_TEST_CASE (kdm_test) BOOST_CHECK_EQUAL (ciphers.front().key_id(), "4ac4f922-8239-4831-b23b-31426d0542c4"); BOOST_CHECK_EQUAL (ciphers.front().not_valid_before(), "2013-07-06T20:04:58+00:00"); BOOST_CHECK_EQUAL (ciphers.front().not_valid_after(), "2023-07-02T20:04:56+00:00"); - BOOST_CHECK_EQUAL (ciphers.front().key_data(), "8a2729c3e5b65c45d78305462104c3fb"); + BOOST_CHECK_EQUAL (ciphers.front().key_string(), "8a2729c3e5b65c45d78305462104c3fb"); BOOST_CHECK_EQUAL (ciphers.back().cpl_id(), "eece17de-77e8-4a55-9347-b6bab5724b9f"); BOOST_CHECK_EQUAL (ciphers.back().key_id(), "73baf5de-e195-4542-ab28-8a465f7d4079"); BOOST_CHECK_EQUAL (ciphers.back().not_valid_before(), "2013-07-06T20:04:58+00:00"); BOOST_CHECK_EQUAL (ciphers.back().not_valid_after(), "2023-07-02T20:04:56+00:00"); - BOOST_CHECK_EQUAL (ciphers.back().key_data(), "5327fb7ec2e807bd57059615bf8a169d"); + BOOST_CHECK_EQUAL (ciphers.back().key_string(), "5327fb7ec2e807bd57059615bf8a169d"); } diff --git a/test/read_dcp_test.cc b/test/read_dcp_test.cc index 026073a3..5e6827d1 100644 --- a/test/read_dcp_test.cc +++ b/test/read_dcp_test.cc @@ -23,7 +23,7 @@ BOOST_AUTO_TEST_CASE (read_dcp) libdcp::DCP d ("test/ref/DCP/foo"); d.read (); - list<shared_ptr<const libdcp::CPL> > cpls = d.cpls (); + list<shared_ptr<libdcp::CPL> > cpls = d.cpls (); BOOST_CHECK_EQUAL (cpls.size(), 1); BOOST_CHECK_EQUAL (cpls.front()->name(), "A Test DCP"); diff --git a/test/rewrite_subs.cc b/test/rewrite_subs.cc index 8c055d9e..c7f8bfbd 100644 --- a/test/rewrite_subs.cc +++ b/test/rewrite_subs.cc @@ -23,11 +23,11 @@ try DCP* dcp = new DCP (argv[1]); dcp->read (false); - list<shared_ptr<const CPL> > cpls = dcp->cpls (); - for (list<boost::shared_ptr<const CPL> >::iterator i = cpls.begin(); i != cpls.end(); ++i) { + list<shared_ptr<CPL> > cpls = dcp->cpls (); + for (list<boost::shared_ptr<CPL> >::iterator i = cpls.begin(); i != cpls.end(); ++i) { - list<shared_ptr<const Reel> > reels = (*i)->reels (); - for (list<shared_ptr<const Reel> >::iterator j = reels.begin(); j != reels.end(); ++j) { + list<shared_ptr<Reel> > reels = (*i)->reels (); + for (list<shared_ptr<Reel> >::iterator j = reels.begin(); j != reels.end(); ++j) { if ((*j)->main_subtitle()) { (*j)->main_subtitle()->write_xml (); diff --git a/test/wscript b/test/wscript index 2892bf9e..f957b106 100644 --- a/test/wscript +++ b/test/wscript @@ -14,6 +14,7 @@ def configure(conf): uselib_store = 'BOOST_TEST') conf.env.prepend_value('LINKFLAGS', '-Lsrc') + conf.env.append_value('LIB', 'tiff') def build(bld): obj = bld(features = 'cxx cxxprogram') diff --git a/tools/dcpinfo.cc b/tools/dcpinfo.cc index 04fec82f..56d71f99 100644 --- a/tools/dcpinfo.cc +++ b/tools/dcpinfo.cc @@ -78,17 +78,17 @@ main (int argc, char* argv[]) cout << "DCP: " << argv[optind] << "\n"; - list<shared_ptr<const CPL> > cpls = dcp->cpls (); + list<shared_ptr<CPL> > cpls = dcp->cpls (); - for (list<shared_ptr<const CPL> >::iterator i = cpls.begin(); i != cpls.end(); ++i) { + for (list<shared_ptr<CPL> >::iterator i = cpls.begin(); i != cpls.end(); ++i) { cout << " CPL: " << (*i)->name() << "\n" << " Length: " << (*i)->length() << "\n" << " Frames per second: " << (*i)->frames_per_second() << "\n"; - list<shared_ptr<const Reel> > reels = (*i)->reels (); + list<shared_ptr<Reel> > reels = (*i)->reels (); int R = 1; - for (list<shared_ptr<const Reel> >::const_iterator j = reels.begin(); j != reels.end(); ++j) { + for (list<shared_ptr<Reel> >::const_iterator j = reels.begin(); j != reels.end(); ++j) { cout << " Reel " << R << "\n"; if ((*j)->main_picture()) { |
