From 5be0255a86726287d7c648adcb8f09f3393f4872 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 8 Nov 2023 23:22:35 +0100 Subject: Rename files to mention J2K. --- src/j2k_picture_asset.cc | 230 +++++++++++++++++++++++++++++++++ src/j2k_picture_asset.h | 155 ++++++++++++++++++++++ src/j2k_picture_asset_writer.cc | 67 ++++++++++ src/j2k_picture_asset_writer.h | 103 +++++++++++++++ src/j2k_picture_asset_writer_common.cc | 95 ++++++++++++++ src/mono_j2k_picture_asset.cc | 208 +++++++++++++++++++++++++++++ src/mono_j2k_picture_asset.h | 94 ++++++++++++++ src/mono_j2k_picture_asset_reader.h | 57 ++++++++ src/mono_j2k_picture_asset_writer.cc | 151 ++++++++++++++++++++++ src/mono_j2k_picture_asset_writer.h | 91 +++++++++++++ src/mono_j2k_picture_frame.cc | 130 +++++++++++++++++++ src/mono_j2k_picture_frame.h | 110 ++++++++++++++++ src/mono_picture_asset.cc | 208 ----------------------------- src/mono_picture_asset.h | 94 -------------- src/mono_picture_asset_reader.h | 57 -------- src/mono_picture_asset_writer.cc | 151 ---------------------- src/mono_picture_asset_writer.h | 91 ------------- src/mono_picture_frame.cc | 130 ------------------- src/mono_picture_frame.h | 110 ---------------- src/picture_asset.cc | 230 --------------------------------- src/picture_asset.h | 155 ---------------------- src/picture_asset_writer.cc | 67 ---------- src/picture_asset_writer.h | 103 --------------- src/picture_asset_writer_common.cc | 95 -------------- src/stereo_j2k_picture_asset.cc | 183 ++++++++++++++++++++++++++ src/stereo_j2k_picture_asset.h | 75 +++++++++++ src/stereo_j2k_picture_asset_reader.h | 57 ++++++++ src/stereo_j2k_picture_asset_writer.cc | 160 +++++++++++++++++++++++ src/stereo_j2k_picture_asset_writer.h | 89 +++++++++++++ src/stereo_j2k_picture_frame.cc | 148 +++++++++++++++++++++ src/stereo_j2k_picture_frame.h | 116 +++++++++++++++++ src/stereo_picture_asset.cc | 183 -------------------------- src/stereo_picture_asset.h | 75 ----------- src/stereo_picture_asset_reader.h | 57 -------- src/stereo_picture_asset_writer.cc | 160 ----------------------- src/stereo_picture_asset_writer.h | 89 ------------- src/stereo_picture_frame.cc | 148 --------------------- src/stereo_picture_frame.h | 116 ----------------- src/wscript | 50 +++---- 39 files changed, 2344 insertions(+), 2344 deletions(-) create mode 100644 src/j2k_picture_asset.cc create mode 100644 src/j2k_picture_asset.h create mode 100644 src/j2k_picture_asset_writer.cc create mode 100644 src/j2k_picture_asset_writer.h create mode 100644 src/j2k_picture_asset_writer_common.cc create mode 100644 src/mono_j2k_picture_asset.cc create mode 100644 src/mono_j2k_picture_asset.h create mode 100644 src/mono_j2k_picture_asset_reader.h create mode 100644 src/mono_j2k_picture_asset_writer.cc create mode 100644 src/mono_j2k_picture_asset_writer.h create mode 100644 src/mono_j2k_picture_frame.cc create mode 100644 src/mono_j2k_picture_frame.h delete mode 100644 src/mono_picture_asset.cc delete mode 100644 src/mono_picture_asset.h delete mode 100644 src/mono_picture_asset_reader.h delete mode 100644 src/mono_picture_asset_writer.cc delete mode 100644 src/mono_picture_asset_writer.h delete mode 100644 src/mono_picture_frame.cc delete mode 100644 src/mono_picture_frame.h delete mode 100644 src/picture_asset.cc delete mode 100644 src/picture_asset.h delete mode 100644 src/picture_asset_writer.cc delete mode 100644 src/picture_asset_writer.h delete mode 100644 src/picture_asset_writer_common.cc create mode 100644 src/stereo_j2k_picture_asset.cc create mode 100644 src/stereo_j2k_picture_asset.h create mode 100644 src/stereo_j2k_picture_asset_reader.h create mode 100644 src/stereo_j2k_picture_asset_writer.cc create mode 100644 src/stereo_j2k_picture_asset_writer.h create mode 100644 src/stereo_j2k_picture_frame.cc create mode 100644 src/stereo_j2k_picture_frame.h delete mode 100644 src/stereo_picture_asset.cc delete mode 100644 src/stereo_picture_asset.h delete mode 100644 src/stereo_picture_asset_reader.h delete mode 100644 src/stereo_picture_asset_writer.cc delete mode 100644 src/stereo_picture_asset_writer.h delete mode 100644 src/stereo_picture_frame.cc delete mode 100644 src/stereo_picture_frame.h (limited to 'src') diff --git a/src/j2k_picture_asset.cc b/src/j2k_picture_asset.cc new file mode 100644 index 00000000..c9f669a6 --- /dev/null +++ b/src/j2k_picture_asset.cc @@ -0,0 +1,230 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/picture_asset.cc + * @brief PictureAsset class + */ + + +#include "compose.hpp" +#include "dcp_assert.h" +#include "equality_options.h" +#include "exceptions.h" +#include "j2k_transcode.h" +#include "openjpeg_image.h" +#include "picture_asset.h" +#include "picture_asset_writer.h" +#include "util.h" +#include +#include +#include +#include +#include +#include + + +using std::string; +using std::list; +using std::vector; +using std::max; +using std::pair; +using std::make_pair; +using std::shared_ptr; +using namespace dcp; + + +PictureAsset::PictureAsset (boost::filesystem::path file) + : Asset (file) +{ + +} + + +PictureAsset::PictureAsset (Fraction edit_rate, Standard standard) + : MXF (standard) + , _edit_rate (edit_rate) +{ + +} + + +void +PictureAsset::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc) +{ + _size.width = desc.StoredWidth; + _size.height = desc.StoredHeight; + _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator); + _intrinsic_duration = desc.ContainerDuration; + _frame_rate = Fraction (desc.SampleRate.Numerator, desc.SampleRate.Denominator); + _screen_aspect_ratio = Fraction (desc.AspectRatio.Numerator, desc.AspectRatio.Denominator); +} + + +bool +PictureAsset::descriptor_equals ( + ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, NoteHandler note + ) const +{ + if ( + a.EditRate != b.EditRate || + a.SampleRate != b.SampleRate || + a.StoredWidth != b.StoredWidth || + a.StoredHeight != b.StoredHeight || + a.AspectRatio != b.AspectRatio || + a.Rsize != b.Rsize || + a.Xsize != b.Xsize || + a.Ysize != b.Ysize || + a.XOsize != b.XOsize || + a.YOsize != b.YOsize || + a.XTsize != b.XTsize || + a.YTsize != b.YTsize || + a.XTOsize != b.XTOsize || + a.YTOsize != b.YTOsize || + a.Csize != b.Csize +// a.CodingStyleDefault != b.CodingStyleDefault || +// a.QuantizationDefault != b.QuantizationDefault + ) { + + note (NoteType::ERROR, "video MXF picture descriptors differ"); + return false; + } + + if (a.ContainerDuration != b.ContainerDuration) { + note (NoteType::ERROR, "video container durations differ"); + } + +// for (unsigned int j = 0; j < ASDCP::JP2K::MaxComponents; ++j) { +// if (a.ImageComponents[j] != b.ImageComponents[j]) { +// notes.pack_start ("video MXF picture descriptors differ"); +// } +// } + + return true; +} + + +bool +PictureAsset::frame_buffer_equals ( + int frame, EqualityOptions const& opt, NoteHandler note, + uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B + ) const +{ + if (size_A == size_B && memcmp (data_A, data_B, size_A) == 0) { + note (NoteType::NOTE, "J2K identical"); + /* Easy result; the J2K data is identical */ + return true; + } + + /* Decompress the images to bitmaps */ + auto image_A = decompress_j2k (const_cast(data_A), size_A, 0); + auto image_B = decompress_j2k (const_cast(data_B), size_B, 0); + + /* Compare them */ + + vector abs_diffs (image_A->size().width * image_A->size().height * 3); + int d = 0; + int max_diff = 0; + + for (int c = 0; c < 3; ++c) { + + if (image_A->size() != image_B->size()) { + note (NoteType::ERROR, String::compose ("image sizes for frame %1 differ", frame)); + return false; + } + + int const pixels = image_A->size().width * image_A->size().height; + for (int j = 0; j < pixels; ++j) { + int const t = abs (image_A->data(c)[j] - image_B->data(c)[j]); + abs_diffs[d++] = t; + max_diff = max (max_diff, t); + } + } + + uint64_t total = 0; + for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { + total += *j; + } + + double const mean = double (total) / abs_diffs.size (); + + uint64_t total_squared_deviation = 0; + for (auto j: abs_diffs) { + total_squared_deviation += pow (j - mean, 2); + } + + auto const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size()); + + note (NoteType::NOTE, String::compose("mean difference %1 deviation %2", mean, std_dev)); + + if (mean > opt.max_mean_pixel_error) { + note ( + NoteType::ERROR, + String::compose ("mean %1 out of range %2 in frame %3", mean, opt.max_mean_pixel_error, frame) + ); + + return false; + } + + if (std_dev > opt.max_std_dev_pixel_error) { + note ( + NoteType::ERROR, + String::compose ("standard deviation %1 out of range %2 in frame %3", std_dev, opt.max_std_dev_pixel_error, frame) + ); + + return false; + } + + return true; +} + + +string +PictureAsset::static_pkl_type (Standard standard) +{ + switch (standard) { + case Standard::INTEROP: + return "application/x-smpte-mxf;asdcpKind=Picture"; + case Standard::SMPTE: + return "application/mxf"; + default: + DCP_ASSERT (false); + } +} + + +string +PictureAsset::pkl_type (Standard standard) const +{ + return static_pkl_type (standard); +} diff --git a/src/j2k_picture_asset.h b/src/j2k_picture_asset.h new file mode 100644 index 00000000..9ad1eb22 --- /dev/null +++ b/src/j2k_picture_asset.h @@ -0,0 +1,155 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/picture_asset.h + * @brief PictureAsset class + */ + + +#ifndef LIBDCP_PICTURE_ASSET_H +#define LIBDCP_PICTURE_ASSET_H + + +#include "mxf.h" +#include "util.h" +#include "metadata.h" + + +namespace ASDCP { + namespace JP2K { + struct PictureDescriptor; + } +} + + +namespace dcp { + + +class MonoPictureFrame; +class StereoPictureFrame; +class PictureAssetWriter; + + +/** @class PictureAsset + * @brief An asset made up of JPEG2000 data + */ +class PictureAsset : public Asset, public MXF +{ +public: + /** Load a PictureAsset from a file */ + explicit PictureAsset (boost::filesystem::path file); + + /** Create a new PictureAsset with a given edit rate and standard */ + PictureAsset(Fraction edit_rate, Standard standard); + + enum class Behaviour { + OVERWRITE_EXISTING, + MAKE_NEW + }; + + virtual std::shared_ptr start_write ( + boost::filesystem::path file, + Behaviour behaviour + ) = 0; + + Size size () const { + return _size; + } + + void set_size (Size s) { + _size = s; + } + + Fraction frame_rate () const { + return _frame_rate; + } + + void set_frame_rate (Fraction r) { + _frame_rate = r; + } + + Fraction screen_aspect_ratio () const { + return _screen_aspect_ratio; + } + + void set_screen_aspect_ratio (Fraction r) { + _screen_aspect_ratio = r; + } + + Fraction edit_rate () const { + return _edit_rate; + } + + int64_t intrinsic_duration () const { + return _intrinsic_duration; + } + + static std::string static_pkl_type (Standard standard); + +protected: + friend class MonoPictureAssetWriter; + friend class StereoPictureAssetWriter; + + bool frame_buffer_equals ( + int frame, EqualityOptions const& opt, NoteHandler note, + uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B + ) const; + + bool descriptor_equals ( + ASDCP::JP2K::PictureDescriptor const & a, + ASDCP::JP2K::PictureDescriptor const & b, + NoteHandler note + ) const; + + void read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const &); + + Fraction _edit_rate; + /** The total length of this content in video frames. The amount of + * content presented may be less than this. + */ + int64_t _intrinsic_duration = 0; + /** picture size in pixels */ + Size _size; + Fraction _frame_rate; + Fraction _screen_aspect_ratio; + +private: + std::string pkl_type (Standard standard) const override; +}; + + +} + + +#endif diff --git a/src/j2k_picture_asset_writer.cc b/src/j2k_picture_asset_writer.cc new file mode 100644 index 00000000..c30be1bc --- /dev/null +++ b/src/j2k_picture_asset_writer.cc @@ -0,0 +1,67 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/picture_asset_writer.cc + * @brief PictureAssetWriter and FrameInfo classes + */ + + +#include "picture_asset_writer.h" +#include "exceptions.h" +#include "picture_asset.h" +#include +#include +#include +#include + + +using std::string; +using std::shared_ptr; +using namespace dcp; + + +PictureAssetWriter::PictureAssetWriter (PictureAsset* asset, boost::filesystem::path file, bool overwrite) + : AssetWriter (asset, file) + , _picture_asset (asset) + , _overwrite (overwrite) +{ + asset->set_file (file); +} + + +FrameInfo +PictureAssetWriter::write (Data const& data) +{ + return write (data.data(), data.size()); +} diff --git a/src/j2k_picture_asset_writer.h b/src/j2k_picture_asset_writer.h new file mode 100644 index 00000000..0caa8815 --- /dev/null +++ b/src/j2k_picture_asset_writer.h @@ -0,0 +1,103 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/picture_asset_writer.h + * @brief PictureAssetWriter and FrameInfo classes. + */ + + +#ifndef LIBDCP_PICTURE_ASSET_WRITER_H +#define LIBDCP_PICTURE_ASSET_WRITER_H + + +#include "asset_writer.h" +#include "metadata.h" +#include +#include +#include +#include + + +namespace dcp { + + +class Data; +class PictureAsset; + + +/** @class FrameInfo + * @brief Information about a single frame (either a monoscopic frame or a left *or* right eye stereoscopic frame) + */ +struct FrameInfo +{ + FrameInfo () {} + + FrameInfo (uint64_t o, uint64_t s, std::string h) + : offset (o) + , size (s) + , hash (h) + {} + + uint64_t offset = 0; + uint64_t size = 0; + std::string hash; +}; + + +/** @class PictureAssetWriter + * @brief Parent class for classes which write picture assets. + */ +class PictureAssetWriter : public AssetWriter +{ +public: + virtual FrameInfo write (uint8_t const *, int) = 0; + virtual void fake_write (int) = 0; + + FrameInfo write (Data const& data); + +protected: + template + friend void start (PictureAssetWriter *, std::shared_ptr

