Move encode_{locally,remotely} into the frame encoder classes.
authorCarl Hetherington <cth@carlh.net>
Fri, 20 May 2022 09:12:55 +0000 (11:12 +0200)
committerCarl Hetherington <cth@carlh.net>
Mon, 23 May 2022 14:55:28 +0000 (16:55 +0200)
src/lib/cpu_j2k_frame_encoder.cc
src/lib/dcp_video.cc
src/lib/dcp_video.h
src/lib/encode_server.cc
src/lib/j2k_encoder.cc
src/lib/remote_j2k_frame_encoder.cc
src/lib/remote_j2k_frame_encoder.h
src/tools/server_test.cc
test/client_server_test.cc
test/low_bitrate_test.cc

index dcfbe9dcf19124569fc54f8b5a078247fd21aa62..5970f89c547728100d6bb57296f1e58098917cb3 100644 (file)
 */
 
 
+#include "colour_conversion.h"
+#include "config.h"
 #include "cpu_j2k_frame_encoder.h"
 #include "cross.h"
 #include "dcp_video.h"
+#include "dcpomatic_assert.h"
 #include "dcpomatic_log.h"
+#include "rng.h"
+#include <dcp/openjpeg_image.h>
+#include <dcp/j2k_transcode.h>
 
 #include "i18n.h"
 
 
 using std::shared_ptr;
 using boost::optional;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
 using dcp::ArrayData;
 
 
@@ -39,7 +48,73 @@ CPUJ2KFrameEncoder::encode (DCPVideo const& vf)
 
        try {
                LOG_TIMING("start-local-encode thread=%1 frame=%2", thread_id(), vf.index());
-               encoded = vf.encode_locally();
+               auto const comment = Config::instance()->dcp_j2k_comment();
+
+               /* This was empirically derived by a user: see #1902 */
+               int const minimum_size = 16384;
+               LOG_GENERAL ("Using minimum frame size %1", minimum_size);
+
+               auto xyz = convert_to_xyz (vf.frame(), boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2));
+               int noise_amount = 2;
+               int pixel_skip = 16;
+               while (true) {
+                       encoded = dcp::compress_j2k (
+                               xyz,
+                               vf.j2k_bandwidth(),
+                               vf.frames_per_second(),
+                               vf.eyes() == Eyes::LEFT || vf.eyes() == Eyes::RIGHT,
+                               vf.resolution() == Resolution::FOUR_K,
+                               comment.empty() ? "libdcp" : comment
+                               );
+
+                       if (encoded->size() >= minimum_size) {
+                               LOG_GENERAL (N_("Frame %1 encoded size was OK (%2)"), vf.index(), encoded->size());
+                               break;
+                       }
+
+                       LOG_GENERAL (N_("Frame %1 encoded size was small (%2); adding noise at level %3 with pixel skip %4"), vf.index(), encoded->size(), noise_amount, pixel_skip);
+
+                       /* The JPEG2000 is too low-bitrate for some decoders <cough>DSS200</cough> so add some noise
+                        * and try again.  This is slow but hopefully won't happen too often.  We have to do
+                        * convert_to_xyz() again because compress_j2k() corrupts its xyz parameter.
+                        */
+
+                       xyz = convert_to_xyz (vf.frame(), boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2));
+                       auto size = xyz->size ();
+                       auto pixels = size.width * size.height;
+                       dcpomatic::RNG rng(42);
+                       for (auto c = 0; c < 3; ++c) {
+                               auto p = xyz->data(c);
+                               auto e = xyz->data(c) + pixels;
+                               while (p < e) {
+                                       *p = std::min(4095, std::max(0, *p + (rng.get() % noise_amount)));
+                                       p += pixel_skip;
+                               }
+                       }
+
+                       if (pixel_skip > 1) {
+                               --pixel_skip;
+                       } else {
+                               ++noise_amount;
+                       }
+                       /* Something's gone badly wrong if this much noise doesn't help */
+                       DCPOMATIC_ASSERT (noise_amount < 16);
+               }
+
+               switch (vf.eyes()) {
+                       case Eyes::BOTH:
+                               LOG_DEBUG_ENCODE (N_("Finished locally-encoded frame %1 for mono"), vf.index());
+                               break;
+                       case Eyes::LEFT:
+                               LOG_DEBUG_ENCODE (N_("Finished locally-encoded frame %1 for L"), vf.index());
+                               break;
+                       case Eyes::RIGHT:
+                               LOG_DEBUG_ENCODE (N_("Finished locally-encoded frame %1 for R"), vf.index());
+                               break;
+                       default:
+                               break;
+               }
+
                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 */
