libdcp
mono_picture_asset.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
3 
4  This file is part of libdcp.
5 
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.
10 
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.
15 
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/>.
18 
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
23  including the two.
24 
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.
32 */
33 
34 
40 #include "mono_picture_asset.h"
43 #include "exceptions.h"
44 #include "dcp_assert.h"
45 #include "mono_picture_frame.h"
46 #include "compose.hpp"
47 #include <asdcp/AS_DCP.h>
48 #include <asdcp/KM_fileio.h>
49 
50 
51 using std::string;
52 using std::vector;
53 using std::list;
54 using std::pair;
55 using std::shared_ptr;
56 using std::dynamic_pointer_cast;
57 using std::make_shared;
58 #if BOOST_VERSION >= 106100
59 using namespace boost::placeholders;
60 #endif
61 using namespace dcp;
62 
63 
64 MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file)
65  : PictureAsset (file)
66 {
67  ASDCP::JP2K::MXFReader reader;
68  auto r = reader.OpenRead (file.string().c_str());
69  if (ASDCP_FAILURE(r)) {
70  boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
71  }
72 
73  ASDCP::JP2K::PictureDescriptor desc;
74  if (ASDCP_FAILURE (reader.FillPictureDescriptor(desc))) {
75  boost::throw_exception (ReadError("could not read video MXF information"));
76  }
77 
78  read_picture_descriptor (desc);
79 
80  ASDCP::WriterInfo info;
81  if (ASDCP_FAILURE (reader.FillWriterInfo (info))) {
82  boost::throw_exception (ReadError("could not read video MXF information"));
83  }
84 
85  _id = read_writer_info (info);
86 }
87 
88 
89 MonoPictureAsset::MonoPictureAsset (Fraction edit_rate, Standard standard)
90  : PictureAsset (edit_rate, standard)
91 {
92 
93 }
94 
95 
96 static void
97 storing_note_handler (list<pair<NoteType, string>>& notes, NoteType t, string s)
98 {
99  notes.push_back (make_pair (t, s));
100 }
101 
102 
103 bool
104 MonoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, NoteHandler note) const
105 {
106  if (!dynamic_pointer_cast<const MonoPictureAsset>(other)) {
107  return false;
108  }
109 
110  ASDCP::JP2K::MXFReader reader_A;
111  DCP_ASSERT (_file);
112  auto r = reader_A.OpenRead (_file->string().c_str());
113  if (ASDCP_FAILURE(r)) {
114  boost::throw_exception (MXFFileError("could not open MXF file for reading", _file->string(), r));
115  }
116 
117  ASDCP::JP2K::MXFReader reader_B;
118  DCP_ASSERT (other->file ());
119  r = reader_B.OpenRead (other->file()->string().c_str());
120  if (ASDCP_FAILURE (r)) {
121  boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r));
122  }
123 
124  ASDCP::JP2K::PictureDescriptor desc_A;
125  if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) {
126  boost::throw_exception (ReadError ("could not read video MXF information"));
127  }
128  ASDCP::JP2K::PictureDescriptor desc_B;
129  if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) {
130  boost::throw_exception (ReadError ("could not read video MXF information"));
131  }
132 
133  if (!descriptor_equals (desc_A, desc_B, note)) {
134  return false;
135  }
136 
137  auto other_picture = dynamic_pointer_cast<const MonoPictureAsset> (other);
138  DCP_ASSERT (other_picture);
139 
140  bool result = true;
141 
142  auto reader = start_read ();
143  auto other_reader = other_picture->start_read ();
144 
145 #ifdef LIBDCP_OPENMP
146 #pragma omp parallel for
147 #endif
148 
149  for (int i = 0; i < _intrinsic_duration; ++i) {
150  if (i >= other_picture->intrinsic_duration()) {
151  result = false;
152  }
153 
154  if (result || opt.keep_going) {
155 
156  auto frame_A = reader->get_frame (i);
157  auto frame_B = other_reader->get_frame (i);
158 
159  list<pair<NoteType, string>> notes;
160 
161  if (!frame_buffer_equals (
162  i, opt, bind (&storing_note_handler, boost::ref(notes), _1, _2),
163  frame_A->data(), frame_A->size(),
164  frame_B->data(), frame_B->size()
165  )) {
166  result = false;
167  }
168 
169 #ifdef LIBDCP_OPENMP
170 #pragma omp critical
171 #endif
172  {
173  note (NoteType::PROGRESS, String::compose("Compared video frame %1 of %2", i, _intrinsic_duration));
174  for (auto const& i: notes) {
175  note (i.first, i.second);
176  }
177  }
178  }
179  }
180 
181  return result;
182 }
183 
184 
185 shared_ptr<PictureAssetWriter>
186 MonoPictureAsset::start_write (boost::filesystem::path file, bool overwrite)
187 {
188  /* Can't use make_shared here as the MonoPictureAssetWriter constructor is private */
189  return shared_ptr<MonoPictureAssetWriter>(new MonoPictureAssetWriter(this, file, overwrite));
190 }
191 
192 shared_ptr<MonoPictureAssetReader>
193 MonoPictureAsset::start_read () const
194 {
195  /* Can't use make_shared here as the MonoPictureAssetReader constructor is private */
196  return shared_ptr<MonoPictureAssetReader>(new MonoPictureAssetReader(this, key(), standard()));
197 
198 }
199 
200 string
201 MonoPictureAsset::cpl_node_name () const
202 {
203  return "MainPicture";
204 }
boost::optional< boost::filesystem::path > file() const
Definition: asset.h:97
boost::optional< boost::filesystem::path > _file
Definition: asset.h:122
A fraction (i.e. a thing with an integer numerator and an integer denominator).
Definition: types.h:214
An exception related to an MXF file.
Definition: exceptions.h:82
std::string read_writer_info(ASDCP::WriterInfo const &)
Definition: mxf.cc:124
boost::optional< Key > key() const
Definition: mxf.h:104
A helper class for writing to MonoPictureAssets.
MonoPictureAsset(boost::filesystem::path file)
std::shared_ptr< PictureAssetWriter > start_write(boost::filesystem::path file, bool overwrite) override
An asset made up of JPEG2000 data.
Definition: picture_asset.h:68
int64_t _intrinsic_duration
Any error that occurs when reading data from a DCP.
Definition: exceptions.h:106
DCP_ASSERT macro.
Exceptions thrown by libdcp.
MonoPictureAssetReader typedef.
MonoPictureAssetWriter class.
MonoPictureFrame class.
Namespace for everything in libdcp.
Definition: array_data.h:50
A class to describe what "equality" means for a particular test.
Definition: types.h:249