summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2020-11-01 23:51:19 +0100
committerCarl Hetherington <cth@carlh.net>2020-11-02 23:10:04 +0100
commit2ea3a0d0e4066a166c0700bd1d53daa7f1c50dff (patch)
treea730b75be36d74a8aee1ebab60d5a3aa629d8d35
parent6fa9748f382302fa88292b4219598bb81edc7bd0 (diff)
Pass around JPEG2000 data as a shared_ptr and hence avoid a copy
of 4MB of data for every JPEG2000 frame we decode.
-rw-r--r--src/lib/j2k_encoder.cc10
-rw-r--r--src/lib/j2k_image_proxy.cc47
-rw-r--r--src/lib/j2k_image_proxy.h8
-rw-r--r--src/lib/player_video.cc2
-rw-r--r--src/lib/player_video.h2
-rw-r--r--src/lib/reel_writer.cc7
-rw-r--r--src/lib/reel_writer.h4
-rw-r--r--src/lib/writer.cc5
-rw-r--r--src/lib/writer.h4
9 files changed, 41 insertions, 48 deletions
diff --git a/src/lib/j2k_encoder.cc b/src/lib/j2k_encoder.cc
index 64cd38147..18bb27645 100644
--- a/src/lib/j2k_encoder.cc
+++ b/src/lib/j2k_encoder.cc
@@ -127,7 +127,7 @@ J2KEncoder::end ()
LOG_GENERAL (N_("Encode left-over frame %1"), (*i)->index ());
try {
_writer->write (
- (*i)->encode_locally(),
+ shared_ptr<dcp::Data>(new dcp::ArrayData((*i)->encode_locally())),
(*i)->index(),
(*i)->eyes()
);
@@ -296,12 +296,12 @@ try
lock.unlock ();
- optional<Data> encoded;
+ shared_ptr<Data> encoded;
/* We need to encode this input */
if (server) {
try {
- encoded = vf->encode_remotely (server.get ());
+ encoded.reset(new dcp::ArrayData(vf->encode_remotely(server.get())));
if (remote_backoff > 0) {
LOG_GENERAL ("%1 was lost, but now she is found; removing backoff", server->host_name ());
@@ -324,7 +324,7 @@ try
} else {
try {
LOG_TIMING ("start-local-encode thread=%1 frame=%2", thread_id(), vf->index());
- encoded = vf->encode_locally ();
+ encoded.reset(new dcp::ArrayData(vf->encode_locally()));
LOG_TIMING ("finish-local-encode thread=%1 frame=%2", thread_id(), vf->index());
} catch (std::exception& e) {
/* This is very bad, so don't cope with it, just pass it on */
@@ -334,7 +334,7 @@ try
}
if (encoded) {
- _writer->write (encoded.get(), vf->index (), vf->eyes ());
+ _writer->write (encoded, vf->index(), vf->eyes());
frame_done ();
} else {
lock.lock ();
diff --git a/src/lib/j2k_image_proxy.cc b/src/lib/j2k_image_proxy.cc
index 08ebc343c..064bbec7b 100644
--- a/src/lib/j2k_image_proxy.cc
+++ b/src/lib/j2k_image_proxy.cc
@@ -46,12 +46,12 @@ using std::make_pair;
using boost::shared_ptr;
using boost::optional;
using boost::dynamic_pointer_cast;
-using dcp::Data;
+using dcp::ArrayData;
using dcp::raw_convert;
/** Construct a J2KImageProxy from a JPEG2000 file */
J2KImageProxy::J2KImageProxy (boost::filesystem::path path, dcp::Size size, AVPixelFormat pixel_format)
- : _data (path)
+ : _data (new dcp::ArrayData(path))
, _size (size)
, _pixel_format (pixel_format)
, _error (false)
@@ -60,13 +60,14 @@ J2KImageProxy::J2KImageProxy (boost::filesystem::path path, dcp::Size size, AVPi
DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB48 || _pixel_format == AV_PIX_FMT_XYZ12LE);
}
+
J2KImageProxy::J2KImageProxy (
shared_ptr<const dcp::MonoPictureFrame> frame,
dcp::Size size,
AVPixelFormat pixel_format,
optional<int> forced_reduction
)
- : _data (frame->j2k_size ())
+ : _data (frame)
, _size (size)
, _pixel_format (pixel_format)
, _forced_reduction (forced_reduction)
@@ -74,9 +75,9 @@ J2KImageProxy::J2KImageProxy (
{
/* ::image assumes 16bpp */
DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB48 || _pixel_format == AV_PIX_FMT_XYZ12LE);
- memcpy (_data.data().get(), frame->j2k_data(), _data.size ());
}
+
J2KImageProxy::J2KImageProxy (
shared_ptr<const dcp::StereoPictureFrame> frame,
dcp::Size size,
@@ -84,7 +85,8 @@ J2KImageProxy::J2KImageProxy (
AVPixelFormat pixel_format,
optional<int> forced_reduction
)
- : _size (size)
+ : _data (eye ? frame->left() : frame->right())
+ , _size (size)
, _eye (eye)
, _pixel_format (pixel_format)
, _forced_reduction (forced_reduction)
@@ -92,18 +94,9 @@ J2KImageProxy::J2KImageProxy (
{
/* ::image assumes 16bpp */
DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB48 || _pixel_format == AV_PIX_FMT_XYZ12LE);
- switch (eye) {
- case dcp::EYE_LEFT:
- _data = Data (frame->left_j2k_size ());
- memcpy (_data.data().get(), frame->left_j2k_data(), _data.size ());
- break;
- case dcp::EYE_RIGHT:
- _data = Data (frame->right_j2k_size ());
- memcpy (_data.data().get(), frame->right_j2k_data(), _data.size ());
- break;
- }
}
+
J2KImageProxy::J2KImageProxy (shared_ptr<cxml::Node> xml, shared_ptr<Socket> socket)
: _error (false)
{
@@ -111,13 +104,14 @@ J2KImageProxy::J2KImageProxy (shared_ptr<cxml::Node> xml, shared_ptr<Socket> soc
if (xml->optional_number_child<int> ("Eye")) {
_eye = static_cast<dcp::Eye> (xml->number_child<int> ("Eye"));
}
- _data = Data (xml->number_child<int> ("Size"));
+ shared_ptr<ArrayData> data(new ArrayData(xml->number_child<int>("Size")));
/* This only matters when we are using J2KImageProxy for the preview, which
will never use this constructor (which is only used for passing data to
encode servers). So we can put anything in here. It's a bit of a hack.
*/
_pixel_format = AV_PIX_FMT_XYZ12LE;
- socket->read (_data.data().get (), _data.size ());
+ socket->read (data->data(), data->size());
+ _data = data;
}
int
@@ -144,7 +138,8 @@ J2KImageProxy::prepare (optional<dcp::Size> target_size) const
}
try {
- shared_ptr<dcp::OpenJPEGImage> decompressed = dcp::decompress_j2k (const_cast<uint8_t*> (_data.data().get()), _data.size (), reduce);
+ /* XXX: should check that potentially trashing _data here doesn't matter */
+ shared_ptr<dcp::OpenJPEGImage> decompressed = dcp::decompress_j2k (const_cast<uint8_t*>(_data->data()), _data->size(), reduce);
_image.reset (new Image (_pixel_format, decompressed->size(), true));
int const shift = 16 - decompressed->precision (0);
@@ -202,13 +197,13 @@ J2KImageProxy::add_metadata (xmlpp::Node* node) const
if (_eye) {
node->add_child("Eye")->add_child_text (raw_convert<string> (static_cast<int> (_eye.get ())));
}
- node->add_child("Size")->add_child_text (raw_convert<string> (_data.size ()));
+ node->add_child("Size")->add_child_text (raw_convert<string>(_data->size()));
}
void
J2KImageProxy::write_to_socket (shared_ptr<Socket> socket) const
{
- socket->write (_data.data().get(), _data.size());
+ socket->write (_data->data(), _data->size());
}
bool
@@ -219,15 +214,11 @@ J2KImageProxy::same (shared_ptr<const ImageProxy> other) const
return false;
}
- if (_data.size() != jp->_data.size()) {
- return false;
- }
-
- return memcmp (_data.data().get(), jp->_data.data().get(), _data.size()) == 0;
+ return *_data == *jp->_data;
}
-J2KImageProxy::J2KImageProxy (Data data, dcp::Size size, AVPixelFormat pixel_format)
- : _data (data)
+J2KImageProxy::J2KImageProxy (ArrayData data, dcp::Size size, AVPixelFormat pixel_format)
+ : _data (new ArrayData(data))
, _size (size)
, _pixel_format (pixel_format)
{
@@ -238,7 +229,7 @@ J2KImageProxy::J2KImageProxy (Data data, dcp::Size size, AVPixelFormat pixel_for
size_t
J2KImageProxy::memory_used () const
{
- size_t m = _data.size();
+ size_t m = _data->size();
if (_image) {
/* 3 components, 16-bits per pixel */
m += 3 * 2 * _image->size().width * _image->size().height;
diff --git a/src/lib/j2k_image_proxy.h b/src/lib/j2k_image_proxy.h
index 71bcffb2c..3eccc213d 100644
--- a/src/lib/j2k_image_proxy.h
+++ b/src/lib/j2k_image_proxy.h
@@ -19,8 +19,8 @@
*/
#include "image_proxy.h"
+#include <dcp/array_data.h>
#include <dcp/util.h>
-#include <dcp/data.h>
#include <boost/thread/mutex.hpp>
namespace dcp {
@@ -60,7 +60,7 @@ public:
bool same (boost::shared_ptr<const ImageProxy>) const;
int prepare (boost::optional<dcp::Size> = boost::optional<dcp::Size>()) const;
- dcp::Data j2k () const {
+ boost::shared_ptr<const dcp::Data> j2k () const {
return _data;
}
@@ -74,9 +74,9 @@ private:
friend struct client_server_test_j2k;
/* For tests */
- J2KImageProxy (dcp::Data data, dcp::Size size, AVPixelFormat pixel_format);
+ J2KImageProxy (dcp::ArrayData data, dcp::Size size, AVPixelFormat pixel_format);
- dcp::Data _data;
+ boost::shared_ptr<const dcp::Data> _data;
dcp::Size _size;
boost::optional<dcp::Eye> _eye;
mutable boost::shared_ptr<Image> _image;
diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc
index 10e798ed5..620245781 100644
--- a/src/lib/player_video.cc
+++ b/src/lib/player_video.cc
@@ -232,7 +232,7 @@ PlayerVideo::has_j2k () const
return _crop == Crop () && _out_size == j2k->size() && !_text && !_fade && !_colour_conversion;
}
-Data
+shared_ptr<const dcp::Data>
PlayerVideo::j2k () const
{
shared_ptr<const J2KImageProxy> j2k = dynamic_pointer_cast<const J2KImageProxy> (_in);
diff --git a/src/lib/player_video.h b/src/lib/player_video.h
index 1a4a01d58..6043632c2 100644
--- a/src/lib/player_video.h
+++ b/src/lib/player_video.h
@@ -79,7 +79,7 @@ public:
bool reset_metadata (boost::shared_ptr<const Film> film, dcp::Size video_container_size, dcp::Size film_frame_size);
bool has_j2k () const;
- dcp::Data j2k () const;
+ boost::shared_ptr<const dcp::Data> j2k () const;
Eyes eyes () const {
return _eyes;
diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc
index 097b9d84b..7ed79d818 100644
--- a/src/lib/reel_writer.cc
+++ b/src/lib/reel_writer.cc
@@ -67,6 +67,7 @@ using boost::dynamic_pointer_cast;
#if BOOST_VERSION >= 106100
using namespace boost::placeholders;
#endif
+using dcp::ArrayData;
using dcp::Data;
using dcp::raw_convert;
using namespace dcpomatic;
@@ -289,14 +290,14 @@ ReelWriter::check_existing_picture_asset (boost::filesystem::path asset)
}
void
-ReelWriter::write (optional<Data> encoded, Frame frame, Eyes eyes)
+ReelWriter::write (shared_ptr<const Data> encoded, Frame frame, Eyes eyes)
{
if (!_picture_asset_writer) {
/* We're not writing any data */
return;
}
- dcp::FrameInfo fin = _picture_asset_writer->write (encoded->data().get (), encoded->size());
+ dcp::FrameInfo fin = _picture_asset_writer->write (encoded->data(), encoded->size());
write_frame_info (frame, eyes, fin);
_last_written[eyes] = encoded;
}
@@ -338,7 +339,7 @@ ReelWriter::repeat_write (Frame frame, Eyes eyes)
}
dcp::FrameInfo fin = _picture_asset_writer->write (
- _last_written[eyes]->data().get(),
+ _last_written[eyes]->data(),
_last_written[eyes]->size()
);
write_frame_info (frame, eyes, fin);
diff --git a/src/lib/reel_writer.h b/src/lib/reel_writer.h
index 17bfc7ba2..09c29adae 100644
--- a/src/lib/reel_writer.h
+++ b/src/lib/reel_writer.h
@@ -66,7 +66,7 @@ public:
boost::optional<std::string> content_summary
);
- void write (boost::optional<dcp::Data> encoded, Frame frame, Eyes eyes);
+ void write (boost::shared_ptr<const dcp::Data> encoded, Frame frame, Eyes eyes);
void fake_write (int size);
void repeat_write (Frame frame, Eyes eyes);
void write (boost::shared_ptr<const AudioBuffers> audio);
@@ -104,7 +104,7 @@ private:
/** the first picture frame index that does not already exist in our MXF */
int _first_nonexistant_frame;
/** the data of the last written frame, if there is one */
- boost::optional<dcp::Data> _last_written[EYES_COUNT];
+ boost::shared_ptr<const dcp::Data> _last_written[EYES_COUNT];
/** index of this reel within the DCP (starting from 0) */
int _reel_index;
/** number of reels in the DCP */
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index d3fdc5128..346cbb0c2 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -66,6 +66,7 @@ using boost::optional;
using namespace boost::placeholders;
#endif
using dcp::Data;
+using dcp::ArrayData;
using namespace dcpomatic;
Writer::Writer (shared_ptr<const Film> film, weak_ptr<Job> j)
@@ -130,7 +131,7 @@ Writer::~Writer ()
* @param eyes Eyes that this frame image is for.
*/
void
-Writer::write (Data encoded, Frame frame, Eyes eyes)
+Writer::write (shared_ptr<const Data> encoded, Frame frame, Eyes eyes)
{
boost::mutex::scoped_lock lock (_state_mutex);
@@ -426,7 +427,7 @@ try
case QueueItem::FULL:
LOG_DEBUG_ENCODE (N_("Writer FULL-writes %1 (%2)"), qi.frame, (int) qi.eyes);
if (!qi.encoded) {
- qi.encoded = Data (_film->j2c_path (qi.reel, qi.frame, qi.eyes, false));
+ qi.encoded.reset (new ArrayData(_film->j2c_path(qi.reel, qi.frame, qi.eyes, false)));
}
reel.write (qi.encoded, qi.frame, qi.eyes);
++_full_written;
diff --git a/src/lib/writer.h b/src/lib/writer.h
index 71e04df96..459bc5a88 100644
--- a/src/lib/writer.h
+++ b/src/lib/writer.h
@@ -70,7 +70,7 @@ public:
} type;
/** encoded data for FULL */
- boost::optional<dcp::Data> encoded;
+ boost::shared_ptr<const dcp::Data> encoded;
/** size of data for FAKE */
int size;
/** reel index */
@@ -105,7 +105,7 @@ public:
bool can_fake_write (Frame) const;
- void write (dcp::Data, Frame, Eyes);
+ void write (boost::shared_ptr<const dcp::Data>, Frame, Eyes);
void fake_write (Frame, Eyes);
bool can_repeat (Frame) const;
void repeat (Frame, Eyes);