index 2cecee95b18d0479d8ddf4eedc0822f0c788bd98..55536266547e87f210cb37105065412c6d6c47b5 100644 (file)
  */
 
 
-#include "colour_conversion.h"
-#include "compose.hpp"
-#include "config.h"
 #include "cross.h"
 #include "dcp_video.h"
-#include "dcpomatic_log.h"
-#include "dcpomatic_socket.h"
-#include "encode_server_description.h"
-#include "exceptions.h"
-#include "image.h"
-#include "log.h"
 #include "player_video.h"
-#include "rng.h"
 #include <libcxml/cxml.h>
-#include <dcp/raw_convert.h>
-#include <dcp/openjpeg_image.h>
-#include <dcp/rgb_xyz.h>
-#include <dcp/j2k_transcode.h>
-#include <dcp/warnings.h>
-LIBDCP_DISABLE_WARNINGS
-#include <libxml++/libxml++.h>
-LIBDCP_ENABLE_WARNINGS
-#include <boost/asio.hpp>
-#include <boost/thread.hpp>
-#include <stdint.h>
-#include <iomanip>
-#include <iostream>
 
 #include "i18n.h"
 
@@ -65,11 +42,6 @@ using std::cout;
 using std::make_shared;
 using std::shared_ptr;
 using std::string;
-using dcp::ArrayData;
-using dcp::raw_convert;
-#if BOOST_VERSION >= 106100
-using namespace boost::placeholders;
-#endif
 
 
 #define DCI_COEFFICENT (48.0 / 52.37)
@@ -102,149 +74,6 @@ DCPVideo::DCPVideo (shared_ptr<const PlayerVideo> frame, shared_ptr<const cxml::
 }
 
 
