2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of libdcp.
6 libdcp is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 libdcp is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with libdcp. If not, see <http://www.gnu.org/licenses/>.
19 In addition, as a special exception, the copyright holders give
20 permission to link the code of portions of this program with the
21 OpenSSL library under certain conditions as described in each
22 individual source file, and distribute linked combinations
25 You must obey the GNU General Public License in all respects
26 for all of the code used other than OpenSSL. If you modify
27 file(s) with this exception, you may extend this exception to your
28 version of the file(s), but you are not obligated to do so. If you
29 do not wish to do so, delete this exception statement from your
30 version. If you delete this exception statement from all source
31 files in the program, then also delete it here.
34 #include "mono_picture_asset.h"
35 #include "mono_picture_asset_writer.h"
36 #include "mono_picture_asset_reader.h"
37 #include "exceptions.h"
38 #include "dcp_assert.h"
39 #include "mono_picture_frame.h"
40 #include "compose.hpp"
41 #include <asdcp/AS_DCP.h>
42 #include <asdcp/KM_fileio.h>
48 using std::shared_ptr;
49 using std::dynamic_pointer_cast;
50 using std::make_shared;
51 #if BOOST_VERSION >= 106100
52 using namespace boost::placeholders;
56 MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file)
59 ASDCP::JP2K::MXFReader reader;
60 auto r = reader.OpenRead (file.string().c_str());
61 if (ASDCP_FAILURE(r)) {
62 boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
65 ASDCP::JP2K::PictureDescriptor desc;
66 if (ASDCP_FAILURE (reader.FillPictureDescriptor(desc))) {
67 boost::throw_exception (ReadError("could not read video MXF information"));
70 read_picture_descriptor (desc);
72 ASDCP::WriterInfo info;
73 if (ASDCP_FAILURE (reader.FillWriterInfo (info))) {
74 boost::throw_exception (ReadError("could not read video MXF information"));
77 _id = read_writer_info (info);
80 MonoPictureAsset::MonoPictureAsset (Fraction edit_rate, Standard standard)
81 : PictureAsset (edit_rate, standard)
87 storing_note_handler (list<pair<NoteType, string> >& notes, NoteType t, string s)
89 notes.push_back (make_pair (t, s));
93 MonoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const
95 if (!dynamic_pointer_cast<const MonoPictureAsset>(other)) {
99 ASDCP::JP2K::MXFReader reader_A;
101 auto r = reader_A.OpenRead (_file->string().c_str());
102 if (ASDCP_FAILURE(r)) {
103 boost::throw_exception (MXFFileError("could not open MXF file for reading", _file->string(), r));
106 ASDCP::JP2K::MXFReader reader_B;
107 DCP_ASSERT (other->file ());
108 r = reader_B.OpenRead (other->file()->string().c_str());
109 if (ASDCP_FAILURE (r)) {
110 boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r));
113 ASDCP::JP2K::PictureDescriptor desc_A;
114 if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) {
115 boost::throw_exception (ReadError ("could not read video MXF information"));
117 ASDCP::JP2K::PictureDescriptor desc_B;
118 if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) {
119 boost::throw_exception (ReadError ("could not read video MXF information"));
122 if (!descriptor_equals (desc_A, desc_B, note)) {
126 auto other_picture = dynamic_pointer_cast<const MonoPictureAsset> (other);
127 DCP_ASSERT (other_picture);
131 auto reader = start_read ();
132 auto other_reader = other_picture->start_read ();
135 #pragma omp parallel for
138 for (int i = 0; i < _intrinsic_duration; ++i) {
139 if (i >= other_picture->intrinsic_duration()) {
143 if (result || opt.keep_going) {
145 auto frame_A = reader->get_frame (i);
146 auto frame_B = other_reader->get_frame (i);
148 list<pair<NoteType, string> > notes;
150 if (!frame_buffer_equals (
151 i, opt, bind (&storing_note_handler, boost::ref(notes), _1, _2),
152 frame_A->data(), frame_A->size(),
153 frame_B->data(), frame_B->size()
162 note (NoteType::PROGRESS, String::compose("Compared video frame %1 of %2", i, _intrinsic_duration));
163 for (auto const& i: notes) {
164 note (i.first, i.second);
173 shared_ptr<PictureAssetWriter>
174 MonoPictureAsset::start_write (boost::filesystem::path file, bool overwrite)
176 return make_shared<MonoPictureAssetWriter>(this, file, overwrite);
179 shared_ptr<MonoPictureAssetReader>
180 MonoPictureAsset::start_read () const
182 return make_shared<MonoPictureAssetReader>(this, key(), standard());
186 MonoPictureAsset::cpl_node_name () const
188 return "MainPicture";