, Q *, uint8_t const *, int); + + PictureAssetWriter (PictureAsset *, boost::filesystem::path, bool); + + PictureAsset* _picture_asset = nullptr; + bool _overwrite = false; +}; + + +} + + +#endif diff --git a/src/j2k_picture_asset_writer_common.cc b/src/j2k_picture_asset_writer_common.cc new file mode 100644 index 00000000..82866aac --- /dev/null +++ b/src/j2k_picture_asset_writer_common.cc @@ -0,0 +1,95 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/picture_asset_writer_common.cc + * @brief Common parts of PictureAssetWriter + */ + + +#include "filesystem.h" + + +using std::shared_ptr; + + +namespace dcp { + + +struct ASDCPStateBase +{ + ASDCPStateBase () + : frame_buffer (4 * Kumu::Megabyte) + {} + + ASDCP::JP2K::CodestreamParser j2k_parser; + ASDCP::JP2K::FrameBuffer frame_buffer; + ASDCP::WriterInfo writer_info; + ASDCP::JP2K::PictureDescriptor picture_descriptor; +}; + + +} + + +template +void dcp::start (PictureAssetWriter* writer, shared_ptr

state, Q* asset, uint8_t const * data, int size) +{ + asset->set_file (writer->_file); + + if (ASDCP_FAILURE (state->j2k_parser.OpenReadFrame(data, size, state->frame_buffer))) { + boost::throw_exception (MiscError ("could not parse J2K frame")); + } + + state->j2k_parser.FillPictureDescriptor (state->picture_descriptor); + state->picture_descriptor.EditRate = ASDCP::Rational (asset->edit_rate().numerator, asset->edit_rate().denominator); + + asset->set_size (Size (state->picture_descriptor.StoredWidth, state->picture_descriptor.StoredHeight)); + asset->set_screen_aspect_ratio (Fraction (state->picture_descriptor.AspectRatio.Numerator, state->picture_descriptor.AspectRatio.Denominator)); + + asset->fill_writer_info (&state->writer_info, asset->id()); + + auto r = state->mxf_writer.OpenWrite( + dcp::filesystem::fix_long_path(*asset->file()).string().c_str(), + state->writer_info, + state->picture_descriptor, + 16384, + writer->_overwrite + ); + + if (ASDCP_FAILURE(r)) { + boost::throw_exception (MXFFileError("could not open MXF file for writing", asset->file()->string(), r)); + } + + writer->_started = true; +} diff --git a/src/mono_j2k_picture_asset.cc b/src/mono_j2k_picture_asset.cc new file mode 100644 index 00000000..9a0beb42 --- /dev/null +++ b/src/mono_j2k_picture_asset.cc @@ -0,0 +1,208 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/mono_picture_asset.cc + * @brief MonoPictureAsset class + */ + + +#include "compose.hpp" +#include "dcp_assert.h" +#include "equality_options.h" +#include "exceptions.h" +#include "filesystem.h" +#include "mono_picture_asset.h" +#include "mono_picture_asset_reader.h" +#include "mono_picture_asset_writer.h" +#include "mono_picture_frame.h" +#include +#include + + +using std::dynamic_pointer_cast; +using std::list; +using std::make_shared; +using std::pair; +using std::shared_ptr; +using std::string; +using std::vector; +#if BOOST_VERSION >= 106100 +using namespace boost::placeholders; +#endif +using namespace dcp; + + +MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file) + : PictureAsset (file) +{ + Kumu::FileReaderFactory factory; + ASDCP::JP2K::MXFReader reader(factory); + auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str()); + if (ASDCP_FAILURE(r)) { + boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r)); + } + + ASDCP::JP2K::PictureDescriptor desc; + if (ASDCP_FAILURE (reader.FillPictureDescriptor(desc))) { + boost::throw_exception (ReadError("could not read video MXF information")); + } + + read_picture_descriptor (desc); + + ASDCP::WriterInfo info; + if (ASDCP_FAILURE (reader.FillWriterInfo (info))) { + boost::throw_exception (ReadError("could not read video MXF information")); + } + + _id = read_writer_info (info); +} + + +MonoPictureAsset::MonoPictureAsset (Fraction edit_rate, Standard standard) + : PictureAsset (edit_rate, standard) +{ + +} + + +static void +storing_note_handler (list>& notes, NoteType t, string s) +{ + notes.push_back (make_pair (t, s)); +} + + +bool +MonoPictureAsset::equals(shared_ptr other, EqualityOptions const& opt, NoteHandler note) const +{ + if (!dynamic_pointer_cast(other)) { + return false; + } + + Kumu::FileReaderFactory factory; + ASDCP::JP2K::MXFReader reader_A(factory); + DCP_ASSERT (_file); + auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*_file).string().c_str()); + if (ASDCP_FAILURE(r)) { + boost::throw_exception (MXFFileError("could not open MXF file for reading", _file->string(), r)); + } + + ASDCP::JP2K::MXFReader reader_B(factory); + DCP_ASSERT (other->file ()); + r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str()); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r)); + } + + ASDCP::JP2K::PictureDescriptor desc_A; + if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) { + boost::throw_exception (ReadError ("could not read video MXF information")); + } + ASDCP::JP2K::PictureDescriptor desc_B; + if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) { + boost::throw_exception (ReadError ("could not read video MXF information")); + } + + if (!descriptor_equals (desc_A, desc_B, note)) { + return false; + } + + auto other_picture = dynamic_pointer_cast (other); + DCP_ASSERT (other_picture); + + bool result = true; + + auto reader = start_read (); + auto other_reader = other_picture->start_read (); + +#ifdef LIBDCP_OPENMP +#pragma omp parallel for +#endif + + for (int i = 0; i < _intrinsic_duration; ++i) { + if (i >= other_picture->intrinsic_duration()) { + result = false; + } + + if (result || opt.keep_going) { + + auto frame_A = reader->get_frame (i); + auto frame_B = other_reader->get_frame (i); + + list> notes; + + if (!frame_buffer_equals ( + i, opt, bind (&storing_note_handler, boost::ref(notes), _1, _2), + frame_A->data(), frame_A->size(), + frame_B->data(), frame_B->size() + )) { + result = false; + } + +#ifdef LIBDCP_OPENMP +#pragma omp critical +#endif + { + note (NoteType::PROGRESS, String::compose("Compared video frame %1 of %2", i, _intrinsic_duration)); + for (auto const& i: notes) { + note (i.first, i.second); + } + } + } + } + + return result; +} + + +shared_ptr +MonoPictureAsset::start_write(boost::filesystem::path file, Behaviour behaviour) +{ + /* Can't use make_shared here as the MonoPictureAssetWriter constructor is private */ + return shared_ptr(new MonoPictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING)); +} + +shared_ptr +MonoPictureAsset::start_read () const +{ + /* Can't use make_shared here as the MonoPictureAssetReader constructor is private */ + return shared_ptr(new MonoPictureAssetReader(this, key(), standard())); + +} + +string +MonoPictureAsset::cpl_node_name () const +{ + return "MainPicture"; +} diff --git a/src/mono_j2k_picture_asset.h b/src/mono_j2k_picture_asset.h new file mode 100644 index 00000000..9658dcf6 --- /dev/null +++ b/src/mono_j2k_picture_asset.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/mono_picture_asset.cc + * @brief MonoPictureAsset class + */ + + +#ifndef LIBDCP_MONO_PICTURE_ASSET_H +#define LIBDCP_MONO_PICTURE_ASSET_H + + +#include "picture_asset.h" +#include "mono_picture_asset_reader.h" + + +namespace dcp { + + +class MonoPictureAssetWriter; + + +/** @class MonoPictureAsset + * @brief A 2D (monoscopic) picture asset + */ +class MonoPictureAsset : public PictureAsset +{ +public: + /** Create a MonoPictureAsset by reading a file. + * @param file Asset file to read. + */ + explicit MonoPictureAsset (boost::filesystem::path file); + + /** Create a MonoPictureAsset with a given edit rate. + * @param edit_rate Edit rate (i.e. frame rate) in frames per second. + * @param standard DCP standard (INTEROP or SMPTE). + */ + MonoPictureAsset(Fraction edit_rate, Standard standard); + + /** Start a progressive write to a MonoPictureAsset. + * @path file File to write to. + * @path behaviour OVERWRITE_EXISTING to overwrite and potentially add to an existing file + * (after a write previously failed), MAKE_NEW to create a new file. + * If in doubt, use MAKE_NEW here. + */ + std::shared_ptr start_write(boost::filesystem::path file, Behaviour behaviour) override; + std::shared_ptr start_read () const; + + bool equals ( + std::shared_ptr other, + EqualityOptions const& opt, + NoteHandler note + ) const override; + +private: + std::string cpl_node_name () const; +}; + + +} + + +#endif diff --git a/src/mono_j2k_picture_asset_reader.h b/src/mono_j2k_picture_asset_reader.h new file mode 100644 index 00000000..5bead791 --- /dev/null +++ b/src/mono_j2k_picture_asset_reader.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2016-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/mono_picture_asset_reader.h + * @brief MonoPictureAssetReader typedef + */ + + +#ifndef LIBDCP_MONO_PICTURE_ASSET_READER_H +#define LIBDCP_MONO_PICTURE_ASSET_READER_H + + +#include "asset_reader.h" +#include "mono_picture_frame.h" + + +namespace dcp { + + +typedef AssetReader MonoPictureAssetReader; + + +} + + +#endif diff --git a/src/mono_j2k_picture_asset_writer.cc b/src/mono_j2k_picture_asset_writer.cc new file mode 100644 index 00000000..7fd58114 --- /dev/null +++ b/src/mono_j2k_picture_asset_writer.cc @@ -0,0 +1,151 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/mono_picture_asset_writer.cc + * @brief MonoPictureAssetWriter class + */ + + +#include "crypto_context.h" +#include "dcp_assert.h" +#include "exceptions.h" +#include "mono_picture_asset_writer.h" +#include "picture_asset.h" +#include "warnings.h" +LIBDCP_DISABLE_WARNINGS +#include +#include +LIBDCP_ENABLE_WARNINGS + + +#include "picture_asset_writer_common.cc" + + +using std::string; +using std::shared_ptr; +using namespace dcp; + + +struct MonoPictureAssetWriter::ASDCPState : public ASDCPStateBase +{ + ASDCP::JP2K::MXFWriter mxf_writer; +}; + + +/** @param a Asset to write to. `a' must not be deleted while + * this writer class still exists, or bad things will happen. + */ +MonoPictureAssetWriter::MonoPictureAssetWriter (PictureAsset* asset, boost::filesystem::path file, bool overwrite) + : PictureAssetWriter (asset, file, overwrite) + , _state (new MonoPictureAssetWriter::ASDCPState) +{ + +} + + +MonoPictureAssetWriter::~MonoPictureAssetWriter() +{ + try { + /* Last-resort finalization to close the file, at least */ + if (!_finalized) { + _state->mxf_writer.Finalize(); + } + } catch (...) {} +} + + +void +MonoPictureAssetWriter::start (uint8_t const * data, int size) +{ + dcp::start (this, _state, _picture_asset, data, size); + _picture_asset->set_frame_rate (_picture_asset->edit_rate()); +} + + +FrameInfo +MonoPictureAssetWriter::write (uint8_t const * data, int size) +{ + DCP_ASSERT (!_finalized); + + if (!_started) { + start (data, size); + } + + if (ASDCP_FAILURE (_state->j2k_parser.OpenReadFrame(data, size, _state->frame_buffer))) { + boost::throw_exception (MiscError ("could not parse J2K frame")); + } + + _state->frame_buffer.PlaintextOffset(0); + + uint64_t const before_offset = _state->mxf_writer.Tell (); + + string hash; + auto const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _crypto_context->context(), _crypto_context->hmac(), &hash); + if (ASDCP_FAILURE(r)) { + boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r)); + } + + ++_frames_written; + return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash); +} + + +void +MonoPictureAssetWriter::fake_write (int size) +{ + DCP_ASSERT (_started); + DCP_ASSERT (!_finalized); + + auto r = _state->mxf_writer.FakeWriteFrame (size); + if (ASDCP_FAILURE(r)) { + boost::throw_exception (MXFFileError("error in writing video MXF", _file.string(), r)); + } + + ++_frames_written; +} + + +bool +MonoPictureAssetWriter::finalize () +{ + if (_started) { + auto r = _state->mxf_writer.Finalize(); + if (ASDCP_FAILURE(r)) { + boost::throw_exception (MXFFileError("error in finalizing video MXF", _file.string(), r)); + } + } + + _picture_asset->_intrinsic_duration = _frames_written; + return PictureAssetWriter::finalize (); +} diff --git a/src/mono_j2k_picture_asset_writer.h b/src/mono_j2k_picture_asset_writer.h new file mode 100644 index 00000000..551d8c80 --- /dev/null +++ b/src/mono_j2k_picture_asset_writer.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/mono_picture_asset_writer.h + * @brief MonoPictureAssetWriter class + */ + + +#ifndef LIBDCP_MONO_PICTURE_ASSET_WRITER_H +#define LIBDCP_MONO_PICTURE_ASSET_WRITER_H + + +#include "picture_asset_writer.h" +#include +#include +#include +#include + + +namespace dcp { + + +/** @class MonoPictureAssetWriter + * @brief A helper class for writing to MonoPictureAssets + * + * Objects of this class can only be created with MonoPictureAsset::start_write(). + * + * Frames can be written to the MonoPictureAsset by calling write() with a JPEG2000 image + * (a verbatim .j2c file). finalize() should be called after the last frame has been written, + * but if it is not, it will be called by the destructor (though in that case any error + * during finalization will be ignored). + */ +class MonoPictureAssetWriter : public PictureAssetWriter +{ +public: + ~MonoPictureAssetWriter(); + + FrameInfo write (uint8_t const *, int) override; + void fake_write (int size) override; + bool finalize () override; + +private: + friend class MonoPictureAsset; + + MonoPictureAssetWriter (PictureAsset* a, boost::filesystem::path file, bool); + + void start (uint8_t const *, int); + + /* do this with an opaque pointer so we don't have to include + ASDCP headers + */ + struct ASDCPState; + std::shared_ptr _state; +}; + + +} + + +#endif diff --git a/src/mono_j2k_picture_frame.cc b/src/mono_j2k_picture_frame.cc new file mode 100644 index 00000000..2abd57e4 --- /dev/null +++ b/src/mono_j2k_picture_frame.cc @@ -0,0 +1,130 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/mono_picture_frame.cc + * @brief MonoPictureFrame class + */ + + +#include "colour_conversion.h" +#include "compose.hpp" +#include "crypto_context.h" +#include "exceptions.h" +#include "file.h" +#include "filesystem.h" +#include "j2k_transcode.h" +#include "mono_picture_frame.h" +#include "rgb_xyz.h" +#include "util.h" +#include +#include + + +using std::make_shared; +using std::string; +using std::shared_ptr; +using boost::optional; +using namespace dcp; + + +MonoPictureFrame::MonoPictureFrame (boost::filesystem::path path) +{ + auto const size = filesystem::file_size(path); + _buffer.reset(new ASDCP::JP2K::FrameBuffer(size)); + File f(path, "rb"); + if (!f) { + boost::throw_exception (FileError("could not open JPEG2000 file", path, errno)); + } + + if (f.read(data(), 1, size) != size) { + boost::throw_exception (FileError("could not read from JPEG2000 file", path, errno)); + } + + _buffer->Size (size); +} + + +/** Make a picture frame from a 2D (monoscopic) asset. + * @param reader Reader for the asset's MXF file. + * @param n Frame within the asset, not taking EntryPoint into account. + * @param c Context for decryption, or 0. + * @param check_hmac true to check the HMAC and give an error if it is not as expected. + */ +MonoPictureFrame::MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, shared_ptr c, bool check_hmac) +{ + /* XXX: unfortunate guesswork on this buffer size */ + _buffer = make_shared(4 * Kumu::Megabyte); + + auto const r = reader->ReadFrame (n, *_buffer, c->context(), check_hmac ? c->hmac() : nullptr); + + if (ASDCP_FAILURE(r)) { + boost::throw_exception (ReadError(String::compose ("could not read video frame %1 (%2)", n, static_cast(r)))); + } +} + + +MonoPictureFrame::MonoPictureFrame (uint8_t const * data, int size) +{ + _buffer = make_shared(size); + _buffer->Size (size); + memcpy (_buffer->Data(), data, size); +} + + +uint8_t const * +MonoPictureFrame::data () const +{ + return _buffer->RoData (); +} + + +uint8_t * +MonoPictureFrame::data () +{ + return _buffer->Data (); +} + + +int +MonoPictureFrame::size () const +{ + return _buffer->Size (); +} + + +shared_ptr +MonoPictureFrame::xyz_image (int reduce) const +{ + return decompress_j2k (const_cast(_buffer->RoData()), _buffer->Size(), reduce); +} diff --git a/src/mono_j2k_picture_frame.h b/src/mono_j2k_picture_frame.h new file mode 100644 index 00000000..43575864 --- /dev/null +++ b/src/mono_j2k_picture_frame.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/mono_picture_frame.h + * @brief MonoPictureFrame class + */ + + +#ifndef LIBDCP_MONO_PICTURE_FRAME_H +#define LIBDCP_MONO_PICTURE_FRAME_H + + +#include "asset_reader.h" +#include +#include +#include +#include +#include + + +namespace ASDCP { + namespace JP2K { + class FrameBuffer; + class MXFReader; + } + class AESDecContext; +} + + +namespace dcp { + + +class OpenJPEGImage; + + +/** @class MonoPictureFrame + * @brief A single frame of a 2D (monoscopic) picture asset + */ +class MonoPictureFrame : public Data +{ +public: + /** Make a picture frame from a JPEG2000 file. + * @param path Path to JPEG2000 file. + */ + explicit MonoPictureFrame (boost::filesystem::path path); + MonoPictureFrame (uint8_t const * data, int size); + + MonoPictureFrame (MonoPictureFrame const&) = delete; + MonoPictureFrame& operator= (MonoPictureFrame const&) = delete; + + /** @param reduce a factor by which to reduce the resolution + * of the image, expressed as a power of two (pass 0 for no + * reduction). + */ + std::shared_ptr xyz_image (int reduce = 0) const; + + /** @return Pointer to JPEG2000 data */ + uint8_t const * data () const override; + + /** @return Pointer to JPEG2000 data */ + uint8_t* data () override; + + /** @return Size of JPEG2000 data in bytes */ + int size () const override; + +private: + /* XXX: this is a bit of a shame, but I tried friend MonoPictureAssetReader and it's + rejected by some (seemingly older) GCCs. + */ + friend class AssetReader; + + MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, std::shared_ptr, bool check_hmac); + + std::shared_ptr _buffer; +}; + +} + +#endif diff --git a/src/mono_picture_asset.cc b/src/mono_picture_asset.cc deleted file mode 100644 index 9a0beb42..00000000 --- a/src/mono_picture_asset.cc +++ /dev/null @@ -1,208 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/mono_picture_asset.cc - * @brief MonoPictureAsset class - */ - - -#include "compose.hpp" -#include "dcp_assert.h" -#include "equality_options.h" -#include "exceptions.h" -#include "filesystem.h" -#include "mono_picture_asset.h" -#include "mono_picture_asset_reader.h" -#include "mono_picture_asset_writer.h" -#include "mono_picture_frame.h" -#include -#include - - -using std::dynamic_pointer_cast; -using std::list; -using std::make_shared; -using std::pair; -using std::shared_ptr; -using std::string; -using std::vector; -#if BOOST_VERSION >= 106100 -using namespace boost::placeholders; -#endif -using namespace dcp; - - -MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file) - : PictureAsset (file) -{ - Kumu::FileReaderFactory factory; - ASDCP::JP2K::MXFReader reader(factory); - auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str()); - if (ASDCP_FAILURE(r)) { - boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r)); - } - - ASDCP::JP2K::PictureDescriptor desc; - if (ASDCP_FAILURE (reader.FillPictureDescriptor(desc))) { - boost::throw_exception (ReadError("could not read video MXF information")); - } - - read_picture_descriptor (desc); - - ASDCP::WriterInfo info; - if (ASDCP_FAILURE (reader.FillWriterInfo (info))) { - boost::throw_exception (ReadError("could not read video MXF information")); - } - - _id = read_writer_info (info); -} - - -MonoPictureAsset::MonoPictureAsset (Fraction edit_rate, Standard standard) - : PictureAsset (edit_rate, standard) -{ - -} - - -static void -storing_note_handler (list>& notes, NoteType t, string s) -{ - notes.push_back (make_pair (t, s)); -} - - -bool -MonoPictureAsset::equals(shared_ptr other, EqualityOptions const& opt, NoteHandler note) const -{ - if (!dynamic_pointer_cast(other)) { - return false; - } - - Kumu::FileReaderFactory factory; - ASDCP::JP2K::MXFReader reader_A(factory); - DCP_ASSERT (_file); - auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*_file).string().c_str()); - if (ASDCP_FAILURE(r)) { - boost::throw_exception (MXFFileError("could not open MXF file for reading", _file->string(), r)); - } - - ASDCP::JP2K::MXFReader reader_B(factory); - DCP_ASSERT (other->file ()); - r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str()); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r)); - } - - ASDCP::JP2K::PictureDescriptor desc_A; - if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) { - boost::throw_exception (ReadError ("could not read video MXF information")); - } - ASDCP::JP2K::PictureDescriptor desc_B; - if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) { - boost::throw_exception (ReadError ("could not read video MXF information")); - } - - if (!descriptor_equals (desc_A, desc_B, note)) { - return false; - } - - auto other_picture = dynamic_pointer_cast (other); - DCP_ASSERT (other_picture); - - bool result = true; - - auto reader = start_read (); - auto other_reader = other_picture->start_read (); - -#ifdef LIBDCP_OPENMP -#pragma omp parallel for -#endif - - for (int i = 0; i < _intrinsic_duration; ++i) { - if (i >= other_picture->intrinsic_duration()) { - result = false; - } - - if (result || opt.keep_going) { - - auto frame_A = reader->get_frame (i); - auto frame_B = other_reader->get_frame (i); - - list> notes; - - if (!frame_buffer_equals ( - i, opt, bind (&storing_note_handler, boost::ref(notes), _1, _2), - frame_A->data(), frame_A->size(), - frame_B->data(), frame_B->size() - )) { - result = false; - } - -#ifdef LIBDCP_OPENMP -#pragma omp critical -#endif - { - note (NoteType::PROGRESS, String::compose("Compared video frame %1 of %2", i, _intrinsic_duration)); - for (auto const& i: notes) { - note (i.first, i.second); - } - } - } - } - - return result; -} - - -shared_ptr -MonoPictureAsset::start_write(boost::filesystem::path file, Behaviour behaviour) -{ - /* Can't use make_shared here as the MonoPictureAssetWriter constructor is private */ - return shared_ptr(new MonoPictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING)); -} - -shared_ptr -MonoPictureAsset::start_read () const -{ - /* Can't use make_shared here as the MonoPictureAssetReader constructor is private */ - return shared_ptr(new MonoPictureAssetReader(this, key(), standard())); - -} - -string -MonoPictureAsset::cpl_node_name () const -{ - return "MainPicture"; -} diff --git a/src/mono_picture_asset.h b/src/mono_picture_asset.h deleted file mode 100644 index 9658dcf6..00000000 --- a/src/mono_picture_asset.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/mono_picture_asset.cc - * @brief MonoPictureAsset class - */ - - -#ifndef LIBDCP_MONO_PICTURE_ASSET_H -#define LIBDCP_MONO_PICTURE_ASSET_H - - -#include "picture_asset.h" -#include "mono_picture_asset_reader.h" - - -namespace dcp { - - -class MonoPictureAssetWriter; - - -/** @class MonoPictureAsset - * @brief A 2D (monoscopic) picture asset - */ -class MonoPictureAsset : public PictureAsset -{ -public: - /** Create a MonoPictureAsset by reading a file. - * @param file Asset file to read. - */ - explicit MonoPictureAsset (boost::filesystem::path file); - - /** Create a MonoPictureAsset with a given edit rate. - * @param edit_rate Edit rate (i.e. frame rate) in frames per second. - * @param standard DCP standard (INTEROP or SMPTE). - */ - MonoPictureAsset(Fraction edit_rate, Standard standard); - - /** Start a progressive write to a MonoPictureAsset. - * @path file File to write to. - * @path behaviour OVERWRITE_EXISTING to overwrite and potentially add to an existing file - * (after a write previously failed), MAKE_NEW to create a new file. - * If in doubt, use MAKE_NEW here. - */ - std::shared_ptr start_write(boost::filesystem::path file, Behaviour behaviour) override; - std::shared_ptr start_read () const; - - bool equals ( - std::shared_ptr other, - EqualityOptions const& opt, - NoteHandler note - ) const override; - -private: - std::string cpl_node_name () const; -}; - - -} - - -#endif diff --git a/src/mono_picture_asset_reader.h b/src/mono_picture_asset_reader.h deleted file mode 100644 index 5bead791..00000000 --- a/src/mono_picture_asset_reader.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2016-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/mono_picture_asset_reader.h - * @brief MonoPictureAssetReader typedef - */ - - -#ifndef LIBDCP_MONO_PICTURE_ASSET_READER_H -#define LIBDCP_MONO_PICTURE_ASSET_READER_H - - -#include "asset_reader.h" -#include "mono_picture_frame.h" - - -namespace dcp { - - -typedef AssetReader MonoPictureAssetReader; - - -} - - -#endif diff --git a/src/mono_picture_asset_writer.cc b/src/mono_picture_asset_writer.cc deleted file mode 100644 index 7fd58114..00000000 --- a/src/mono_picture_asset_writer.cc +++ /dev/null @@ -1,151 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/mono_picture_asset_writer.cc - * @brief MonoPictureAssetWriter class - */ - - -#include "crypto_context.h" -#include "dcp_assert.h" -#include "exceptions.h" -#include "mono_picture_asset_writer.h" -#include "picture_asset.h" -#include "warnings.h" -LIBDCP_DISABLE_WARNINGS -#include -#include -LIBDCP_ENABLE_WARNINGS - - -#include "picture_asset_writer_common.cc" - - -using std::string; -using std::shared_ptr; -using namespace dcp; - - -struct MonoPictureAssetWriter::ASDCPState : public ASDCPStateBase -{ - ASDCP::JP2K::MXFWriter mxf_writer; -}; - - -/** @param a Asset to write to. `a' must not be deleted while - * this writer class still exists, or bad things will happen. - */ -MonoPictureAssetWriter::MonoPictureAssetWriter (PictureAsset* asset, boost::filesystem::path file, bool overwrite) - : PictureAssetWriter (asset, file, overwrite) - , _state (new MonoPictureAssetWriter::ASDCPState) -{ - -} - - -MonoPictureAssetWriter::~MonoPictureAssetWriter() -{ - try { - /* Last-resort finalization to close the file, at least */ - if (!_finalized) { - _state->mxf_writer.Finalize(); - } - } catch (...) {} -} - - -void -MonoPictureAssetWriter::start (uint8_t const * data, int size) -{ - dcp::start (this, _state, _picture_asset, data, size); - _picture_asset->set_frame_rate (_picture_asset->edit_rate()); -} - - -FrameInfo -MonoPictureAssetWriter::write (uint8_t const * data, int size) -{ - DCP_ASSERT (!_finalized); - - if (!_started) { - start (data, size); - } - - if (ASDCP_FAILURE (_state->j2k_parser.OpenReadFrame(data, size, _state->frame_buffer))) { - boost::throw_exception (MiscError ("could not parse J2K frame")); - } - - _state->frame_buffer.PlaintextOffset(0); - - uint64_t const before_offset = _state->mxf_writer.Tell (); - - string hash; - auto const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _crypto_context->context(), _crypto_context->hmac(), &hash); - if (ASDCP_FAILURE(r)) { - boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r)); - } - - ++_frames_written; - return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash); -} - - -void -MonoPictureAssetWriter::fake_write (int size) -{ - DCP_ASSERT (_started); - DCP_ASSERT (!_finalized); - - auto r = _state->mxf_writer.FakeWriteFrame (size); - if (ASDCP_FAILURE(r)) { - boost::throw_exception (MXFFileError("error in writing video MXF", _file.string(), r)); - } - - ++_frames_written; -} - - -bool -MonoPictureAssetWriter::finalize () -{ - if (_started) { - auto r = _state->mxf_writer.Finalize(); - if (ASDCP_FAILURE(r)) { - boost::throw_exception (MXFFileError("error in finalizing video MXF", _file.string(), r)); - } - } - - _picture_asset->_intrinsic_duration = _frames_written; - return PictureAssetWriter::finalize (); -} diff --git a/src/mono_picture_asset_writer.h b/src/mono_picture_asset_writer.h deleted file mode 100644 index 551d8c80..00000000 --- a/src/mono_picture_asset_writer.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/mono_picture_asset_writer.h - * @brief MonoPictureAssetWriter class - */ - - -#ifndef LIBDCP_MONO_PICTURE_ASSET_WRITER_H -#define LIBDCP_MONO_PICTURE_ASSET_WRITER_H - - -#include "picture_asset_writer.h" -#include -#include -#include -#include - - -namespace dcp { - - -/** @class MonoPictureAssetWriter - * @brief A helper class for writing to MonoPictureAssets - * - * Objects of this class can only be created with MonoPictureAsset::start_write(). - * - * Frames can be written to the MonoPictureAsset by calling write() with a JPEG2000 image - * (a verbatim .j2c file). finalize() should be called after the last frame has been written, - * but if it is not, it will be called by the destructor (though in that case any error - * during finalization will be ignored). - */ -class MonoPictureAssetWriter : public PictureAssetWriter -{ -public: - ~MonoPictureAssetWriter(); - - FrameInfo write (uint8_t const *, int) override; - void fake_write (int size) override; - bool finalize () override; - -private: - friend class MonoPictureAsset; - - MonoPictureAssetWriter (PictureAsset* a, boost::filesystem::path file, bool); - - void start (uint8_t const *, int); - - /* do this with an opaque pointer so we don't have to include - ASDCP headers - */ - struct ASDCPState; - std::shared_ptr _state; -}; - - -} - - -#endif diff --git a/src/mono_picture_frame.cc b/src/mono_picture_frame.cc deleted file mode 100644 index 2abd57e4..00000000 --- a/src/mono_picture_frame.cc +++ /dev/null @@ -1,130 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/mono_picture_frame.cc - * @brief MonoPictureFrame class - */ - - -#include "colour_conversion.h" -#include "compose.hpp" -#include "crypto_context.h" -#include "exceptions.h" -#include "file.h" -#include "filesystem.h" -#include "j2k_transcode.h" -#include "mono_picture_frame.h" -#include "rgb_xyz.h" -#include "util.h" -#include -#include - - -using std::make_shared; -using std::string; -using std::shared_ptr; -using boost::optional; -using namespace dcp; - - -MonoPictureFrame::MonoPictureFrame (boost::filesystem::path path) -{ - auto const size = filesystem::file_size(path); - _buffer.reset(new ASDCP::JP2K::FrameBuffer(size)); - File f(path, "rb"); - if (!f) { - boost::throw_exception (FileError("could not open JPEG2000 file", path, errno)); - } - - if (f.read(data(), 1, size) != size) { - boost::throw_exception (FileError("could not read from JPEG2000 file", path, errno)); - } - - _buffer->Size (size); -} - - -/** Make a picture frame from a 2D (monoscopic) asset. - * @param reader Reader for the asset's MXF file. - * @param n Frame within the asset, not taking EntryPoint into account. - * @param c Context for decryption, or 0. - * @param check_hmac true to check the HMAC and give an error if it is not as expected. - */ -MonoPictureFrame::MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, shared_ptr c, bool check_hmac) -{ - /* XXX: unfortunate guesswork on this buffer size */ - _buffer = make_shared(4 * Kumu::Megabyte); - - auto const r = reader->ReadFrame (n, *_buffer, c->context(), check_hmac ? c->hmac() : nullptr); - - if (ASDCP_FAILURE(r)) { - boost::throw_exception (ReadError(String::compose ("could not read video frame %1 (%2)", n, static_cast(r)))); - } -} - - -MonoPictureFrame::MonoPictureFrame (uint8_t const * data, int size) -{ - _buffer = make_shared(size); - _buffer->Size (size); - memcpy (_buffer->Data(), data, size); -} - - -uint8_t const * -MonoPictureFrame::data () const -{ - return _buffer->RoData (); -} - - -uint8_t * -MonoPictureFrame::data () -{ - return _buffer->Data (); -} - - -int -MonoPictureFrame::size () const -{ - return _buffer->Size (); -} - - -shared_ptr -MonoPictureFrame::xyz_image (int reduce) const -{ - return decompress_j2k (const_cast(_buffer->RoData()), _buffer->Size(), reduce); -} diff --git a/src/mono_picture_frame.h b/src/mono_picture_frame.h deleted file mode 100644 index 43575864..00000000 --- a/src/mono_picture_frame.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/mono_picture_frame.h - * @brief MonoPictureFrame class - */ - - -#ifndef LIBDCP_MONO_PICTURE_FRAME_H -#define LIBDCP_MONO_PICTURE_FRAME_H - - -#include "asset_reader.h" -#include -#include -#include -#include -#include - - -namespace ASDCP { - namespace JP2K { - class FrameBuffer; - class MXFReader; - } - class AESDecContext; -} - - -namespace dcp { - - -class OpenJPEGImage; - - -/** @class MonoPictureFrame - * @brief A single frame of a 2D (monoscopic) picture asset - */ -class MonoPictureFrame : public Data -{ -public: - /** Make a picture frame from a JPEG2000 file. - * @param path Path to JPEG2000 file. - */ - explicit MonoPictureFrame (boost::filesystem::path path); - MonoPictureFrame (uint8_t const * data, int size); - - MonoPictureFrame (MonoPictureFrame const&) = delete; - MonoPictureFrame& operator= (MonoPictureFrame const&) = delete; - - /** @param reduce a factor by which to reduce the resolution - * of the image, expressed as a power of two (pass 0 for no - * reduction). - */ - std::shared_ptr xyz_image (int reduce = 0) const; - - /** @return Pointer to JPEG2000 data */ - uint8_t const * data () const override; - - /** @return Pointer to JPEG2000 data */ - uint8_t* data () override; - - /** @return Size of JPEG2000 data in bytes */ - int size () const override; - -private: - /* XXX: this is a bit of a shame, but I tried friend MonoPictureAssetReader and it's - rejected by some (seemingly older) GCCs. - */ - friend class AssetReader; - - MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, std::shared_ptr, bool check_hmac); - - std::shared_ptr _buffer; -}; - -} - -#endif diff --git a/src/picture_asset.cc b/src/picture_asset.cc deleted file mode 100644 index c9f669a6..00000000 --- a/src/picture_asset.cc +++ /dev/null @@ -1,230 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/picture_asset.cc - * @brief PictureAsset class - */ - - -#include "compose.hpp" -#include "dcp_assert.h" -#include "equality_options.h" -#include "exceptions.h" -#include "j2k_transcode.h" -#include "openjpeg_image.h" -#include "picture_asset.h" -#include "picture_asset_writer.h" -#include "util.h" -#include -#include -#include -#include -#include -#include - - -using std::string; -using std::list; -using std::vector; -using std::max; -using std::pair; -using std::make_pair; -using std::shared_ptr; -using namespace dcp; - - -PictureAsset::PictureAsset (boost::filesystem::path file) - : Asset (file) -{ - -} - - -PictureAsset::PictureAsset (Fraction edit_rate, Standard standard) - : MXF (standard) - , _edit_rate (edit_rate) -{ - -} - - -void -PictureAsset::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc) -{ - _size.width = desc.StoredWidth; - _size.height = desc.StoredHeight; - _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator); - _intrinsic_duration = desc.ContainerDuration; - _frame_rate = Fraction (desc.SampleRate.Numerator, desc.SampleRate.Denominator); - _screen_aspect_ratio = Fraction (desc.AspectRatio.Numerator, desc.AspectRatio.Denominator); -} - - -bool -PictureAsset::descriptor_equals ( - ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, NoteHandler note - ) const -{ - if ( - a.EditRate != b.EditRate || - a.SampleRate != b.SampleRate || - a.StoredWidth != b.StoredWidth || - a.StoredHeight != b.StoredHeight || - a.AspectRatio != b.AspectRatio || - a.Rsize != b.Rsize || - a.Xsize != b.Xsize || - a.Ysize != b.Ysize || - a.XOsize != b.XOsize || - a.YOsize != b.YOsize || - a.XTsize != b.XTsize || - a.YTsize != b.YTsize || - a.XTOsize != b.XTOsize || - a.YTOsize != b.YTOsize || - a.Csize != b.Csize -// a.CodingStyleDefault != b.CodingStyleDefault || -// a.QuantizationDefault != b.QuantizationDefault - ) { - - note (NoteType::ERROR, "video MXF picture descriptors differ"); - return false; - } - - if (a.ContainerDuration != b.ContainerDuration) { - note (NoteType::ERROR, "video container durations differ"); - } - -// for (unsigned int j = 0; j < ASDCP::JP2K::MaxComponents; ++j) { -// if (a.ImageComponents[j] != b.ImageComponents[j]) { -// notes.pack_start ("video MXF picture descriptors differ"); -// } -// } - - return true; -} - - -bool -PictureAsset::frame_buffer_equals ( - int frame, EqualityOptions const& opt, NoteHandler note, - uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B - ) const -{ - if (size_A == size_B && memcmp (data_A, data_B, size_A) == 0) { - note (NoteType::NOTE, "J2K identical"); - /* Easy result; the J2K data is identical */ - return true; - } - - /* Decompress the images to bitmaps */ - auto image_A = decompress_j2k (const_cast(data_A), size_A, 0); - auto image_B = decompress_j2k (const_cast(data_B), size_B, 0); - - /* Compare them */ - - vector abs_diffs (image_A->size().width * image_A->size().height * 3); - int d = 0; - int max_diff = 0; - - for (int c = 0; c < 3; ++c) { - - if (image_A->size() != image_B->size()) { - note (NoteType::ERROR, String::compose ("image sizes for frame %1 differ", frame)); - return false; - } - - int const pixels = image_A->size().width * image_A->size().height; - for (int j = 0; j < pixels; ++j) { - int const t = abs (image_A->data(c)[j] - image_B->data(c)[j]); - abs_diffs[d++] = t; - max_diff = max (max_diff, t); - } - } - - uint64_t total = 0; - for (vector::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) { - total += *j; - } - - double const mean = double (total) / abs_diffs.size (); - - uint64_t total_squared_deviation = 0; - for (auto j: abs_diffs) { - total_squared_deviation += pow (j - mean, 2); - } - - auto const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size()); - - note (NoteType::NOTE, String::compose("mean difference %1 deviation %2", mean, std_dev)); - - if (mean > opt.max_mean_pixel_error) { - note ( - NoteType::ERROR, - String::compose ("mean %1 out of range %2 in frame %3", mean, opt.max_mean_pixel_error, frame) - ); - - return false; - } - - if (std_dev > opt.max_std_dev_pixel_error) { - note ( - NoteType::ERROR, - String::compose ("standard deviation %1 out of range %2 in frame %3", std_dev, opt.max_std_dev_pixel_error, frame) - ); - - return false; - } - - return true; -} - - -string -PictureAsset::static_pkl_type (Standard standard) -{ - switch (standard) { - case Standard::INTEROP: - return "application/x-smpte-mxf;asdcpKind=Picture"; - case Standard::SMPTE: - return "application/mxf"; - default: - DCP_ASSERT (false); - } -} - - -string -PictureAsset::pkl_type (Standard standard) const -{ - return static_pkl_type (standard); -} diff --git a/src/picture_asset.h b/src/picture_asset.h deleted file mode 100644 index 9ad1eb22..00000000 --- a/src/picture_asset.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/picture_asset.h - * @brief PictureAsset class - */ - - -#ifndef LIBDCP_PICTURE_ASSET_H -#define LIBDCP_PICTURE_ASSET_H - - -#include "mxf.h" -#include "util.h" -#include "metadata.h" - - -namespace ASDCP { - namespace JP2K { - struct PictureDescriptor; - } -} - - -namespace dcp { - - -class MonoPictureFrame; -class StereoPictureFrame; -class PictureAssetWriter; - - -/** @class PictureAsset - * @brief An asset made up of JPEG2000 data - */ -class PictureAsset : public Asset, public MXF -{ -public: - /** Load a PictureAsset from a file */ - explicit PictureAsset (boost::filesystem::path file); - - /** Create a new PictureAsset with a given edit rate and standard */ - PictureAsset(Fraction edit_rate, Standard standard); - - enum class Behaviour { - OVERWRITE_EXISTING, - MAKE_NEW - }; - - virtual std::shared_ptr start_write ( - boost::filesystem::path file, - Behaviour behaviour - ) = 0; - - Size size () const { - return _size; - } - - void set_size (Size s) { - _size = s; - } - - Fraction frame_rate () const { - return _frame_rate; - } - - void set_frame_rate (Fraction r) { - _frame_rate = r; - } - - Fraction screen_aspect_ratio () const { - return _screen_aspect_ratio; - } - - void set_screen_aspect_ratio (Fraction r) { - _screen_aspect_ratio = r; - } - - Fraction edit_rate () const { - return _edit_rate; - } - - int64_t intrinsic_duration () const { - return _intrinsic_duration; - } - - static std::string static_pkl_type (Standard standard); - -protected: - friend class MonoPictureAssetWriter; - friend class StereoPictureAssetWriter; - - bool frame_buffer_equals ( - int frame, EqualityOptions const& opt, NoteHandler note, - uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B - ) const; - - bool descriptor_equals ( - ASDCP::JP2K::PictureDescriptor const & a, - ASDCP::JP2K::PictureDescriptor const & b, - NoteHandler note - ) const; - - void read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const &); - - Fraction _edit_rate; - /** The total length of this content in video frames. The amount of - * content presented may be less than this. - */ - int64_t _intrinsic_duration = 0; - /** picture size in pixels */ - Size _size; - Fraction _frame_rate; - Fraction _screen_aspect_ratio; - -private: - std::string pkl_type (Standard standard) const override; -}; - - -} - - -#endif diff --git a/src/picture_asset_writer.cc b/src/picture_asset_writer.cc deleted file mode 100644 index c30be1bc..00000000 --- a/src/picture_asset_writer.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/picture_asset_writer.cc - * @brief PictureAssetWriter and FrameInfo classes - */ - - -#include "picture_asset_writer.h" -#include "exceptions.h" -#include "picture_asset.h" -#include -#include -#include -#include - - -using std::string; -using std::shared_ptr; -using namespace dcp; - - -PictureAssetWriter::PictureAssetWriter (PictureAsset* asset, boost::filesystem::path file, bool overwrite) - : AssetWriter (asset, file) - , _picture_asset (asset) - , _overwrite (overwrite) -{ - asset->set_file (file); -} - - -FrameInfo -PictureAssetWriter::write (Data const& data) -{ - return write (data.data(), data.size()); -} diff --git a/src/picture_asset_writer.h b/src/picture_asset_writer.h deleted file mode 100644 index 0caa8815..00000000 --- a/src/picture_asset_writer.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/picture_asset_writer.h - * @brief PictureAssetWriter and FrameInfo classes. - */ - - -#ifndef LIBDCP_PICTURE_ASSET_WRITER_H -#define LIBDCP_PICTURE_ASSET_WRITER_H - - -#include "asset_writer.h" -#include "metadata.h" -#include -#include -#include -#include - - -namespace dcp { - - -class Data; -class PictureAsset; - - -/** @class FrameInfo - * @brief Information about a single frame (either a monoscopic frame or a left *or* right eye stereoscopic frame) - */ -struct FrameInfo -{ - FrameInfo () {} - - FrameInfo (uint64_t o, uint64_t s, std::string h) - : offset (o) - , size (s) - , hash (h) - {} - - uint64_t offset = 0; - uint64_t size = 0; - std::string hash; -}; - - -/** @class PictureAssetWriter - * @brief Parent class for classes which write picture assets. - */ -class PictureAssetWriter : public AssetWriter -{ -public: - virtual FrameInfo write (uint8_t const *, int) = 0; - virtual void fake_write (int) = 0; - - FrameInfo write (Data const& data); - -protected: - template - friend void start (PictureAssetWriter *, std::shared_ptr