-/** J2K-encode this frame on the local host.
- *  @return Encoded data.
- */
-ArrayData
-DCPVideo::encode_locally () const
-{
-       auto const comment = Config::instance()->dcp_j2k_comment();
-
-       ArrayData enc = {};
-       /* This was empirically derived by a user: see #1902 */
-       int const minimum_size = 16384;
-       LOG_GENERAL ("Using minimum frame size %1", minimum_size);
-
-       auto xyz = convert_to_xyz (_frame, boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2));
-       int noise_amount = 2;
-       int pixel_skip = 16;
-       while (true) {
-               enc = dcp::compress_j2k (
-                       xyz,
-                       _j2k_bandwidth,
-                       _frames_per_second,
-                       _frame->eyes() == Eyes::LEFT || _frame->eyes() == Eyes::RIGHT,
-                       _resolution == Resolution::FOUR_K,
-                       comment.empty() ? "libdcp" : comment
-               );
-
-               if (enc.size() >= minimum_size) {
-                       LOG_GENERAL (N_("Frame %1 encoded size was OK (%2)"), _index, enc.size());
-                       break;
-               }
-
-               LOG_GENERAL (N_("Frame %1 encoded size was small (%2); adding noise at level %3 with pixel skip %4"), _index, enc.size(), noise_amount, pixel_skip);
-
-               /* The JPEG2000 is too low-bitrate for some decoders <cough>DSS200</cough> so add some noise
-                * and try again.  This is slow but hopefully won't happen too often.  We have to do
-                * convert_to_xyz() again because compress_j2k() corrupts its xyz parameter.
-                */
-
-               xyz = convert_to_xyz (_frame, boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2));
-               auto size = xyz->size ();
-               auto pixels = size.width * size.height;
-               dcpomatic::RNG rng(42);
-               for (auto c = 0; c < 3; ++c) {
-                       auto p = xyz->data(c);
-                       auto e = xyz->data(c) + pixels;
-                       while (p < e) {
-                               *p = std::min(4095, std::max(0, *p + (rng.get() % noise_amount)));
-                               p += pixel_skip;
-                       }
-               }
-
-               if (pixel_skip > 1) {
-                       --pixel_skip;
-               } else {
-                       ++noise_amount;
-               }
-               /* Something's gone badly wrong if this much noise doesn't help */
-               DCPOMATIC_ASSERT (noise_amount < 16);
-       }
-
-       switch (_frame->eyes()) {
-       case Eyes::BOTH:
-               LOG_DEBUG_ENCODE (N_("Finished locally-encoded frame %1 for mono"), _index);
-               break;
-       case Eyes::LEFT:
-               LOG_DEBUG_ENCODE (N_("Finished locally-encoded frame %1 for L"), _index);
-               break;
-       case Eyes::RIGHT:
-               LOG_DEBUG_ENCODE (N_("Finished locally-encoded frame %1 for R"), _index);
-               break;
-       default:
-               break;
-       }
-
-       return enc;
-}
-
-/** Send this frame to a remote server for J2K encoding, then read the result.
- *  @param serv Server to send to.
- *  @param timeout timeout in seconds.
- *  @return Encoded data.
- */
-ArrayData
-DCPVideo::encode_remotely (EncodeServerDescription serv, int timeout) const
-{
-       boost::asio::io_service io_service;
-       boost::asio::ip::tcp::resolver resolver (io_service);
-       boost::asio::ip::tcp::resolver::query query (serv.host_name(), raw_convert<string> (ENCODE_FRAME_PORT));
-       boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query);
-
-       auto socket = make_shared<Socket>(timeout);
-
-       socket->connect (*endpoint_iterator);
-
-       /* Collect all XML metadata */
-       xmlpp::Document doc;
-       auto root = doc.create_root_node ("EncodingRequest");
-       root->add_child("Version")->add_child_text (raw_convert<string> (SERVER_LINK_VERSION));
-       add_metadata (root);
-
-       LOG_DEBUG_ENCODE (N_("Sending frame %1 to remote"), _index);
-
-       {
-               Socket::WriteDigestScope ds (socket);
-
-               /* Send XML metadata */
-               auto xml = doc.write_to_string ("UTF-8");
-               socket->write (xml.length() + 1);
-               socket->write ((uint8_t *) xml.c_str(), xml.bytes() + 1);
-
-               /* Send binary data */
-               LOG_TIMING("start-remote-send thread=%1", thread_id ());
-               _frame->write_to_socket (socket);
-       }
-
-       /* Read the response (JPEG2000-encoded data); this blocks until the data
-          is ready and sent back.
-       */
-       Socket::ReadDigestScope ds (socket);
-       LOG_TIMING("start-remote-encode thread=%1", thread_id ());
-       ArrayData e (socket->read_uint32 ());
-       LOG_TIMING("start-remote-receive thread=%1", thread_id ());
-       socket->read (e.data(), e.size());
-       LOG_TIMING("finish-remote-receive thread=%1", thread_id ());
-       if (!ds.check()) {
-               throw NetworkError ("Checksums do not match");
-       }
-
-       LOG_DEBUG_ENCODE (N_("Finished remotely-encoded frame %1"), _index);
-
-       return e;
-}
-
-void
-DCPVideo::add_metadata (xmlpp::Element* el) const
-{
-       el->add_child("Index")->add_child_text (raw_convert<string> (_index));
-       el->add_child("FramesPerSecond")->add_child_text (raw_convert<string> (_frames_per_second));
-       el->add_child("J2KBandwidth")->add_child_text (raw_convert<string> (_j2k_bandwidth));
-       el->add_child("Resolution")->add_child_text (raw_convert<string> (int (_resolution)));
-       _frame->add_metadata (el);
-}
-
 Eyes
 DCPVideo::eyes () const
 {
index 14440deb928e7bf57f1d56b516a0a571e45d754a..75aa2e11762222b40944bf425b41807390159581 100644 (file)
@@ -48,21 +48,31 @@ public:
        DCPVideo (DCPVideo const&) = default;
        DCPVideo& operator= (DCPVideo const&) = default;
 
-       dcp::ArrayData encode_locally () const;
-       dcp::ArrayData encode_remotely (EncodeServerDescription, int timeout = 30) const;
+       std::shared_ptr<const PlayerVideo> frame() const {
+               return _frame;
+       }
 
        int index () const {
                return _index;
        }
 
+       int frames_per_second() const {
+               return _frames_per_second;
+       }
+
+       int j2k_bandwidth() const {
+               return _j2k_bandwidth;
+       }
+
+       Resolution resolution() const {
+               return _resolution;
+       }
+
        Eyes eyes () const;
 
        bool same (std::shared_ptr<const DCPVideo> other) const;
 
 private:
-
-       void add_metadata (xmlpp::Element *) const;
-
        std::shared_ptr<const PlayerVideo> _frame;
        int _index;                      ///< frame index within the DCP's intrinsic duration
        int _frames_per_second;          ///< Frames per second that we will use for the DCP
index d326c767be226aa240255504354a4ae08a33ef75..47c28654a9fc90529d3c09c158690e32276a286f 100644 (file)
  */
 
 
-#include "encode_server.h"
-#include "util.h"
-#include "dcpomatic_socket.h"
-#include "image.h"
-#include "dcp_video.h"
+#include "compose.hpp"
 #include "config.h"
+#include "cpu_j2k_frame_encoder.h"
 #include "cross.h"
-#include "player_video.h"
-#include "compose.hpp"
-#include "log.h"
+#include "dcp_video.h"
 #include "dcpomatic_log.h"
+#include "dcpomatic_socket.h"
+#include "encode_server.h"
 #include "encoded_log_entry.h"
+#include "image.h"
+#include "log.h"
+#include "player_video.h"
+#include "util.h"
 #include "version.h"
 #include <dcp/raw_convert.h>
 #include <dcp/warnings.h>
@@ -49,25 +50,25 @@ LIBDCP_ENABLE_WARNINGS
 #ifdef HAVE_VALGRIND_H
 #include <valgrind/memcheck.h>
 #endif
+#include <iostream>
 #include <string>
 #include <vector>
-#include <iostream>
 
 #include "i18n.h"
 
 
-using std::string;
-using std::vector;
-using std::list;
-using std::cout;
 using std::cerr;
+using std::cout;
 using std::fixed;
-using std::shared_ptr;
+using std::list;
 using std::make_shared;
-using boost::thread;
+using std::shared_ptr;
+using std::string;
+using std::vector;
 using boost::bind;
-using boost::scoped_array;
 using boost::optional;
+using boost::scoped_array;
+using boost::thread;
 using dcp::ArrayData;
 using dcp::Size;
 using dcp::raw_convert;
@@ -151,14 +152,15 @@ EncodeServer::process (shared_ptr<Socket> socket, struct timeval& after_read, st
 
        gettimeofday (&after_read, 0);
 
-       auto encoded = dcp_video_frame.encode_locally ();
+       CPUJ2KFrameEncoder cpu;
+       auto encoded = cpu.encode(dcp_video_frame);
 
        gettimeofday (&after_encode, 0);
 
        try {
                Socket::WriteDigestScope ds (socket);
-               socket->write (encoded.size());
-               socket->write (encoded.data(), encoded.size());
+               socket->write (encoded->size());
+               socket->write (encoded->data(), encoded->size());
        } catch (std::exception& e) {
                cerr << "Send failed; frame " << dcp_video_frame.index() << "\n";
                LOG_ERROR ("Send failed; frame %1", dcp_video_frame.index());
index 47d8b129559b173d7cf23acf8245d1f83221eac3..f9969927fb7ae5bec6fdab6dc22b426ae64890c7 100644 (file)
@@ -137,14 +137,11 @@ J2KEncoder::end ()
             So just mop up anything left in the queue here.
        */
 
+       CPUJ2KFrameEncoder cpu;
        for (auto const& i: _queue) {
                LOG_GENERAL(N_("Encode left-over frame %1"), i.index());
                try {
-                       _writer->write (
-                               make_shared<dcp::ArrayData>(i.encode_locally()),
-                               i.index(),
-                               i.eyes()
-                               );
+                       _writer->write(make_shared<dcp::ArrayData>(*cpu.encode(i)), i.index(), i.eyes());
                        frame_done ();
                } catch (std::exception& e) {
                        LOG_ERROR (N_("Local encode failed (%1)"), e.what ());
@@ -290,12 +287,6 @@ try
                return;
        }
 
-       /* Number of seconds that we currently wait between attempts
-          to connect to the server; not relevant for localhost
-          encodings.
-       */
-       int remote_backoff = 0;
-
        while (true) {
 
                LOG_TIMING ("encoder-sleep thread=%1", thread_id ());
@@ -332,10 +323,6 @@ try
                        }
                }
 
-               if (remote_backoff > 0) {
-                       boost::this_thread::sleep (boost::posix_time::seconds (remote_backoff));
-               }
-
                /* The queue might not be full any more, so notify anything that is waiting on that */
                lock.lock ();
                _full_condition.notify_all ();
index 3917cc07b5645a5d3aeaefc7c4e94631251a3bc3..adaef495ef9ef6ff2558cf00d131065e26cc54b7 100644 (file)
 */
 
 
+#include "config.h"
 #include "cross.h"
 #include "dcp_video.h"
 #include "dcpomatic_log.h"
+#include "dcpomatic_socket.h"
+#include "exceptions.h"
+#include "player_video.h"
 #include "remote_j2k_frame_encoder.h"
+#include <dcp/raw_convert.h>
+#include <dcp/warnings.h>
+LIBDCP_DISABLE_WARNINGS
+#include <libxml++/libxml++.h>
+LIBDCP_ENABLE_WARNINGS
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
 
 #include "i18n.h"
 
 
 using std::make_shared;
 using std::shared_ptr;
+using std::string;
 using boost::optional;
+using dcp::ArrayData;
 using dcp::Data;
 
 
@@ -39,7 +52,54 @@ RemoteJ2KFrameEncoder::encode(DCPVideo const& vf)
        optional<dcp::ArrayData> encoded;
 
        try {
-               encoded = vf.encode_remotely(_server);
+               boost::asio::io_service io_service;
+               boost::asio::ip::tcp::resolver resolver (io_service);
+               boost::asio::ip::tcp::resolver::query query (_server.host_name(), dcp::raw_convert<string>(ENCODE_FRAME_PORT));
+               auto endpoint_iterator = resolver.resolve (query);
+
+               auto socket = make_shared<Socket>(_timeout);
+
+               socket->connect (*endpoint_iterator);
+
+               /* Collect all XML metadata */
+               xmlpp::Document doc;
+               auto root = doc.create_root_node ("EncodingRequest");
+               root->add_child("Version")->add_child_text(dcp::raw_convert<string>(SERVER_LINK_VERSION));
+               root->add_child("Index")->add_child_text(dcp::raw_convert<string>(vf.index()));
+               root->add_child("FramesPerSecond")->add_child_text(dcp::raw_convert<string>(vf.frames_per_second()));
+               root->add_child("J2KBandwidth")->add_child_text(dcp::raw_convert<string>(vf.j2k_bandwidth()));
+               root->add_child("Resolution")->add_child_text(dcp::raw_convert<string>(int(vf.resolution())));
+               vf.frame()->add_metadata(root);
+
+               LOG_DEBUG_ENCODE(N_("Sending frame %1 to remote"), vf.index());
+
+               {
+                       Socket::WriteDigestScope ds (socket);
+
+                       /* Send XML metadata */
+                       auto xml = doc.write_to_string ("UTF-8");
+                       socket->write (xml.length() + 1);
+                       socket->write (reinterpret_cast<uint8_t const *>(xml.c_str()), xml.bytes() + 1);
+
+                       /* Send binary data */
+                       LOG_TIMING("start-remote-send thread=%1", thread_id());
+                       vf.frame()->write_to_socket(socket);
+               }
+
+               /* Read the response (JPEG2000-encoded data); this blocks until the data
+                  is ready and sent back.
+                  */
+               Socket::ReadDigestScope ds (socket);
+               LOG_TIMING("start-remote-encode thread=%1", thread_id());
+               encoded = ArrayData(socket->read_uint32());
+               LOG_TIMING("start-remote-receive thread=%1", thread_id());
+               socket->read (encoded->data(), encoded->size());
+               LOG_TIMING("finish-remote-receive thread=%1", thread_id());
+               if (!ds.check()) {
+                       throw NetworkError ("Checksums do not match");
+               }
+
+               LOG_DEBUG_ENCODE (N_("Finished remotely-encoded frame %1"), vf.index());
 
                if (_remote_backoff > 0) {
                        LOG_GENERAL ("%1 was lost, but now she is found; removing backoff", _server.host_name());
index e532782b2685e5fcfb3de27a58313090c6710c5e..4a8fd0ae6a437d6bfe8405804eaf0f961692fa16 100644 (file)
@@ -29,8 +29,9 @@
 class RemoteJ2KFrameEncoder : public J2KFrameEncoder
 {
 public:
-       RemoteJ2KFrameEncoder(EncodeServerDescription s)
+       RemoteJ2KFrameEncoder(EncodeServerDescription s, int timeout = 30)
                : _server(s)
+               , _timeout(timeout)
        {}
 
        boost::optional<dcp::ArrayData> encode (DCPVideo const &) override;
@@ -38,6 +39,7 @@ public:
 
 private:
        EncodeServerDescription _server;
+       int _timeout;
        int _remote_backoff = 0;
 };
 
index ff3295599da1ca4e905cd922cbfd4b18d49d1dcc..9831605e0464387a6905212e52dbef3af20ecc8d 100644 (file)
@@ -19,6 +19,7 @@
 */
 
 
+#include "lib/cpu_j2k_frame_encoder.h"
 #include "lib/dcp_video.h"
 #include "lib/decoder.h"
 #include "lib/encode_server.h"
@@ -30,6 +31,7 @@
 #include "lib/player.h"
 #include "lib/player_video.h"
 #include "lib/ratio.h"
+#include "lib/remote_j2k_frame_encoder.h"
 #include "lib/util.h"
 #include "lib/video_decoder.h"
 #include <getopt.h>
@@ -60,20 +62,22 @@ static int frame_count = 0;
 void
 process_video (shared_ptr<PlayerVideo> pvf)
 {
-       auto local = make_shared<DCPVideo>(pvf, frame_count, film->video_frame_rate(), 250000000, Resolution::TWO_K);
-       auto remote = make_shared<DCPVideo>(pvf, frame_count, film->video_frame_rate(), 250000000, Resolution::TWO_K);
+       auto local = DCPVideo(pvf, frame_count, film->video_frame_rate(), 250000000, Resolution::TWO_K);
+       auto remote = DCPVideo(pvf, frame_count, film->video_frame_rate(), 250000000, Resolution::TWO_K);
 
        cout << "Frame " << frame_count << ": ";
        cout.flush ();
 
        ++frame_count;
 
-       auto local_encoded = local->encode_locally ();
-       ArrayData remote_encoded;
+       CPUJ2KFrameEncoder cpu;
+       auto local_encoded = cpu.encode(local);
+       optional<dcp::ArrayData> remote_encoded;
 
        string remote_error;
        try {
-               remote_encoded = remote->encode_remotely (*server);
+               RemoteJ2KFrameEncoder encoder(*server);
+               remote_encoded = encoder.encode(remote);
        } catch (NetworkError& e) {
                remote_error = e.what ();
        }
@@ -83,14 +87,14 @@ process_video (shared_ptr<PlayerVideo> pvf)
                return;
        }
 
-       if (local_encoded.size() != remote_encoded.size()) {
+       if (local_encoded->size() != remote_encoded->size()) {
                cout << "\033[0;31msizes differ\033[0m\n";
                return;
        }
 
-       auto p = local_encoded.data();
-       auto q = remote_encoded.data();
-       for (int i = 0; i < local_encoded.size(); ++i) {
+       auto p = local_encoded->data();
+       auto q = remote_encoded->data();
+       for (int i = 0; i < local_encoded->size(); ++i) {
                if (*p++ != *q++) {
                        cout << "\033[0;31mdata differ\033[0m at byte " << i << "\n";
                        return;
index 7a99f72274758a1bace8f1e9f637fe7e1c61d502..3f7acac95b80cd9aa14768b2687dd798461e9c5f 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 
+#include "lib/cpu_j2k_frame_encoder.h"
 #include "lib/cross.h"
 #include "lib/dcp_video.h"
 #include "lib/dcpomatic_log.h"
@@ -39,6 +40,7 @@
 #include "lib/j2k_image_proxy.h"
 #include "lib/player_video.h"
 #include "lib/raw_image_proxy.h"
+#include "lib/remote_j2k_frame_encoder.h"
 #include "test.h"
 #include <boost/test/unit_test.hpp>
 #include <boost/thread.hpp>
@@ -54,13 +56,15 @@ using dcp::ArrayData;
 
 
 void
-do_remote_encode (shared_ptr<DCPVideo> frame, EncodeServerDescription description, ArrayData locally_encoded)
+do_remote_encode (DCPVideo const& frame, EncodeServerDescription description, ArrayData locally_encoded)
 {
-       ArrayData remotely_encoded;
-       BOOST_REQUIRE_NO_THROW (remotely_encoded = frame->encode_remotely (description, 1200));
+       optional<ArrayData> remotely_encoded;
+       RemoteJ2KFrameEncoder remote(description, 1200);
+       BOOST_REQUIRE_NO_THROW (remotely_encoded = remote.encode(frame));
+       BOOST_REQUIRE (remotely_encoded);
 
-       BOOST_REQUIRE_EQUAL (locally_encoded.size(), remotely_encoded.size());
-       BOOST_CHECK_EQUAL (memcmp (locally_encoded.data(), remotely_encoded.data(), locally_encoded.size()), 0);
+       BOOST_REQUIRE_EQUAL (locally_encoded.size(), remotely_encoded->size());
+       BOOST_CHECK_EQUAL (memcmp(locally_encoded.data(), remotely_encoded->data(), locally_encoded.size()), 0);
 }
 
 
@@ -111,7 +115,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb)
 
        pvf->set_text (PositionImage(sub_image, Position<int>(50, 60)));
 
-       auto frame = make_shared<DCPVideo> (
+       auto frame = DCPVideo(
                pvf,
                0,
                24,
@@ -119,7 +123,8 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb)
                Resolution::TWO_K
                );
 
-       auto locally_encoded = frame->encode_locally ();
+       CPUJ2KFrameEncoder cpu;
+       auto locally_encoded = cpu.encode(frame);
 
        auto server = new EncodeServer (true, 2);
 
@@ -133,7 +138,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb)
 
        list<thread*> threads;
        for (int i = 0; i < 8; ++i) {
-               threads.push_back (new thread (boost::bind (do_remote_encode, frame, description, locally_encoded)));
+               threads.push_back(new thread(boost::bind(do_remote_encode, frame, description, *locally_encoded)));
        }
 
        for (auto i: threads) {
@@ -194,7 +199,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv)
 
        pvf->set_text (PositionImage(sub_image, Position<int>(50, 60)));
 
-       auto frame = make_shared<DCPVideo>(
+       auto frame = DCPVideo(
                pvf,
                0,
                24,
@@ -202,7 +207,8 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv)
                Resolution::TWO_K
                );
 
-       auto locally_encoded = frame->encode_locally ();
+       CPUJ2KFrameEncoder cpu;
+       auto locally_encoded = cpu.encode(frame);
 
        auto server = new EncodeServer (true, 2);
 
@@ -216,7 +222,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv)
 
        list<thread*> threads;
        for (int i = 0; i < 8; ++i) {
-               threads.push_back (new thread(boost::bind(do_remote_encode, frame, description, locally_encoded)));
+               threads.push_back(new thread(boost::bind(do_remote_encode, frame, description, *locally_encoded)));
        }
 
        for (auto i: threads) {
@@ -262,7 +268,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
                false
                );
 
-       auto raw_frame = make_shared<DCPVideo> (
+       auto raw_frame = DCPVideo(
                raw_pvf,
                0,
                24,
@@ -270,10 +276,11 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
                Resolution::TWO_K
                );
 
-       auto raw_locally_encoded = raw_frame->encode_locally ();
+       CPUJ2KFrameEncoder cpu;
+       auto raw_locally_encoded = cpu.encode(raw_frame);
 
        auto j2k_pvf = std::make_shared<PlayerVideo> (
-               std::make_shared<J2KImageProxy>(raw_locally_encoded, dcp::Size(1998, 1080), AV_PIX_FMT_XYZ12LE),
+               std::make_shared<J2KImageProxy>(*raw_locally_encoded, dcp::Size(1998, 1080), AV_PIX_FMT_XYZ12LE),
                Crop(),
                optional<double>(),
                dcp::Size(1998, 1080),
@@ -287,7 +294,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
                false
                );
 
-       auto j2k_frame = make_shared<DCPVideo> (
+       auto j2k_frame = DCPVideo(
                j2k_pvf,
                0,
                24,
@@ -295,7 +302,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
                Resolution::TWO_K
                );
 
-       auto j2k_locally_encoded = j2k_frame->encode_locally ();
+       auto j2k_locally_encoded = cpu.encode(j2k_frame);
 
        auto server = new EncodeServer (true, 2);
 
@@ -309,7 +316,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
 
        list<thread*> threads;
        for (int i = 0; i < 8; ++i) {
-               threads.push_back (new thread(boost::bind(do_remote_encode, j2k_frame, description, j2k_locally_encoded)));
+               threads.push_back(new thread(boost::bind(do_remote_encode, j2k_frame, description, *j2k_locally_encoded)));
        }
 
        for (auto i: threads) {
index 7050dd771acc6dd74dd8a57f0e30b8d177010470..f71a69d785dc697a9dad0d11ef0af4f60422e578 100644 (file)
@@ -19,6 +19,7 @@
 */
 
 
+#include "lib/cpu_j2k_frame_encoder.h"
 #include "lib/dcp_video.h"
 #include "lib/image.h"
 #include "lib/player_video.h"
@@ -55,9 +56,10 @@ BOOST_AUTO_TEST_CASE (low_bitrate_test)
                false
                );
 
-       auto dcp_video = make_shared<DCPVideo>(frame, 0, 24, 100000000, Resolution::TWO_K);
-       auto j2k = dcp_video->encode_locally();
-       BOOST_REQUIRE (j2k.size() >= 16536);
+       auto dcp_video = DCPVideo(frame, 0, 24, 100000000, Resolution::TWO_K);
+       CPUJ2KFrameEncoder cpu;
+       auto j2k = cpu.encode(dcp_video);
+       BOOST_REQUIRE (j2k->size() >= 16536);
 }