From: Carl Hetherington Date: Tue, 17 Jul 2012 19:29:24 +0000 (+0100) Subject: Use libdcp. X-Git-Tag: v2.0.48~1963 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=21e682c5eb1e0957e8fdae155028be65532ed96e Use libdcp. --- diff --git a/src/gtk/film_editor.cc b/src/gtk/film_editor.cc index 0e410aa6b..3367c9a70 100644 --- a/src/gtk/film_editor.cc +++ b/src/gtk/film_editor.cc @@ -31,7 +31,6 @@ #include "lib/exceptions.h" #include "lib/ab_transcode_job.h" #include "lib/thumbs_job.h" -#include "lib/make_mxf_job.h" #include "lib/job_manager.h" #include "lib/filter.h" #include "lib/screen.h" diff --git a/src/lib/dcp_content_type.cc b/src/lib/dcp_content_type.cc index 321aa61da..03712cb0d 100644 --- a/src/lib/dcp_content_type.cc +++ b/src/lib/dcp_content_type.cc @@ -28,9 +28,9 @@ using namespace std; vector DCPContentType::_dcp_content_types; -DCPContentType::DCPContentType (string p, string d) +DCPContentType::DCPContentType (string p, libdcp::DCP::ContentType c) : _pretty_name (p) - , _dcp_name (d) + , _libdcp_type (c) { } @@ -38,16 +38,16 @@ DCPContentType::DCPContentType (string p, string d) void DCPContentType::setup_dcp_content_types () { - _dcp_content_types.push_back (new DCPContentType ("Feature", "feature")); - _dcp_content_types.push_back (new DCPContentType ("Short", "short")); - _dcp_content_types.push_back (new DCPContentType ("Trailer", "trailer")); - _dcp_content_types.push_back (new DCPContentType ("Test", "test")); - _dcp_content_types.push_back (new DCPContentType ("Transitional", "transitional")); - _dcp_content_types.push_back (new DCPContentType ("Rating", "rating")); - _dcp_content_types.push_back (new DCPContentType ("Teaser", "teaster")); - _dcp_content_types.push_back (new DCPContentType ("Policy", "policy")); - _dcp_content_types.push_back (new DCPContentType ("Public Service Announcement", "psa")); - _dcp_content_types.push_back (new DCPContentType ("Advertisement", "advertisement")); + _dcp_content_types.push_back (new DCPContentType ("Feature", libdcp::DCP::FEATURE)); + _dcp_content_types.push_back (new DCPContentType ("Short", libdcp::DCP::SHORT)); + _dcp_content_types.push_back (new DCPContentType ("Trailer", libdcp::DCP::TRAILER)); + _dcp_content_types.push_back (new DCPContentType ("Test", libdcp::DCP::TEST)); + _dcp_content_types.push_back (new DCPContentType ("Transitional", libdcp::DCP::TRANSITIONAL)); + _dcp_content_types.push_back (new DCPContentType ("Rating", libdcp::DCP::RATING)); + _dcp_content_types.push_back (new DCPContentType ("Teaser", libdcp::DCP::TEASER)); + _dcp_content_types.push_back (new DCPContentType ("Policy", libdcp::DCP::POLICY)); + _dcp_content_types.push_back (new DCPContentType ("Public Service Announcement", libdcp::DCP::PUBLIC_SERVICE_ANNOUNCEMENT)); + _dcp_content_types.push_back (new DCPContentType ("Advertisement", libdcp::DCP::ADVERTISEMENT)); } DCPContentType const * diff --git a/src/lib/dcp_content_type.h b/src/lib/dcp_content_type.h index aba305449..2c6d1879b 100644 --- a/src/lib/dcp_content_type.h +++ b/src/lib/dcp_content_type.h @@ -23,6 +23,7 @@ #include #include +#include /** @class DCPContentType * @brief A description of the type of content for a DCP (e.g. feature, trailer etc.) @@ -30,16 +31,15 @@ class DCPContentType { public: - DCPContentType (std::string, std::string); + DCPContentType (std::string, libdcp::DCP::ContentType); /** @return user-visible `pretty' name */ std::string pretty_name () const { return _pretty_name; } - /** @return name as written to a DCP */ - std::string dcp_name () const { - return _dcp_name; + libdcp::DCP::ContentType libdcp_type () const { + return _libdcp_type; } static DCPContentType const * from_pretty_name (std::string); @@ -50,7 +50,7 @@ public: private: std::string _pretty_name; - std::string _dcp_name; + libdcp::DCP::ContentType _libdcp_type; /** All available DCP content types */ static std::vector _dcp_content_types; diff --git a/src/lib/film.cc b/src/lib/film.cc index 3eea41c25..6bf8fee84 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -36,7 +36,6 @@ #include "job_manager.h" #include "ab_transcode_job.h" #include "transcode_job.h" -#include "make_mxf_job.h" #include "scp_dcp_job.h" #include "copy_from_dvd_job.h" #include "make_dcp_job.h" @@ -518,10 +517,6 @@ Film::make_dcp (bool transcode, int freq) } } - JobManager::instance()->add (shared_ptr (new MakeMXFJob (fs, o, log (), MakeMXFJob::VIDEO))); - if (audio_channels() > 0) { - JobManager::instance()->add (shared_ptr (new MakeMXFJob (fs, o, log (), MakeMXFJob::AUDIO))); - } JobManager::instance()->add (shared_ptr (new MakeDCPJob (fs, o, log ()))); } diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc index 998d1f9c3..b0b8a2a1a 100644 --- a/src/lib/make_dcp_job.cc +++ b/src/lib/make_dcp_job.cc @@ -22,6 +22,7 @@ */ #include +#include extern "C" { #include } @@ -29,6 +30,7 @@ extern "C" { #include "film_state.h" #include "dcp_content_type.h" #include "exceptions.h" +#include "options.h" using namespace std; using namespace boost; @@ -54,45 +56,43 @@ MakeDCPJob::name () const void MakeDCPJob::run () { - set_progress_unknown (); - string const dcp_path = _fs->dir (_fs->name); - - /* Check that we have our prerequisites */ - - if (!filesystem::exists (filesystem::path (_fs->file ("video.mxf")))) { - throw EncodeError ("missing video.mxf"); - } - - bool const have_audio = filesystem::exists (filesystem::path (_fs->file ("audio.mxf"))); /* Remove any old DCP */ filesystem::remove_all (dcp_path); - DCP dcp (_fs->dir (_fs->name())); - dcp.add_asset ( - shared_ptr (new MainPictureAsset ("video.mxf", rint (_fs->frames_per_second), _fs->length, _opt->out_size)) - ); + libdcp::DCP dcp (_fs->dir (_fs->name), _fs->name, _fs->dcp_content_type->libdcp_type (), rint (_fs->frames_per_second), _fs->length); + dcp.Progress.connect (sigc::mem_fun (*this, &MakeDCPJob::dcp_progress)); - if (filesystem::exists (filesystem::path (_fs->file ("audio.mxf")))) { - dcp.add_asset ( - shared_ptr (new MainSoundAsset ("audio.mxf", rint (_fs->frames_per_second), _fs->length)) - ); + list j2cs; + int f = _fs->dcp_frames ? _fs->dcp_frames : _fs->length; + for (int i = 0; i < f; ++i) { + j2cs.push_back (_opt->frame_out_path (i, false)); } - - dcp.write_xml (); - - add_pkl (); - add_cpl (pkl[0]); + descend (0.9); + dcp.add_picture_asset (j2cs, _opt->out_size.width, _opt->out_size.height); + ascend (); - add_reel (pkl[0].cpl[0]); + list wavs; + for (int i = 0; i < _fs->audio_channels; ++i) { + wavs.push_back (_opt->multichannel_audio_out_path (i, false)); + } - write_cpl (); - write_pkl (); - write_volindex (); - write_assetmap (); + if (!wavs.empty ()) { + descend (0.1); + dcp.add_sound_asset (wavs); + ascend (); + } + dcp.write_xml (); set_progress (1); + set_state (FINISHED_OK); +} + +void +MakeDCPJob::dcp_progress (float p) +{ + set_progress (p); } diff --git a/src/lib/make_dcp_job.h b/src/lib/make_dcp_job.h index 98cb2d8c3..fc7da6c89 100644 --- a/src/lib/make_dcp_job.h +++ b/src/lib/make_dcp_job.h @@ -21,7 +21,7 @@ * @brief A job to create DCPs. */ -#include "shell_command_job.h" +#include "job.h" /** @class MakeDCPJob * @brief A job to create DCPs @@ -33,5 +33,8 @@ public: std::string name () const; void run (); + +private: + void dcp_progress (float); }; diff --git a/src/lib/make_mxf_job.cc b/src/lib/make_mxf_job.cc deleted file mode 100644 index ac4c61e6d..000000000 --- a/src/lib/make_mxf_job.cc +++ /dev/null @@ -1,251 +0,0 @@ -/* - Copyright (C) 2012 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. - -*/ - -/** @file src/make_mxf_job.cc - * @brief A job that creates a MXF file from some data. - */ - -#include -#include -#include "AS_DCP.h" -#include "KM_fileio.h" -#include "make_mxf_job.h" -#include "film.h" -#include "film_state.h" -#include "options.h" -#include "exceptions.h" - -using namespace std; -using namespace boost; - -/** @class MakeMXFJob - * @brief A job that creates a MXF file from some data. - */ - -MakeMXFJob::MakeMXFJob (shared_ptr s, shared_ptr o, Log* l, Type t) - : Job (s, o, l) - , _type (t) -{ - -} - -string -MakeMXFJob::name () const -{ - stringstream s; - switch (_type) { - case VIDEO: - s << "Make video MXF for " << _fs->name; - break; - case AUDIO: - s << "Make audio MXF for " << _fs->name; - break; - } - - return s.str (); -} - -void -MakeMXFJob::run () -{ - set_progress (0); - - string dir; - switch (_type) { - case VIDEO: - dir = _opt->frame_out_path (); - break; - case AUDIO: - dir = _opt->multichannel_audio_out_path (); - break; - } - - list files; - for (filesystem::directory_iterator i = filesystem::directory_iterator (dir); i != filesystem::directory_iterator(); ++i) { - files.push_back (filesystem::path (*i).string()); - } - - if (files.empty ()) { - throw EncodeError ("no input files found for MXF"); - } - - files.sort (); - - switch (_type) { - case VIDEO: - j2k (files, _fs->file ("video.mxf")); - break; - case AUDIO: - wav (files, _fs->file ("audio.mxf")); - break; - default: - throw EncodeError ("unknown essence type"); - } - - set_progress (1); -} - -void -MakeMXFJob::wav (list const & files, string const & mxf) -{ - /* XXX: we round for DCP: not sure if this is right */ - ASDCP::Rational fps (rintf (_fs->frames_per_second), 1); - - ASDCP::PCM::WAVParser pcm_parser_channel[files.size()]; - if (pcm_parser_channel[0].OpenRead (files.front().c_str(), fps)) { - throw EncodeError ("could not open WAV file for reading"); - } - - ASDCP::PCM::AudioDescriptor audio_desc; - pcm_parser_channel[0].FillAudioDescriptor (audio_desc); - audio_desc.ChannelCount = 0; - audio_desc.BlockAlign = 0; - audio_desc.EditRate = fps; - audio_desc.AvgBps = audio_desc.AvgBps * files.size (); - - ASDCP::PCM::FrameBuffer frame_buffer_channel[files.size()]; - ASDCP::PCM::AudioDescriptor audio_desc_channel[files.size()]; - - int j = 0; - for (list::const_iterator i = files.begin(); i != files.end(); ++i) { - - if (ASDCP_FAILURE (pcm_parser_channel[j].OpenRead (i->c_str(), fps))) { - throw EncodeError ("could not open WAV file for reading"); - } - - pcm_parser_channel[j].FillAudioDescriptor (audio_desc_channel[j]); - frame_buffer_channel[j].Capacity (ASDCP::PCM::CalcFrameBufferSize (audio_desc_channel[j])); - - audio_desc.ChannelCount += audio_desc_channel[j].ChannelCount; - audio_desc.BlockAlign += audio_desc_channel[j].BlockAlign; - ++j; - } - - ASDCP::PCM::FrameBuffer frame_buffer; - frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (audio_desc)); - frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (audio_desc)); - - ASDCP::WriterInfo writer_info; - fill_writer_info (&writer_info); - - ASDCP::PCM::MXFWriter mxf_writer; - if (ASDCP_FAILURE (mxf_writer.OpenWrite (mxf.c_str(), writer_info, audio_desc))) { - throw EncodeError ("could not open audio MXF for writing"); - } - - for (int i = 0; i < _fs->length; ++i) { - - byte_t *data_s = frame_buffer.Data(); - byte_t *data_e = data_s + frame_buffer.Capacity(); - byte_t sample_size = ASDCP::PCM::CalcSampleSize (audio_desc_channel[0]); - int offset = 0; - - for (list::size_type j = 0; j < files.size(); ++j) { - memset (frame_buffer_channel[j].Data(), 0, frame_buffer_channel[j].Capacity()); - if (ASDCP_FAILURE (pcm_parser_channel[j].ReadFrame (frame_buffer_channel[j]))) { - throw EncodeError ("could not read audio frame"); - } - - if (frame_buffer_channel[j].Size() != frame_buffer_channel[j].Capacity()) { - throw EncodeError ("short audio frame"); - } - } - - while (data_s < data_e) { - for (list::size_type j = 0; j < files.size(); ++j) { - byte_t* frame = frame_buffer_channel[j].Data() + offset; - memcpy (data_s, frame, sample_size); - data_s += sample_size; - } - offset += sample_size; - } - - if (ASDCP_FAILURE (mxf_writer.WriteFrame (frame_buffer, 0, 0))) { - throw EncodeError ("could not write audio MXF frame"); - } - - set_progress (float (i) / _fs->length); - } - - if (ASDCP_FAILURE (mxf_writer.Finalize())) { - throw EncodeError ("could not finalise audio MXF"); - } - - set_progress (1); - set_state (FINISHED_OK); -} - -void -MakeMXFJob::j2k (list const & files, string const & mxf) -{ - ASDCP::JP2K::CodestreamParser j2k_parser; - ASDCP::JP2K::FrameBuffer frame_buffer (4 * Kumu::Megabyte); - if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (files.front().c_str(), frame_buffer))) { - throw EncodeError ("could not open J2K file for reading"); - } - - ASDCP::JP2K::PictureDescriptor picture_desc; - j2k_parser.FillPictureDescriptor (picture_desc); - /* XXX: we round for DCP: not sure if this is right */ - picture_desc.EditRate = ASDCP::Rational (rintf (_fs->frames_per_second), 1); - - ASDCP::WriterInfo writer_info; - fill_writer_info (&writer_info); - - ASDCP::JP2K::MXFWriter mxf_writer; - if (ASDCP_FAILURE (mxf_writer.OpenWrite (mxf.c_str(), writer_info, picture_desc))) { - throw EncodeError ("could not open MXF for writing"); - } - - int j = 0; - for (list::const_iterator i = files.begin(); i != files.end(); ++i) { - if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (i->c_str(), frame_buffer))) { - throw EncodeError ("could not open J2K file for reading"); - } - - /* XXX: passing 0 to WriteFrame ok? */ - if (ASDCP_FAILURE (mxf_writer.WriteFrame (frame_buffer, 0, 0))) { - throw EncodeError ("error in writing video MXF"); - } - - ++j; - set_progress (float (j) / files.size ()); - } - - if (ASDCP_FAILURE (mxf_writer.Finalize())) { - throw EncodeError ("error in finalising video MXF"); - } - - set_progress (1); - set_state (FINISHED_OK); -} - -void -MakeMXFJob::fill_writer_info (ASDCP::WriterInfo* writer_info) -{ - writer_info->ProductVersion = DVDOMATIC_VERSION; - writer_info->CompanyName = "dvd-o-matic"; - writer_info->ProductName = "dvd-o-matic"; - - /* set the label type */ - writer_info->LabelSetType = ASDCP::LS_MXF_SMPTE; - - /* generate a random UUID for this essence */ - Kumu::GenRandomUUID (writer_info->AssetUUID); -} diff --git a/src/lib/make_mxf_job.h b/src/lib/make_mxf_job.h deleted file mode 100644 index 90542561a..000000000 --- a/src/lib/make_mxf_job.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2012 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. - -*/ - -/** @file src/make_mxf_job.h - * @brief A job that creates a MXF file from some data. - */ - -#include "shell_command_job.h" - -namespace ASDCP { - class WriterInfo; -} - -class FilmState; -class Options; - -/** @class MakeMXFJob - * @brief A job that creates a MXF file from some data. - */ -class MakeMXFJob : public Job -{ -public: - enum Type { - AUDIO, - VIDEO - }; - - MakeMXFJob (boost::shared_ptr, boost::shared_ptr, Log *, Type); - - std::string name () const; - void run (); - -private: - void j2k (std::list const &, std::string const &); - void wav (std::list const &, std::string const &); - void fill_writer_info (ASDCP::WriterInfo *); - - Type _type; -}; - diff --git a/src/lib/util.cc b/src/lib/util.cc index b8531e26b..1348d307e 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -216,37 +216,6 @@ audio_sample_format_from_string (string s) return AV_SAMPLE_FMT_NONE; } -/** @return Version of OpenDCP that is on the path (and hence that we will use) */ -static string -opendcp_version () -{ - FILE* f = popen ("opendcp_xml", "r"); - if (f == 0) { - throw EncodeError ("could not run opendcp_xml to check version"); - } - - string version = "unknown"; - - while (!feof (f)) { - char* buf = 0; - size_t n = 0; - ssize_t const r = getline (&buf, &n, f); - if (r > 0) { - string s (buf); - vector b; - split (b, s, is_any_of (" ")); - if (b.size() >= 3 && b[0] == "OpenDCP" && b[1] == "version") { - version = b[2]; - } - free (buf); - } - } - - pclose (f); - - return version; -} - /** @return Version of vobcopy that is on the path (and hence that we will use) */ static string vobcopy_version () @@ -295,7 +264,6 @@ dependency_version_summary () { stringstream s; s << "libopenjpeg " << opj_version () << ", " - << "opendcp " << opendcp_version () << ", " << "vobcopy " << vobcopy_version() << ", " << "libswresample " << ffmpeg_version_to_string (swresample_version()) << ", " << "libavcodec " << ffmpeg_version_to_string (avcodec_version()) << ", " diff --git a/src/lib/wscript b/src/lib/wscript index 406697f9c..cee0a47e7 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -7,8 +7,7 @@ def build(bld): obj = bld(features = 'cxx cxxshlib') obj.name = 'libdvdomatic' obj.export_includes = ['.'] - obj.uselib = 'AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE SNDFILE BOOST_FILESYSTEM BOOST_THREAD OPENJPEG POSTPROC TIFF SIGC++ MAGICK SSH' - obj.use = 'libasdcp-dvdomatic' + obj.uselib = 'AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE SNDFILE BOOST_FILESYSTEM BOOST_THREAD OPENJPEG POSTPROC TIFF SIGC++ MAGICK SSH DCP' if bld.env.DEBUG_HASH: obj.uselib += ' MHASH' obj.source = """ @@ -39,7 +38,6 @@ def build(bld): log.cc lut.cc make_dcp_job.cc - make_mxf_job.cc player.cc player_manager.cc scaler.cc diff --git a/src/tools/makedcp.cc b/src/tools/makedcp.cc index 76cda8202..15880cae9 100644 --- a/src/tools/makedcp.cc +++ b/src/tools/makedcp.cc @@ -24,7 +24,6 @@ #include "film.h" #include "filter.h" #include "transcode_job.h" -#include "make_mxf_job.h" #include "make_dcp_job.h" #include "job_manager.h" #include "ab_transcode_job.h" diff --git a/src/wscript b/src/wscript index f864e1ce1..2ddd90f5c 100644 --- a/src/wscript +++ b/src/wscript @@ -1,6 +1,5 @@ def configure(conf): conf.recurse('lib') - conf.recurse('asdcplib') if not conf.env.DISABLE_GUI: conf.recurse('gtk') diff --git a/wscript b/wscript index f10f225a2..e6ff18d93 100644 --- a/wscript +++ b/wscript @@ -31,6 +31,7 @@ def configure(conf): conf.check_cfg(package = 'libswresample', args = '--cflags --libs', uselib_store = 'SWRESAMPLE', mandatory = True) conf.check_cfg(package = 'libpostproc', args = '--cflags --libs', uselib_store = 'POSTPROC', mandatory = True) conf.check_cfg(package = 'sndfile', args = '--cflags --libs', uselib_store = 'SNDFILE', mandatory = True) + conf.check_cfg(package = 'libdcp', args = '--cflags --libs', uselib_store = 'DCP', mandatory = True) conf.check_cfg(package = '', path = 'Magick++-config', args = '--cppflags --cxxflags --libs', uselib_store = 'MAGICK', mandatory = True) conf.check_cc(msg = 'Checking for library libtiff', function_name = 'TIFFOpen', header_name = 'tiffio.h', lib = 'tiff', uselib_store = 'TIFF') conf.check_cc(fragment = """