, Q *, uint8_t const *, int); - - PictureAssetWriter (PictureAsset *, boost::filesystem::path, bool); - - PictureAsset* _picture_asset = nullptr; - bool _overwrite = false; -}; - - -} - - -#endif diff --git a/src/picture_asset_writer_common.cc b/src/picture_asset_writer_common.cc deleted file mode 100644 index 82866aac..00000000 --- a/src/picture_asset_writer_common.cc +++ /dev/null @@ -1,95 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/picture_asset_writer_common.cc - * @brief Common parts of PictureAssetWriter - */ - - -#include "filesystem.h" - - -using std::shared_ptr; - - -namespace dcp { - - -struct ASDCPStateBase -{ - ASDCPStateBase () - : frame_buffer (4 * Kumu::Megabyte) - {} - - ASDCP::JP2K::CodestreamParser j2k_parser; - ASDCP::JP2K::FrameBuffer frame_buffer; - ASDCP::WriterInfo writer_info; - ASDCP::JP2K::PictureDescriptor picture_descriptor; -}; - - -} - - -template -void dcp::start (PictureAssetWriter* writer, shared_ptr

state, Q* asset, uint8_t const * data, int size) -{ - asset->set_file (writer->_file); - - if (ASDCP_FAILURE (state->j2k_parser.OpenReadFrame(data, size, state->frame_buffer))) { - boost::throw_exception (MiscError ("could not parse J2K frame")); - } - - state->j2k_parser.FillPictureDescriptor (state->picture_descriptor); - state->picture_descriptor.EditRate = ASDCP::Rational (asset->edit_rate().numerator, asset->edit_rate().denominator); - - asset->set_size (Size (state->picture_descriptor.StoredWidth, state->picture_descriptor.StoredHeight)); - asset->set_screen_aspect_ratio (Fraction (state->picture_descriptor.AspectRatio.Numerator, state->picture_descriptor.AspectRatio.Denominator)); - - asset->fill_writer_info (&state->writer_info, asset->id()); - - auto r = state->mxf_writer.OpenWrite( - dcp::filesystem::fix_long_path(*asset->file()).string().c_str(), - state->writer_info, - state->picture_descriptor, - 16384, - writer->_overwrite - ); - - if (ASDCP_FAILURE(r)) { - boost::throw_exception (MXFFileError("could not open MXF file for writing", asset->file()->string(), r)); - } - - writer->_started = true; -} diff --git a/src/stereo_j2k_picture_asset.cc b/src/stereo_j2k_picture_asset.cc new file mode 100644 index 00000000..687d8572 --- /dev/null +++ b/src/stereo_j2k_picture_asset.cc @@ -0,0 +1,183 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/stereo_picture_asset.cc + * @brief StereoPictureAsset class + */ + + +#include "dcp_assert.h" +#include "equality_options.h" +#include "exceptions.h" +#include "filesystem.h" +#include "stereo_picture_asset.h" +#include "stereo_picture_asset_reader.h" +#include "stereo_picture_asset_writer.h" +#include "stereo_picture_frame.h" +#include + + +using std::string; +using std::pair; +using std::make_pair; +using std::shared_ptr; +using std::dynamic_pointer_cast; +using namespace dcp; + + +StereoPictureAsset::StereoPictureAsset (boost::filesystem::path file) + : PictureAsset (file) +{ + Kumu::FileReaderFactory factory; + ASDCP::JP2K::MXFSReader reader(factory); + auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str()); + if (ASDCP_FAILURE(r)) { + boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r)); + } + + ASDCP::JP2K::PictureDescriptor desc; + if (ASDCP_FAILURE (reader.FillPictureDescriptor(desc))) { + boost::throw_exception (ReadError("could not read video MXF information")); + } + + read_picture_descriptor (desc); + + ASDCP::WriterInfo info; + if (ASDCP_FAILURE (reader.FillWriterInfo(info))) { + boost::throw_exception (ReadError("could not read video MXF information")); + } + + _id = read_writer_info (info); +} + + +StereoPictureAsset::StereoPictureAsset (Fraction edit_rate, Standard standard) + : PictureAsset (edit_rate, standard) +{ + +} + + +shared_ptr +StereoPictureAsset::start_write(boost::filesystem::path file, Behaviour behaviour) +{ + return shared_ptr(new StereoPictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING)); +} + + +shared_ptr +StereoPictureAsset::start_read () const +{ + return shared_ptr (new StereoPictureAssetReader(this, key(), standard())); +} + + +bool +StereoPictureAsset::equals(shared_ptr other, EqualityOptions const& opt, NoteHandler note) const +{ + Kumu::FileReaderFactory factory; + ASDCP::JP2K::MXFSReader reader_A(factory); + DCP_ASSERT (file()); + auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*file()).string().c_str()); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("could not open MXF file for reading", file()->string(), r)); + } + + ASDCP::JP2K::MXFSReader reader_B(factory); + DCP_ASSERT (other->file()); + r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str()); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r)); + } + + ASDCP::JP2K::PictureDescriptor desc_A; + if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) { + boost::throw_exception (ReadError ("could not read video MXF information")); + } + ASDCP::JP2K::PictureDescriptor desc_B; + if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) { + boost::throw_exception (ReadError ("could not read video MXF information")); + } + + if (!descriptor_equals (desc_A, desc_B, note)) { + return false; + } + + auto other_picture = dynamic_pointer_cast (other); + DCP_ASSERT (other_picture); + + auto reader = start_read (); + auto other_reader = other_picture->start_read (); + + bool result = true; + + for (int i = 0; i < _intrinsic_duration; ++i) { + shared_ptr frame_A; + shared_ptr frame_B; + try { + frame_A = reader->get_frame (i); + frame_B = other_reader->get_frame (i); + } catch (ReadError& e) { + /* If there was a problem reading the frame data we'll just assume + the two frames are not equal. + */ + note (NoteType::ERROR, e.what ()); + return false; + } + + if (!frame_buffer_equals ( + i, opt, note, + frame_A->left()->data(), frame_A->left()->size(), + frame_B->left()->data(), frame_B->left()->size() + )) { + result = false; + if (!opt.keep_going) { + return result; + } + } + + if (!frame_buffer_equals ( + i, opt, note, + frame_A->right()->data(), frame_A->right()->size(), + frame_B->right()->data(), frame_B->right()->size() + )) { + result = false; + if (!opt.keep_going) { + return result; + } + } + } + + return result; +} diff --git a/src/stereo_j2k_picture_asset.h b/src/stereo_j2k_picture_asset.h new file mode 100644 index 00000000..6ee1d423 --- /dev/null +++ b/src/stereo_j2k_picture_asset.h @@ -0,0 +1,75 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/stereo_picture_asset.h + * @brief StereoPictureAsset class + */ + + +#ifndef LIBDCP_STEREO_PICTURE_ASSET_H +#define LIBDCP_STEREO_PICTURE_ASSET_H + + +#include "picture_asset.h" +#include "stereo_picture_asset_reader.h" + + +namespace dcp { + + +/** @class StereoPictureAsset + * @brief A 3D (stereoscopic) picture asset + */ +class StereoPictureAsset : public PictureAsset +{ +public: + explicit StereoPictureAsset (boost::filesystem::path file); + explicit StereoPictureAsset (Fraction edit_rate, Standard standard); + + /** Start a progressive write to a StereoPictureAsset */ + std::shared_ptr start_write(boost::filesystem::path file, Behaviour behaviour) override; + std::shared_ptr start_read () const; + + bool equals ( + std::shared_ptr other, + EqualityOptions const& opt, + NoteHandler note + ) const override; +}; + + +} + + +#endif diff --git a/src/stereo_j2k_picture_asset_reader.h b/src/stereo_j2k_picture_asset_reader.h new file mode 100644 index 00000000..9cb05263 --- /dev/null +++ b/src/stereo_j2k_picture_asset_reader.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2016-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/stereo_picture_asset_reader.h + * @brief StereoPictureAssetReader typedef + */ + + +#ifndef LIBDCP_STEREO_PICTURE_ASSET_READER_H +#define LIBDCP_STEREO_PICTURE_ASSET_READER_H + + +#include "asset_reader.h" +#include "stereo_picture_frame.h" + + +namespace dcp { + + +typedef AssetReader StereoPictureAssetReader; + + +} + + +#endif diff --git a/src/stereo_j2k_picture_asset_writer.cc b/src/stereo_j2k_picture_asset_writer.cc new file mode 100644 index 00000000..6ee271bc --- /dev/null +++ b/src/stereo_j2k_picture_asset_writer.cc @@ -0,0 +1,160 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/stereo_picture_asset_writer.cc + * @brief StereoPictureAssetWriter class + */ + + +#include "stereo_picture_asset_writer.h" +#include "exceptions.h" +#include "dcp_assert.h" +#include "picture_asset.h" +#include "crypto_context.h" +#include +#include + + +#include "picture_asset_writer_common.cc" + + +using std::string; +using std::shared_ptr; +using namespace dcp; + + +struct StereoPictureAssetWriter::ASDCPState : public ASDCPStateBase +{ + ASDCP::JP2K::MXFSWriter mxf_writer; +}; + + +StereoPictureAssetWriter::StereoPictureAssetWriter (PictureAsset* mxf, boost::filesystem::path file, bool overwrite) + : PictureAssetWriter (mxf, file, overwrite) + , _state (new StereoPictureAssetWriter::ASDCPState) +{ + +} + + +StereoPictureAssetWriter::~StereoPictureAssetWriter() +{ + try { + /* Last-resort finalization to close the file, at least */ + if (!_finalized) { + _state->mxf_writer.Finalize(); + } + } catch (...) {} +} + + +void +StereoPictureAssetWriter::start (uint8_t const * data, int size) +{ + dcp::start (this, _state, _picture_asset, data, size); + _picture_asset->set_frame_rate (Fraction (_picture_asset->edit_rate().numerator * 2, _picture_asset->edit_rate().denominator)); +} + + +FrameInfo +StereoPictureAssetWriter::write (uint8_t const * data, int size) +{ + DCP_ASSERT (!_finalized); + + if (!_started) { + start (data, size); + } + + if (ASDCP_FAILURE (_state->j2k_parser.OpenReadFrame (data, size, _state->frame_buffer))) { + boost::throw_exception (MiscError ("could not parse J2K frame")); + } + + _state->frame_buffer.PlaintextOffset(0); + + uint64_t const before_offset = _state->mxf_writer.Tell (); + + string hash; + auto r = _state->mxf_writer.WriteFrame ( + _state->frame_buffer, + _next_eye == Eye::LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT, + _crypto_context->context(), + _crypto_context->hmac(), + &hash + ); + + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r)); + } + + _next_eye = _next_eye == Eye::LEFT ? Eye::RIGHT : Eye::LEFT; + + if (_next_eye == Eye::LEFT) { + ++_frames_written; + } + + return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash); +} + + +void +StereoPictureAssetWriter::fake_write (int size) +{ + DCP_ASSERT (_started); + DCP_ASSERT (!_finalized); + + auto r = _state->mxf_writer.FakeWriteFrame (size, _next_eye == Eye::LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT); + if (ASDCP_FAILURE(r)) { + boost::throw_exception (MXFFileError("error in writing video MXF", _file.string(), r)); + } + + _next_eye = _next_eye == Eye::LEFT ? Eye::RIGHT : Eye::LEFT; + if (_next_eye == Eye::LEFT) { + ++_frames_written; + } +} + + +bool +StereoPictureAssetWriter::finalize () +{ + if (_started) { + auto r = _state->mxf_writer.Finalize(); + if (ASDCP_FAILURE(r)) { + boost::throw_exception (MXFFileError("error in finalizing video MXF", _file.string(), r)); + } + } + + _picture_asset->_intrinsic_duration = _frames_written; + return PictureAssetWriter::finalize (); +} diff --git a/src/stereo_j2k_picture_asset_writer.h b/src/stereo_j2k_picture_asset_writer.h new file mode 100644 index 00000000..1cee1202 --- /dev/null +++ b/src/stereo_j2k_picture_asset_writer.h @@ -0,0 +1,89 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/stereo_picture_asset_writer.h + * @brief StereoPictureAssetWriter class + */ + + +#include "picture_asset_writer.h" +#include +#include +#include + + +namespace dcp { + + +/** @class StereoPictureAssetWriter + * @brief A helper class for writing to StereoPictureAssets. + * + * Objects of this class can only be created with StereoPictureAsset::start_write(). + * + * Frames can be written to the StereoPictureAsset by calling write() with a JPEG2000 image + * (a verbatim .j2c file). finalize() should be called after the last frame has been written, + * but if it is not, it will be called by the destructor (though in that case any error + * during finalization will be ignored). + */ +class StereoPictureAssetWriter : public PictureAssetWriter +{ +public: + ~StereoPictureAssetWriter(); + + /** Write a frame for one eye. Frames must be written left, then right, then left etc. + * @param data JPEG2000 data. + * @param size Size of data. + */ + FrameInfo write (uint8_t const * data, int size) override; + void fake_write (int size) override; + bool finalize () override; + +private: + friend class StereoPictureAsset; + + StereoPictureAssetWriter (PictureAsset *, boost::filesystem::path file, bool); + void start (uint8_t const *, int); + + /* do this with an opaque pointer so we don't have to include + ASDCP headers + */ + + struct ASDCPState; + std::shared_ptr _state; + + dcp::Eye _next_eye = Eye::LEFT; +}; + + +} diff --git a/src/stereo_j2k_picture_frame.cc b/src/stereo_j2k_picture_frame.cc new file mode 100644 index 00000000..8d3a2757 --- /dev/null +++ b/src/stereo_j2k_picture_frame.cc @@ -0,0 +1,148 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/stereo_picture_frame.cc + * @brief StereoPictureFrame class + */ + + +#include "colour_conversion.h" +#include "compose.hpp" +#include "crypto_context.h" +#include "exceptions.h" +#include "j2k_transcode.h" +#include "rgb_xyz.h" +#include "stereo_picture_frame.h" +#include "util.h" +#include +#include + + +using std::string; +using std::shared_ptr; +using std::make_shared; +using namespace dcp; + + +StereoPictureFrame::Part::Part (shared_ptr buffer, Eye eye) + : _buffer (buffer) + , _eye (eye) +{ + +} + + +ASDCP::JP2K::FrameBuffer & +StereoPictureFrame::Part::mono () const +{ + return _eye == Eye::LEFT ? _buffer->Left : _buffer->Right; +} + + +uint8_t const * +StereoPictureFrame::Part::data () const +{ + return mono().RoData(); +} + + +uint8_t * +StereoPictureFrame::Part::data () +{ + return mono().Data(); +} + + +int +StereoPictureFrame::Part::size () const +{ + return mono().Size(); +} + + +/** Make a picture frame from a 3D (stereoscopic) asset. + * @param reader Reader for the MXF file. + * @param n Frame within the asset, not taking EntryPoint into account. + * @param check_hmac true to check the HMAC and give an error if it is not as expected. + */ +StereoPictureFrame::StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, shared_ptr c, bool check_hmac) +{ + /* XXX: unfortunate guesswork on this buffer size */ + _buffer = make_shared(4 * Kumu::Megabyte); + + if (ASDCP_FAILURE (reader->ReadFrame (n, *_buffer, c->context(), check_hmac ? c->hmac() : nullptr))) { + boost::throw_exception (ReadError (String::compose ("could not read video frame %1 of %2", n))); + } +} + + +StereoPictureFrame::StereoPictureFrame () +{ + _buffer = make_shared(4 * Kumu::Megabyte); +} + + +/** @param eye Eye to return (EYE_LEFT or EYE_RIGHT). + * @param reduce a factor by which to reduce the resolution + * of the image, expressed as a power of two (pass 0 for no + * reduction). + */ +shared_ptr +StereoPictureFrame::xyz_image (Eye eye, int reduce) const +{ + switch (eye) { + case Eye::LEFT: + return decompress_j2k (const_cast(_buffer->Left.RoData()), _buffer->Left.Size(), reduce); + case Eye::RIGHT: + return decompress_j2k (const_cast(_buffer->Right.RoData()), _buffer->Right.Size(), reduce); + } + + return {}; +} + + +shared_ptr +StereoPictureFrame::right () const +{ + return make_shared(_buffer, Eye::RIGHT); +} + + +shared_ptr +StereoPictureFrame::left () const +{ + return make_shared(_buffer, Eye::LEFT); +} + + diff --git a/src/stereo_j2k_picture_frame.h b/src/stereo_j2k_picture_frame.h new file mode 100644 index 00000000..b0c0f0c8 --- /dev/null +++ b/src/stereo_j2k_picture_frame.h @@ -0,0 +1,116 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington + + 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 . + + 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. +*/ + + +/** @file src/stereo_picture_frame.h + * @brief StereoPictureFrame class + */ + + +#ifndef LIBDCP_STEREO_PICTURE_FRAME_H +#define LIBDCP_STEREO_PICTURE_FRAME_H + + +#include "asset_reader.h" +#include +#include +#include +#include + + +namespace ASDCP { + namespace JP2K { + struct SFrameBuffer; + class MXFSReader; + } + class AESDecContext; +} + + +namespace dcp { + + +class OpenJPEGImage; +class StereoPictureFrame; + + +/** @class StereoPictureFrame + * @brief A single frame of a 3D (stereoscopic) picture asset + */ +class StereoPictureFrame +{ +public: + StereoPictureFrame (); + + StereoPictureFrame (StereoPictureFrame const &) = delete; + StereoPictureFrame& operator= (StereoPictureFrame const &) = delete; + + std::shared_ptr xyz_image (Eye eye, int reduce = 0) const; + + class Part : public Data + { + public: + Part (std::shared_ptr buffer, Eye eye); + + uint8_t const * data () const override; + uint8_t * data () override; + int size () const override; + + private: + friend class StereoPictureFrame; + + ASDCP::JP2K::FrameBuffer& mono () const; + + std::shared_ptr _buffer; + Eye _eye; + }; + + std::shared_ptr left () const; + std::shared_ptr right () const; + +private: + /* XXX: this is a bit of a shame, but I tried friend StereoPictureAssetReader and it's + rejected by some (seemingly older) GCCs. + */ + friend class AssetReader; + + StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, std::shared_ptr, bool check_hmac); + + std::shared_ptr _buffer; +}; + + +} + + +#endif diff --git a/src/stereo_picture_asset.cc b/src/stereo_picture_asset.cc deleted file mode 100644 index 687d8572..00000000 --- a/src/stereo_picture_asset.cc +++ /dev/null @@ -1,183 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/stereo_picture_asset.cc - * @brief StereoPictureAsset class - */ - - -#include "dcp_assert.h" -#include "equality_options.h" -#include "exceptions.h" -#include "filesystem.h" -#include "stereo_picture_asset.h" -#include "stereo_picture_asset_reader.h" -#include "stereo_picture_asset_writer.h" -#include "stereo_picture_frame.h" -#include - - -using std::string; -using std::pair; -using std::make_pair; -using std::shared_ptr; -using std::dynamic_pointer_cast; -using namespace dcp; - - -StereoPictureAsset::StereoPictureAsset (boost::filesystem::path file) - : PictureAsset (file) -{ - Kumu::FileReaderFactory factory; - ASDCP::JP2K::MXFSReader reader(factory); - auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str()); - if (ASDCP_FAILURE(r)) { - boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r)); - } - - ASDCP::JP2K::PictureDescriptor desc; - if (ASDCP_FAILURE (reader.FillPictureDescriptor(desc))) { - boost::throw_exception (ReadError("could not read video MXF information")); - } - - read_picture_descriptor (desc); - - ASDCP::WriterInfo info; - if (ASDCP_FAILURE (reader.FillWriterInfo(info))) { - boost::throw_exception (ReadError("could not read video MXF information")); - } - - _id = read_writer_info (info); -} - - -StereoPictureAsset::StereoPictureAsset (Fraction edit_rate, Standard standard) - : PictureAsset (edit_rate, standard) -{ - -} - - -shared_ptr -StereoPictureAsset::start_write(boost::filesystem::path file, Behaviour behaviour) -{ - return shared_ptr(new StereoPictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING)); -} - - -shared_ptr -StereoPictureAsset::start_read () const -{ - return shared_ptr (new StereoPictureAssetReader(this, key(), standard())); -} - - -bool -StereoPictureAsset::equals(shared_ptr other, EqualityOptions const& opt, NoteHandler note) const -{ - Kumu::FileReaderFactory factory; - ASDCP::JP2K::MXFSReader reader_A(factory); - DCP_ASSERT (file()); - auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*file()).string().c_str()); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MXFFileError ("could not open MXF file for reading", file()->string(), r)); - } - - ASDCP::JP2K::MXFSReader reader_B(factory); - DCP_ASSERT (other->file()); - r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str()); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r)); - } - - ASDCP::JP2K::PictureDescriptor desc_A; - if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) { - boost::throw_exception (ReadError ("could not read video MXF information")); - } - ASDCP::JP2K::PictureDescriptor desc_B; - if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) { - boost::throw_exception (ReadError ("could not read video MXF information")); - } - - if (!descriptor_equals (desc_A, desc_B, note)) { - return false; - } - - auto other_picture = dynamic_pointer_cast (other); - DCP_ASSERT (other_picture); - - auto reader = start_read (); - auto other_reader = other_picture->start_read (); - - bool result = true; - - for (int i = 0; i < _intrinsic_duration; ++i) { - shared_ptr frame_A; - shared_ptr frame_B; - try { - frame_A = reader->get_frame (i); - frame_B = other_reader->get_frame (i); - } catch (ReadError& e) { - /* If there was a problem reading the frame data we'll just assume - the two frames are not equal. - */ - note (NoteType::ERROR, e.what ()); - return false; - } - - if (!frame_buffer_equals ( - i, opt, note, - frame_A->left()->data(), frame_A->left()->size(), - frame_B->left()->data(), frame_B->left()->size() - )) { - result = false; - if (!opt.keep_going) { - return result; - } - } - - if (!frame_buffer_equals ( - i, opt, note, - frame_A->right()->data(), frame_A->right()->size(), - frame_B->right()->data(), frame_B->right()->size() - )) { - result = false; - if (!opt.keep_going) { - return result; - } - } - } - - return result; -} diff --git a/src/stereo_picture_asset.h b/src/stereo_picture_asset.h deleted file mode 100644 index 6ee1d423..00000000 --- a/src/stereo_picture_asset.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/stereo_picture_asset.h - * @brief StereoPictureAsset class - */ - - -#ifndef LIBDCP_STEREO_PICTURE_ASSET_H -#define LIBDCP_STEREO_PICTURE_ASSET_H - - -#include "picture_asset.h" -#include "stereo_picture_asset_reader.h" - - -namespace dcp { - - -/** @class StereoPictureAsset - * @brief A 3D (stereoscopic) picture asset - */ -class StereoPictureAsset : public PictureAsset -{ -public: - explicit StereoPictureAsset (boost::filesystem::path file); - explicit StereoPictureAsset (Fraction edit_rate, Standard standard); - - /** Start a progressive write to a StereoPictureAsset */ - std::shared_ptr start_write(boost::filesystem::path file, Behaviour behaviour) override; - std::shared_ptr start_read () const; - - bool equals ( - std::shared_ptr other, - EqualityOptions const& opt, - NoteHandler note - ) const override; -}; - - -} - - -#endif diff --git a/src/stereo_picture_asset_reader.h b/src/stereo_picture_asset_reader.h deleted file mode 100644 index 9cb05263..00000000 --- a/src/stereo_picture_asset_reader.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2016-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/stereo_picture_asset_reader.h - * @brief StereoPictureAssetReader typedef - */ - - -#ifndef LIBDCP_STEREO_PICTURE_ASSET_READER_H -#define LIBDCP_STEREO_PICTURE_ASSET_READER_H - - -#include "asset_reader.h" -#include "stereo_picture_frame.h" - - -namespace dcp { - - -typedef AssetReader StereoPictureAssetReader; - - -} - - -#endif diff --git a/src/stereo_picture_asset_writer.cc b/src/stereo_picture_asset_writer.cc deleted file mode 100644 index 6ee271bc..00000000 --- a/src/stereo_picture_asset_writer.cc +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/stereo_picture_asset_writer.cc - * @brief StereoPictureAssetWriter class - */ - - -#include "stereo_picture_asset_writer.h" -#include "exceptions.h" -#include "dcp_assert.h" -#include "picture_asset.h" -#include "crypto_context.h" -#include -#include - - -#include "picture_asset_writer_common.cc" - - -using std::string; -using std::shared_ptr; -using namespace dcp; - - -struct StereoPictureAssetWriter::ASDCPState : public ASDCPStateBase -{ - ASDCP::JP2K::MXFSWriter mxf_writer; -}; - - -StereoPictureAssetWriter::StereoPictureAssetWriter (PictureAsset* mxf, boost::filesystem::path file, bool overwrite) - : PictureAssetWriter (mxf, file, overwrite) - , _state (new StereoPictureAssetWriter::ASDCPState) -{ - -} - - -StereoPictureAssetWriter::~StereoPictureAssetWriter() -{ - try { - /* Last-resort finalization to close the file, at least */ - if (!_finalized) { - _state->mxf_writer.Finalize(); - } - } catch (...) {} -} - - -void -StereoPictureAssetWriter::start (uint8_t const * data, int size) -{ - dcp::start (this, _state, _picture_asset, data, size); - _picture_asset->set_frame_rate (Fraction (_picture_asset->edit_rate().numerator * 2, _picture_asset->edit_rate().denominator)); -} - - -FrameInfo -StereoPictureAssetWriter::write (uint8_t const * data, int size) -{ - DCP_ASSERT (!_finalized); - - if (!_started) { - start (data, size); - } - - if (ASDCP_FAILURE (_state->j2k_parser.OpenReadFrame (data, size, _state->frame_buffer))) { - boost::throw_exception (MiscError ("could not parse J2K frame")); - } - - _state->frame_buffer.PlaintextOffset(0); - - uint64_t const before_offset = _state->mxf_writer.Tell (); - - string hash; - auto r = _state->mxf_writer.WriteFrame ( - _state->frame_buffer, - _next_eye == Eye::LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT, - _crypto_context->context(), - _crypto_context->hmac(), - &hash - ); - - if (ASDCP_FAILURE (r)) { - boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r)); - } - - _next_eye = _next_eye == Eye::LEFT ? Eye::RIGHT : Eye::LEFT; - - if (_next_eye == Eye::LEFT) { - ++_frames_written; - } - - return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash); -} - - -void -StereoPictureAssetWriter::fake_write (int size) -{ - DCP_ASSERT (_started); - DCP_ASSERT (!_finalized); - - auto r = _state->mxf_writer.FakeWriteFrame (size, _next_eye == Eye::LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT); - if (ASDCP_FAILURE(r)) { - boost::throw_exception (MXFFileError("error in writing video MXF", _file.string(), r)); - } - - _next_eye = _next_eye == Eye::LEFT ? Eye::RIGHT : Eye::LEFT; - if (_next_eye == Eye::LEFT) { - ++_frames_written; - } -} - - -bool -StereoPictureAssetWriter::finalize () -{ - if (_started) { - auto r = _state->mxf_writer.Finalize(); - if (ASDCP_FAILURE(r)) { - boost::throw_exception (MXFFileError("error in finalizing video MXF", _file.string(), r)); - } - } - - _picture_asset->_intrinsic_duration = _frames_written; - return PictureAssetWriter::finalize (); -} diff --git a/src/stereo_picture_asset_writer.h b/src/stereo_picture_asset_writer.h deleted file mode 100644 index 1cee1202..00000000 --- a/src/stereo_picture_asset_writer.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/stereo_picture_asset_writer.h - * @brief StereoPictureAssetWriter class - */ - - -#include "picture_asset_writer.h" -#include -#include -#include - - -namespace dcp { - - -/** @class StereoPictureAssetWriter - * @brief A helper class for writing to StereoPictureAssets. - * - * Objects of this class can only be created with StereoPictureAsset::start_write(). - * - * Frames can be written to the StereoPictureAsset by calling write() with a JPEG2000 image - * (a verbatim .j2c file). finalize() should be called after the last frame has been written, - * but if it is not, it will be called by the destructor (though in that case any error - * during finalization will be ignored). - */ -class StereoPictureAssetWriter : public PictureAssetWriter -{ -public: - ~StereoPictureAssetWriter(); - - /** Write a frame for one eye. Frames must be written left, then right, then left etc. - * @param data JPEG2000 data. - * @param size Size of data. - */ - FrameInfo write (uint8_t const * data, int size) override; - void fake_write (int size) override; - bool finalize () override; - -private: - friend class StereoPictureAsset; - - StereoPictureAssetWriter (PictureAsset *, boost::filesystem::path file, bool); - void start (uint8_t const *, int); - - /* do this with an opaque pointer so we don't have to include - ASDCP headers - */ - - struct ASDCPState; - std::shared_ptr _state; - - dcp::Eye _next_eye = Eye::LEFT; -}; - - -} diff --git a/src/stereo_picture_frame.cc b/src/stereo_picture_frame.cc deleted file mode 100644 index 8d3a2757..00000000 --- a/src/stereo_picture_frame.cc +++ /dev/null @@ -1,148 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/stereo_picture_frame.cc - * @brief StereoPictureFrame class - */ - - -#include "colour_conversion.h" -#include "compose.hpp" -#include "crypto_context.h" -#include "exceptions.h" -#include "j2k_transcode.h" -#include "rgb_xyz.h" -#include "stereo_picture_frame.h" -#include "util.h" -#include -#include - - -using std::string; -using std::shared_ptr; -using std::make_shared; -using namespace dcp; - - -StereoPictureFrame::Part::Part (shared_ptr buffer, Eye eye) - : _buffer (buffer) - , _eye (eye) -{ - -} - - -ASDCP::JP2K::FrameBuffer & -StereoPictureFrame::Part::mono () const -{ - return _eye == Eye::LEFT ? _buffer->Left : _buffer->Right; -} - - -uint8_t const * -StereoPictureFrame::Part::data () const -{ - return mono().RoData(); -} - - -uint8_t * -StereoPictureFrame::Part::data () -{ - return mono().Data(); -} - - -int -StereoPictureFrame::Part::size () const -{ - return mono().Size(); -} - - -/** Make a picture frame from a 3D (stereoscopic) asset. - * @param reader Reader for the MXF file. - * @param n Frame within the asset, not taking EntryPoint into account. - * @param check_hmac true to check the HMAC and give an error if it is not as expected. - */ -StereoPictureFrame::StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, shared_ptr c, bool check_hmac) -{ - /* XXX: unfortunate guesswork on this buffer size */ - _buffer = make_shared(4 * Kumu::Megabyte); - - if (ASDCP_FAILURE (reader->ReadFrame (n, *_buffer, c->context(), check_hmac ? c->hmac() : nullptr))) { - boost::throw_exception (ReadError (String::compose ("could not read video frame %1 of %2", n))); - } -} - - -StereoPictureFrame::StereoPictureFrame () -{ - _buffer = make_shared(4 * Kumu::Megabyte); -} - - -/** @param eye Eye to return (EYE_LEFT or EYE_RIGHT). - * @param reduce a factor by which to reduce the resolution - * of the image, expressed as a power of two (pass 0 for no - * reduction). - */ -shared_ptr -StereoPictureFrame::xyz_image (Eye eye, int reduce) const -{ - switch (eye) { - case Eye::LEFT: - return decompress_j2k (const_cast(_buffer->Left.RoData()), _buffer->Left.Size(), reduce); - case Eye::RIGHT: - return decompress_j2k (const_cast(_buffer->Right.RoData()), _buffer->Right.Size(), reduce); - } - - return {}; -} - - -shared_ptr -StereoPictureFrame::right () const -{ - return make_shared(_buffer, Eye::RIGHT); -} - - -shared_ptr -StereoPictureFrame::left () const -{ - return make_shared(_buffer, Eye::LEFT); -} - - diff --git a/src/stereo_picture_frame.h b/src/stereo_picture_frame.h deleted file mode 100644 index b0c0f0c8..00000000 --- a/src/stereo_picture_frame.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright (C) 2012-2021 Carl Hetherington - - 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 . - - 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. -*/ - - -/** @file src/stereo_picture_frame.h - * @brief StereoPictureFrame class - */ - - -#ifndef LIBDCP_STEREO_PICTURE_FRAME_H -#define LIBDCP_STEREO_PICTURE_FRAME_H - - -#include "asset_reader.h" -#include -#include -#include -#include - - -namespace ASDCP { - namespace JP2K { - struct SFrameBuffer; - class MXFSReader; - } - class AESDecContext; -} - - -namespace dcp { - - -class OpenJPEGImage; -class StereoPictureFrame; - - -/** @class StereoPictureFrame - * @brief A single frame of a 3D (stereoscopic) picture asset - */ -class StereoPictureFrame -{ -public: - StereoPictureFrame (); - - StereoPictureFrame (StereoPictureFrame const &) = delete; - StereoPictureFrame& operator= (StereoPictureFrame const &) = delete; - - std::shared_ptr xyz_image (Eye eye, int reduce = 0) const; - - class Part : public Data - { - public: - Part (std::shared_ptr buffer, Eye eye); - - uint8_t const * data () const override; - uint8_t * data () override; - int size () const override; - - private: - friend class StereoPictureFrame; - - ASDCP::JP2K::FrameBuffer& mono () const; - - std::shared_ptr _buffer; - Eye _eye; - }; - - std::shared_ptr left () const; - std::shared_ptr right () const; - -private: - /* XXX: this is a bit of a shame, but I tried friend StereoPictureAssetReader and it's - rejected by some (seemingly older) GCCs. - */ - friend class AssetReader; - - StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, std::shared_ptr, bool check_hmac); - - std::shared_ptr _buffer; -}; - - -} - - -#endif diff --git a/src/wscript b/src/wscript index adaa57bb..428e2769 100644 --- a/src/wscript +++ b/src/wscript @@ -36,14 +36,14 @@ def build(bld): source = """ array_data.cc asset.cc - asset_map.cc asset_factory.cc + asset_map.cc asset_writer.cc atmos_asset.cc atmos_asset_writer.cc bitstream.cc - certificate_chain.cc certificate.cc + certificate_chain.cc chromaticity.cc colour_conversion.cc combine.cc @@ -65,6 +65,8 @@ def build(bld): identity_transfer_function.cc interop_load_font_node.cc interop_subtitle_asset.cc + j2k_picture_asset.cc + j2k_picture_asset_writer.cc j2k_transcode.cc key.cc language_tag.cc @@ -72,15 +74,13 @@ def build(bld): locale_convert.cc metadata.cc modified_gamma_transfer_function.cc - mono_picture_asset.cc - mono_picture_asset_writer.cc - mono_picture_frame.cc + mono_j2k_picture_asset.cc + mono_j2k_picture_asset_writer.cc + mono_j2k_picture_frame.cc mxf.cc name_format.cc object.cc openjpeg_image.cc - picture_asset.cc - picture_asset_writer.cc pkl.cc rating.cc raw_convert.cc @@ -91,9 +91,9 @@ def build(bld): reel_file_asset.cc reel_interop_closed_caption_asset.cc reel_interop_subtitle_asset.cc + reel_markers_asset.cc reel_mono_picture_asset.cc reel_picture_asset.cc - reel_markers_asset.cc reel_smpte_closed_caption_asset.cc reel_smpte_subtitle_asset.cc reel_sound_asset.cc @@ -109,9 +109,9 @@ def build(bld): sound_asset.cc sound_asset_writer.cc sound_frame.cc - stereo_picture_asset.cc - stereo_picture_asset_writer.cc - stereo_picture_frame.cc + stereo_j2k_picture_asset.cc + stereo_j2k_picture_asset_writer.cc + stereo_j2k_picture_frame.cc subtitle.cc subtitle_asset.cc subtitle_asset_internal.cc @@ -140,8 +140,8 @@ def build(bld): atmos_asset_reader.h atmos_asset_writer.h atmos_frame.h - certificate_chain.h certificate.h + certificate_chain.h chromaticity.h colour_conversion.h combine.h @@ -168,6 +168,8 @@ def build(bld): identity_transfer_function.h interop_load_font_node.h interop_subtitle_asset.h + j2k_picture_asset.h + j2k_picture_asset_writer.h j2k_transcode.h key.h language_tag.h @@ -175,22 +177,19 @@ def build(bld): local_time.h locale_convert.h metadata.h - mono_picture_asset.h - mono_picture_asset_reader.h - mono_picture_asset_writer.h - mono_picture_frame.h modified_gamma_transfer_function.h + mono_j2k_picture_asset.h + mono_j2k_picture_asset_reader.h + mono_j2k_picture_asset_writer.h + mono_j2k_picture_frame.h mxf.h name_format.h object.h openjpeg_image.h - picture_asset.h - picture_asset_writer.h piecewise_lut.h pkl.h rating.h raw_convert.h - rgb_xyz.h reel.h reel_asset.h reel_atmos_asset.h @@ -201,26 +200,27 @@ def build(bld): reel_markers_asset.h reel_mono_picture_asset.h reel_picture_asset.h - reel_sound_asset.h reel_smpte_closed_caption_asset.h reel_smpte_subtitle_asset.h + reel_sound_asset.h reel_stereo_picture_asset.h reel_subtitle_asset.h ref.h + rgb_xyz.h ruby.h s_gamut3_transfer_function.h scope_guard.h search.h smpte_load_font_node.h smpte_subtitle_asset.h - sound_frame.h sound_asset.h sound_asset_reader.h sound_asset_writer.h - stereo_picture_asset.h - stereo_picture_asset_reader.h - stereo_picture_asset_writer.h - stereo_picture_frame.h + sound_frame.h + stereo_j2k_picture_asset.h + stereo_j2k_picture_asset_reader.h + stereo_j2k_picture_asset_writer.h + stereo_j2k_picture_frame.h subtitle.h subtitle_asset.h subtitle_image.h -- cgit v1.2.3