From 568e553f506809e753c78a0e0cbad5906bc002b1 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 3 Oct 2013 18:04:31 +0100 Subject: [PATCH] KDM / libdcp API changes. --- run/dcpomatic_kdm | 12 +++++ src/lib/film.cc | 77 ++++++++++---------------- src/lib/film.h | 7 +++ src/lib/util.cc | 37 +++++++++++++ src/lib/util.h | 5 ++ src/lib/writer.cc | 45 +++++----------- src/tools/dcpomatic_kdm.cc | 108 +++++++++++++++++++++++++++++++++++++ src/tools/wscript | 2 +- 8 files changed, 213 insertions(+), 80 deletions(-) create mode 100755 run/dcpomatic_kdm create mode 100644 src/tools/dcpomatic_kdm.cc diff --git a/run/dcpomatic_kdm b/run/dcpomatic_kdm new file mode 100755 index 000000000..faad61018 --- /dev/null +++ b/run/dcpomatic_kdm @@ -0,0 +1,12 @@ +#!/bin/bash + +export LD_LIBRARY_PATH=build/src/lib:$LD_LIBRARY_PATH:build/src +if [ "$1" == "--debug" ]; then + shift + gdb --args build/src/tools/dcpomatic_kdm "$@" +elif [ "$1" == "--valgrind" ]; then + shift + valgrind --tool="memcheck" --leak-check=full --show-reachable=yes build/src/tools/dcpomatic_kdm "$@" +else + build/src/tools/dcpomatic_kdm "$@" +fi diff --git a/src/lib/film.cc b/src/lib/film.cc index 8252b492c..bceaef96e 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -895,42 +895,14 @@ Film::full_frame () const return libdcp::Size (); } -list -Film::make_kdms ( - list > screens, +libdcp::KDM +Film::make_kdm ( + shared_ptr target, boost::posix_time::ptime from, boost::posix_time::ptime until ) const { - boost::filesystem::path const sd = Config::instance()->signer_chain_directory (); - if (boost::filesystem::is_empty (sd)) { - libdcp::make_signer_chain (sd); - } - - libdcp::CertificateChain chain; - - { - boost::filesystem::path p (sd); - p /= "ca.self-signed.pem"; - chain.add (shared_ptr (new libdcp::Certificate (p))); - } - - { - boost::filesystem::path p (sd); - p /= "intermediate.signed.pem"; - chain.add (shared_ptr (new libdcp::Certificate (p))); - } - - { - boost::filesystem::path p (sd); - p /= "leaf.signed.pem"; - chain.add (shared_ptr (new libdcp::Certificate (p))); - } - - boost::filesystem::path signer_key (sd); - signer_key /= "leaf.key"; - - shared_ptr signer (new Signer (chain, signer_key)); + shared_ptr signer = make_signer (); /* Find the DCP to make the KDM for */ string const dir = this->directory (); @@ -947,25 +919,34 @@ Film::make_kdms ( throw KDMError (_("More than one possible DCP to make KDM for")); } + libdcp::DCP dcp (dcps.front ()); + + try { + dcp.read (); + } catch (...) { + throw KDMError (_("Could not read DCP to make KDM for")); + } + + time_t now = time (0); + struct tm* tm = localtime (&now); + string const issue_date = libdcp::tm_to_string (tm); + + dcp.cpls().front()->set_mxf_keys (key ()); + + return libdcp::KDM (dcp.cpls().front(), signer, target, from, until, "DCP-o-matic", issue_date); +} + +list +Film::make_kdms ( + list > screens, + boost::posix_time::ptime from, + boost::posix_time::ptime until + ) const +{ list kdms; for (list >::iterator i = screens.begin(); i != screens.end(); ++i) { - - libdcp::DCP dcp (dcps.front ()); - - try { - dcp.read (); - } catch (...) { - throw KDMError (_("Could not read DCP to make KDM for")); - } - - time_t now = time (0); - struct tm* tm = localtime (&now); - string const issue_date = libdcp::tm_to_string (tm); - - dcp.cpls().front()->set_mxf_keys (key ()); - - kdms.push_back (libdcp::KDM (dcp.cpls().front(), signer, (*i)->certificate, from, until, "DCP-o-matic", issue_date)); + kdms.push_back (make_kdm ((*i)->certificate, from, until)); } return kdms; diff --git a/src/lib/film.h b/src/lib/film.h index a30a630b9..01fccf7d1 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -116,6 +116,13 @@ public: bool has_subtitles () const; OutputVideoFrame best_video_frame_rate () const; + libdcp::KDM + make_kdm ( + boost::shared_ptr target, + boost::posix_time::ptime from, + boost::posix_time::ptime until + ) const; + std::list make_kdms ( std::list >, boost::posix_time::ptime from, diff --git a/src/lib/util.cc b/src/lib/util.cc index 6746b4773..ae3de2d6b 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -46,6 +46,8 @@ #include #include #include +#include +#include extern "C" { #include #include @@ -816,3 +818,38 @@ tidy_for_filename (string f) return t; } + +shared_ptr +make_signer () +{ + boost::filesystem::path const sd = Config::instance()->signer_chain_directory (); + if (boost::filesystem::is_empty (sd)) { + libdcp::make_signer_chain (sd); + } + + libdcp::CertificateChain chain; + + { + boost::filesystem::path p (sd); + p /= "ca.self-signed.pem"; + chain.add (shared_ptr (new libdcp::Certificate (p))); + } + + { + boost::filesystem::path p (sd); + p /= "intermediate.signed.pem"; + chain.add (shared_ptr (new libdcp::Certificate (p))); + } + + { + boost::filesystem::path p (sd); + p /= "leaf.signed.pem"; + chain.add (shared_ptr (new libdcp::Certificate (p))); + } + + boost::filesystem::path signer_key (sd); + signer_key /= "leaf.key"; + + return shared_ptr (new libdcp::Signer (chain, signer_key)); +} + diff --git a/src/lib/util.h b/src/lib/util.h index b5c94d994..377b3b785 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -51,6 +51,10 @@ extern "C" { /** The maximum number of audio channels that we can cope with */ #define MAX_AUDIO_CHANNELS 6 +namespace libdcp { + class Signer; +} + class Job; extern std::string seconds_to_hms (int); @@ -71,6 +75,7 @@ extern bool valid_image_file (boost::filesystem::path); extern boost::filesystem::path mo_path (); #endif extern std::string tidy_for_filename (std::string); +boost::shared_ptr make_signer (); struct FrameRateConversion { diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 37376ca23..caa37c211 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -19,12 +19,13 @@ #include #include -#include #include #include #include #include #include +#include +#include #include "writer.h" #include "compose.hpp" #include "film.h" @@ -74,48 +75,30 @@ Writer::Writer (shared_ptr f, shared_ptr j) */ if (_film->three_d ()) { - _picture_asset.reset ( - new libdcp::StereoPictureAsset ( - _film->internal_video_mxf_dir (), - _film->internal_video_mxf_filename (), - _film->video_frame_rate (), - _film->container()->size (_film->full_frame ()) - ) - ); - + _picture_asset.reset (new libdcp::StereoPictureAsset (_film->internal_video_mxf_dir (), _film->internal_video_mxf_filename ())); } else { - _picture_asset.reset ( - new libdcp::MonoPictureAsset ( - _film->internal_video_mxf_dir (), - _film->internal_video_mxf_filename (), - _film->video_frame_rate (), - _film->container()->size (_film->full_frame ()) - ) - ); - + _picture_asset.reset (new libdcp::MonoPictureAsset (_film->internal_video_mxf_dir (), _film->internal_video_mxf_filename ())); } + _picture_asset->set_edit_rate (_film->video_frame_rate ()); + _picture_asset->set_size (_film->container()->size (_film->full_frame ())); + if (_film->encrypted ()) { _picture_asset->set_key (_film->key ()); } - _picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0, _film->interop ()); + _picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0); - _sound_asset.reset ( - new libdcp::SoundAsset ( - _film->dir (_film->dcp_name()), - _film->audio_mxf_filename (), - _film->video_frame_rate (), - _film->audio_channels (), - _film->audio_frame_rate () - ) - ); + _sound_asset.reset (new libdcp::SoundAsset (_film->dir (_film->dcp_name()), _film->audio_mxf_filename ())); + _sound_asset->set_edit_rate (_film->video_frame_rate ()); + _sound_asset->set_channels (_film->audio_channels ()); + _sound_asset->set_sampling_rate (_film->audio_frame_rate ()); if (_film->encrypted ()) { _sound_asset->set_key (_film->key ()); } - _sound_asset_writer = _sound_asset->start_write (_film->interop ()); + _sound_asset_writer = _sound_asset->start_write (); _thread = new boost::thread (boost::bind (&Writer::thread, this)); @@ -413,7 +396,7 @@ Writer::finish () libdcp::XMLMetadata meta = Config::instance()->dcp_metadata (); meta.set_issue_date_now (); - dcp.write_xml (_film->interop (), meta); + dcp.write_xml (_film->interop (), meta, make_signer ()); _film->log()->log (String::compose (N_("Wrote %1 FULL, %2 FAKE, %3 REPEAT; %4 pushed to disk"), _full_written, _fake_written, _repeat_written, _pushed_to_disk)); } diff --git a/src/tools/dcpomatic_kdm.cc b/src/tools/dcpomatic_kdm.cc new file mode 100644 index 000000000..294248697 --- /dev/null +++ b/src/tools/dcpomatic_kdm.cc @@ -0,0 +1,108 @@ +/* + Copyright (C) 2013 Carl Hetherington + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include "lib/film.h" + +using std::string; +using std::cerr; +using boost::shared_ptr; + +static void +help (string n) +{ + cerr << "Syntax: " << n << " [OPTION] \n" + << " -h, --help show this help\n" + << " -o, --output output filename\n" + << " -f, --valid-from valid from time (e.g. \"2013-09-28 01:41:51\")\n" + << " -t, --valid-to valid to time (e.g. \"2014-09-28 01:41:51\")\n" + << " -c, --certificate file containing projector certificate\n"; +} + +int main (int argc, char* argv[]) +{ + string output; + string valid_from; + string valid_to; + string certificate_file; + + int option_index = 0; + while (1) { + static struct option long_options[] = { + { "help", no_argument, 0, 'h'}, + { "output", required_argument, 0, 'o'}, + { "valid-from", required_argument, 0, 'f'}, + { "valid-to", required_argument, 0, 't'}, + { "certificate", required_argument, 0, 'c' }, + { 0, 0, 0, 0 } + }; + + int c = getopt_long (argc, argv, "ho:f:t:c:", long_options, &option_index); + + if (c == -1) { + break; + } + + switch (c) { + case 'h': + help (argv[0]); + exit (EXIT_SUCCESS); + case 'o': + output = optarg; + break; + case 'f': + valid_from = optarg; + break; + case 't': + valid_to = optarg; + break; + case 'c': + certificate_file = optarg; + break; + } + } + + if (optind >= argc) { + help (argv[0]); + exit (EXIT_FAILURE); + } + + string const film_dir = argv[optind]; + + dcpomatic_setup (); + + shared_ptr film; + try { + film.reset (new Film (film_dir)); + film->read_metadata (); + } catch (std::exception& e) { + cerr << argv[0] << ": error reading film `" << film_dir << "' (" << e.what() << ")\n"; + exit (EXIT_FAILURE); + } + + cerr << "reading " << certificate_file << "\n"; + shared_ptr certificate (new libdcp::Certificate (boost::filesystem::path (certificate_file))); + libdcp::KDM kdm = film->make_kdm ( + certificate, boost::posix_time::time_from_string (valid_from), boost::posix_time::time_from_string (valid_to) + ); + + kdm.as_xml (output); + return 0; +} diff --git a/src/tools/wscript b/src/tools/wscript index 4adf84382..b68926830 100644 --- a/src/tools/wscript +++ b/src/tools/wscript @@ -4,7 +4,7 @@ from waflib import Logs import i18n def build(bld): - for t in ['dcpomatic_cli', 'dcpomatic_server_cli', 'server_test']: + for t in ['dcpomatic_cli', 'dcpomatic_server_cli', 'server_test', 'dcpomatic_kdm']: obj = bld(features = 'cxx cxxprogram') obj.uselib = 'BOOST_THREAD OPENJPEG DCP CXML AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC WXWIDGETS' obj.includes = ['..'] -- 2.30.2