Rearrange encoding so that the different methods / backends are not all crammed into...
authorCarl Hetherington <cth@carlh.net>
Thu, 13 Aug 2020 12:55:20 +0000 (14:55 +0200)
committerCarl Hetherington <cth@carlh.net>
Sun, 13 Sep 2020 18:23:29 +0000 (20:23 +0200)
14 files changed:
src/lib/dcp_video.cc
src/lib/dcp_video.h
src/lib/encode_server.cc
src/lib/encode_server.h
src/lib/j2k_encoder.cc
src/lib/j2k_encoder.h
src/lib/j2k_encoder_backend.h [new file with mode: 0644]
src/lib/j2k_encoder_cpu_backend.cc [new file with mode: 0644]
src/lib/j2k_encoder_cpu_backend.h [new file with mode: 0644]
src/lib/j2k_encoder_remote_backend.cc [new file with mode: 0644]
src/lib/j2k_encoder_remote_backend.h [new file with mode: 0644]
src/lib/wscript
src/tools/server_test.cc
test/client_server_test.cc

index 440571b760705c0dec18627e444e569d2b2eccba..161f74c57121abac0c9dbaa4f3a75696d4695d3e 100644 (file)
@@ -32,7 +32,6 @@
 #include "config.h"
 #include "exceptions.h"
 #include "encode_server_description.h"
-#include "dcpomatic_socket.h"
 #include "image.h"
 #include "log.h"
 #include "dcpomatic_log.h"
@@ -48,7 +47,6 @@
 DCPOMATIC_DISABLE_WARNINGS
 #include <libxml++/libxml++.h>
 DCPOMATIC_ENABLE_WARNINGS
-#include <boost/asio.hpp>
 #include <boost/thread.hpp>
 #include <stdint.h>
 #include <iomanip>
@@ -117,95 +115,6 @@ DCPVideo::convert_to_xyz (shared_ptr<const PlayerVideo> frame, dcp::NoteHandler
        return xyz;
 }
 
-/** J2K-encode this frame on the local host.
- *  @return Encoded data.
- */
-Data
-DCPVideo::encode_locally ()
-{
-       string const comment = Config::instance()->dcp_j2k_comment();
-
-       Data enc = dcp::compress_j2k (
-               convert_to_xyz (_frame, boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2)),
-               _j2k_bandwidth,
-               _frames_per_second,
-               _frame->eyes() == EYES_LEFT || _frame->eyes() == EYES_RIGHT,
-               _resolution == RESOLUTION_4K,
-               comment.empty() ? "libdcp" : comment
-               );
-
-       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.
- */
-Data
-DCPVideo::encode_remotely (EncodeServerDescription serv, int timeout)
-{
-       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);
-
-       shared_ptr<Socket> socket (new Socket (timeout));
-
-       socket->connect (*endpoint_iterator);
-
-       /* Collect all XML metadata */
-       xmlpp::Document doc;
-       xmlpp::Element* 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 */
-               string xml = doc.write_to_string ("UTF-8");
-               socket->write (xml.length() + 1);
-               socket->write ((uint8_t *) xml.c_str(), xml.length() + 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 ());
-       Data e (socket->read_uint32 ());
-       LOG_TIMING("start-remote-receive thread=%1", thread_id ());
-       socket->read (e.data().get(), 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
@@ -217,11 +126,6 @@ DCPVideo::add_metadata (xmlpp::Element* el) const
        _frame->add_metadata (el);
 }
 
-Eyes
-DCPVideo::eyes () const
-{
-       return _frame->eyes ();
-}
 
 /** @return true if this DCPVideo is definitely the same as another;
  *  (apart from the frame index), false if it is probably not.
index 81ddc4470c9e748f81289262a3da382eae11ee68..49a8587333f2b330940443504c82552adde2646b 100644 (file)
@@ -45,23 +45,32 @@ public:
        DCPVideo (boost::shared_ptr<const PlayerVideo>, int, int, int, Resolution);
        DCPVideo (boost::shared_ptr<const PlayerVideo>, cxml::ConstNodePtr);
 
-       dcp::Data encode_locally ();
-       dcp::Data encode_remotely (EncodeServerDescription, int timeout = 30);
+       boost::shared_ptr<const PlayerVideo> frame () const {
+               return _frame;
+       }
 
        int index () const {
                return _index;
        }
 
-       Eyes eyes () const;
+       int frames_per_second () const {
+               return _frames_per_second;
+       }
+
+       int j2k_bandwidth () const {
+               return _j2k_bandwidth;
+       }
+
+       Resolution resolution () const {
+               return _resolution;
+       }
 
        bool same (boost::shared_ptr<const DCPVideo> other) const;
+       void add_metadata (xmlpp::Element *) const;
 
        static boost::shared_ptr<dcp::OpenJPEGImage> convert_to_xyz (boost::shared_ptr<const PlayerVideo> frame, dcp::NoteHandler note);
 
 private:
-
-       void add_metadata (xmlpp::Element *) const;
-
        boost::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 f4224798bce211f423574aed7c0496ecb1e0958e..85f3ca7b005cafee64914deaa93efd6de5d02ffe 100644 (file)
@@ -141,11 +141,11 @@ EncodeServer::process (shared_ptr<Socket> socket, struct timeval& after_read, st
                throw NetworkError ("Checksums do not match");
        }
 
-       DCPVideo dcp_video_frame (pvf, xml);
+       shared_ptr<DCPVideo> frame(new DCPVideo(pvf, xml));
 
        gettimeofday (&after_read, 0);
 
-       Data encoded = dcp_video_frame.encode_locally ();
+       Data encoded = *_cpu_encoder.encode (frame);
 
        gettimeofday (&after_encode, 0);
 
@@ -154,12 +154,12 @@ EncodeServer::process (shared_ptr<Socket> socket, struct timeval& after_read, st
                socket->write (encoded.size());
                socket->write (encoded.data().get(), 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());
+               cerr << "Send failed; frame " << frame->index() << "\n";
+               LOG_ERROR ("Send failed; frame %1", frame->index());
                throw;
        }
 
-       return dcp_video_frame.index ();
+       return frame->index ();
 }
 
 void
index a43cea7efea8228a02a06d063766bd861948477f..af1ead2bb6a1e1e7728257bbfc41d2fb4c5e5b92 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "server.h"
 #include "exception_store.h"
+#include "j2k_encoder_cpu_backend.h"
 #include <boost/thread.hpp>
 #include <boost/asio.hpp>
 #include <boost/thread/condition.hpp>
@@ -61,6 +62,8 @@ private:
        bool _verbose;
        int _num_threads;
 
+       J2KEncoderCPUBackend _cpu_encoder;
+
        struct Broadcast {
 
                Broadcast ()
index 64cd3814784306877628794326fdcec462cd88af..ef38aaa55f859f7843ff388d21310c35d0f47ce0 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -23,6 +23,9 @@
  */
 
 #include "j2k_encoder.h"
+#include "j2k_encoder_backend.h"
+#include "j2k_encoder_cpu_backend.h"
+#include "j2k_encoder_remote_backend.h"
 #include "util.h"
 #include "film.h"
 #include "log.h"
@@ -57,6 +60,7 @@ using namespace dcpomatic;
 J2KEncoder::J2KEncoder (shared_ptr<const Film> film, shared_ptr<Writer> writer)
        : _film (film)
        , _history (200)
+       , _cpu_backend (new J2KEncoderCPUBackend())
        , _writer (writer)
 {
        servers_list_changed ();
@@ -123,13 +127,13 @@ J2KEncoder::end ()
             So just mop up anything left in the queue here.
        */
 
-       for (list<shared_ptr<DCPVideo> >::iterator i = _queue.begin(); i != _queue.end(); ++i) {
-               LOG_GENERAL (N_("Encode left-over frame %1"), (*i)->index ());
+       BOOST_FOREACH (shared_ptr<DCPVideo> i, _queue) {
+               LOG_GENERAL (N_("Encode left-over frame %1"), i->index());
                try {
                        _writer->write (
-                               (*i)->encode_locally(),
-                               (*i)->index(),
-                               (*i)->eyes()
+                               *_cpu_backend->encode(i),
+                               i->index(),
+                               i->frame()->eyes()
                                );
                        frame_done ();
                } catch (std::exception& e) {
@@ -258,20 +262,10 @@ J2KEncoder::terminate_threads ()
 }
 
 void
-J2KEncoder::encoder_thread (optional<EncodeServerDescription> server)
+J2KEncoder::encoder_thread (shared_ptr<J2KEncoderBackend> backend)
 try
 {
-       if (server) {
-               LOG_TIMING ("start-encoder-thread thread=%1 server=%2", thread_id (), server->host_name ());
-       } else {
-               LOG_TIMING ("start-encoder-thread thread=%1 server=localhost", thread_id ());
-       }
-
-       /* Number of seconds that we currently wait between attempts
-          to connect to the server; not relevant for localhost
-          encodings.
-       */
-       int remote_backoff = 0;
+       LOG_TIMING ("start-encoder-thread thread=%1", thread_id());
 
        while (true) {
 
@@ -291,50 +285,15 @@ try
                {
                        boost::this_thread::disable_interruption dis;
 
-                       LOG_TIMING ("encoder-pop thread=%1 frame=%2 eyes=%3", thread_id(), vf->index(), (int) vf->eyes ());
+                       LOG_TIMING ("encoder-pop thread=%1 frame=%2 eyes=%3", thread_id(), vf->index(), (int) vf->frame()->eyes());
                        _queue.pop_front ();
 
                        lock.unlock ();
 
-                       optional<Data> encoded;
-
-                       /* We need to encode this input */
-                       if (server) {
-                               try {
-                                       encoded = vf->encode_remotely (server.get ());
-
-                                       if (remote_backoff > 0) {
-                                               LOG_GENERAL ("%1 was lost, but now she is found; removing backoff", server->host_name ());
-                                       }
-
-                                       /* This job succeeded, so remove any backoff */
-                                       remote_backoff = 0;
-
-                               } catch (std::exception& e) {
-                                       if (remote_backoff < 60) {
-                                               /* back off more */
-                                               remote_backoff += 10;
-                                       }
-                                       LOG_ERROR (
-                                               N_("Remote encode of %1 on %2 failed (%3); thread sleeping for %4s"),
-                                               vf->index(), server->host_name(), e.what(), remote_backoff
-                                               );
-                               }
-
-                       } else {
-                               try {
-                                       LOG_TIMING ("start-local-encode thread=%1 frame=%2", thread_id(), vf->index());
-                                       encoded = 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 */
-                                       LOG_ERROR (N_("Local encode failed (%1)"), e.what ());
-                                       throw;
-                               }
-                       }
+                       optional<Data> encoded = backend->encode (vf);
 
                        if (encoded) {
-                               _writer->write (encoded.get(), vf->index (), vf->eyes ());
+                               _writer->write (encoded.get(), vf->index (), vf->frame()->eyes());
                                frame_done ();
                        } else {
                                lock.lock ();
@@ -344,10 +303,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 ();
@@ -375,10 +330,10 @@ J2KEncoder::servers_list_changed ()
        if (!Config::instance()->only_servers_encode ()) {
                for (int i = 0; i < Config::instance()->master_encoding_threads (); ++i) {
 #ifdef DCPOMATIC_LINUX
-                       boost::thread* t = _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, optional<EncodeServerDescription>()));
+                       boost::thread* t = _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, _cpu_backend));
                        pthread_setname_np (t->native_handle(), "encode-worker");
 #else
-                       _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, optional<EncodeServerDescription>()));
+                       _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, _cpu_backend));
 #endif
                }
        }
@@ -389,8 +344,9 @@ J2KEncoder::servers_list_changed ()
                }
 
                LOG_GENERAL (N_("Adding %1 worker threads for remote %2"), i.threads(), i.host_name ());
+               shared_ptr<J2KEncoderRemoteBackend> backend (new J2KEncoderRemoteBackend(i));
                for (int j = 0; j < i.threads(); ++j) {
-                       _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, i));
+                       _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, backend));
                }
        }
 
index d56fc1aecd19576c15c96525ce77193fff66d9f9..df23a5bae4e75d54aa3625e3d4ce361905be32e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -45,6 +45,10 @@ class DCPVideo;
 class Writer;
 class Job;
 class PlayerVideo;
+class J2KEncoderBackend;
+class J2KEncoderCPUBackend;
+class J2KEncoderRemoteBackend;
+
 
 /** @class J2KEncoder
  *  @brief Class to manage encoding to J2K.
@@ -79,16 +83,17 @@ private:
 
        void frame_done ();
 
-       void encoder_thread (boost::optional<EncodeServerDescription>);
+       void encoder_thread (boost::shared_ptr<J2KEncoderBackend> backend);
        void terminate_threads ();
 
-       /** Film that we are encoding */
        boost::shared_ptr<const Film> _film;
 
        EventHistory _history;
 
        boost::shared_ptr<boost::thread_group> _threads;
 
+       boost::shared_ptr<J2KEncoderCPUBackend> _cpu_backend;
+
        mutable boost::mutex _queue_mutex;
        std::list<boost::shared_ptr<DCPVideo> > _queue;
        /** condition to manage thread wakeups when we have nothing to do */
diff --git a/src/lib/j2k_encoder_backend.h b/src/lib/j2k_encoder_backend.h
new file mode 100644 (file)
index 0000000..7688e5f
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef DCPOMATIC_J2K_ENCODER_BACKEND_H
+#define DCPOMATIC_J2K_ENCODER_BACKEND_H
+
+#include <dcp/data.h>
+#include <boost/noncopyable.hpp>
+#include <boost/optional.hpp>
+#include <boost/shared_ptr.hpp>
+
+
+class DCPVideo;
+
+
+class J2KEncoderBackend : public boost::noncopyable
+{
+public:
+       virtual boost::optional<dcp::Data> encode (boost::shared_ptr<DCPVideo> video) = 0;
+};
+
+#endif
diff --git a/src/lib/j2k_encoder_cpu_backend.cc b/src/lib/j2k_encoder_cpu_backend.cc
new file mode 100644 (file)
index 0000000..732913c
--- /dev/null
@@ -0,0 +1,56 @@
+#include "config.h"
+#include "cross.h"
+#include "dcp_video.h"
+#include "dcpomatic_log.h"
+#include "j2k_encoder_cpu_backend.h"
+#include "player_video.h"
+#include <dcp/j2k.h>
+
+#include "i18n.h"
+
+
+using std::string;
+using boost::optional;
+using boost::shared_ptr;
+using dcp::Data;
+
+
+optional<Data>
+J2KEncoderCPUBackend::encode (shared_ptr<DCPVideo> video)
+{
+       try {
+               LOG_TIMING ("start-local-encode thread=%1 frame=%2", thread_id(), video->index());
+               string const comment = Config::instance()->dcp_j2k_comment();
+
+               Data enc = dcp::compress_j2k (
+                       DCPVideo::convert_to_xyz (video->frame(), boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2)),
+                       video->j2k_bandwidth(),
+                       video->frames_per_second(),
+                       video->frame()->eyes() == EYES_LEFT || video->frame()->eyes() == EYES_RIGHT,
+                       video->resolution() == RESOLUTION_4K,
+                       comment.empty() ? "libdcp" : comment
+                       );
+
+               switch (video->frame()->eyes()) {
+               case EYES_BOTH:
+                       LOG_DEBUG_ENCODE (N_("Finished locally-encoded frame %1 for mono"), video->index());
+                       break;
+               case EYES_LEFT:
+                       LOG_DEBUG_ENCODE (N_("Finished locally-encoded frame %1 for L"), video->index());
+                       break;
+               case EYES_RIGHT:
+                       LOG_DEBUG_ENCODE (N_("Finished locally-encoded frame %1 for R"), video->index());
+                       break;
+               default:
+                       break;
+               }
+
+               LOG_TIMING ("finish-local-encode thread=%1 frame=%2", thread_id(), video->index());
+               return enc;
+       } catch (std::exception& e) {
+               /* This is very bad, so don't cope with it, just pass it on */
+               LOG_ERROR (N_("Local encode failed (%1)"), e.what());
+               throw;
+       }
+}
+
diff --git a/src/lib/j2k_encoder_cpu_backend.h b/src/lib/j2k_encoder_cpu_backend.h
new file mode 100644 (file)
index 0000000..75d7c97
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef DCPOMATIC_J2K_ENCODER_CPU_BACKEND_H
+#define DCPOMATIC_J2K_ENCODER_CPU_BACKEND_H
+
+
+#include "j2k_encoder_backend.h"
+
+
+class J2KEncoderCPUBackend : public J2KEncoderBackend
+{
+public:
+       boost::optional<dcp::Data> encode (boost::shared_ptr<DCPVideo> video);
+};
+
+#endif
diff --git a/src/lib/j2k_encoder_remote_backend.cc b/src/lib/j2k_encoder_remote_backend.cc
new file mode 100644 (file)
index 0000000..8311347
--- /dev/null
@@ -0,0 +1,108 @@
+#include "config.h"
+#include "cross.h"
+#include "dcp_video.h"
+#include "dcpomatic_log.h"
+#include "dcpomatic_socket.h"
+#include "encode_server_description.h"
+#include "j2k_encoder_remote_backend.h"
+#include "player_video.h"
+#include "warnings.h"
+#include <dcp/raw_convert.h>
+DCPOMATIC_DISABLE_WARNINGS
+#include <libxml++/libxml++.h>
+DCPOMATIC_ENABLE_WARNINGS
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
+
+#include "i18n.h"
+
+
+using std::string;
+using boost::optional;
+using boost::shared_ptr;
+using dcp::Data;
+using dcp::raw_convert;
+
+
+J2KEncoderRemoteBackend::J2KEncoderRemoteBackend (EncodeServerDescription server)
+       : _server (server)
+       , _backoff (0)
+{
+
+}
+
+
+optional<Data>
+J2KEncoderRemoteBackend::encode (shared_ptr<DCPVideo> video)
+{
+       int const timeout = 30;
+
+       try {
+               boost::asio::io_service io_service;
+               boost::asio::ip::tcp::resolver resolver (io_service);
+               boost::asio::ip::tcp::resolver::query query (_server.host_name(), raw_convert<string>(ENCODE_FRAME_PORT));
+               boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query);
+
+               shared_ptr<Socket> socket (new Socket(timeout));
+
+               socket->connect (*endpoint_iterator);
+
+               /* Collect all XML metadata */
+               xmlpp::Document doc;
+               xmlpp::Element* root = doc.create_root_node ("EncodingRequest");
+               root->add_child("Version")->add_child_text(raw_convert<string> (SERVER_LINK_VERSION));
+               video->add_metadata (root);
+
+               LOG_DEBUG_ENCODE (N_("Sending frame %1 to remote"), video->index());
+
+               {
+                       Socket::WriteDigestScope ds (socket);
+
+                       /* Send XML metadata */
+                       string xml = doc.write_to_string ("UTF-8");
+                       socket->write (xml.length() + 1);
+                       socket->write ((uint8_t *) xml.c_str(), xml.length() + 1);
+
+                       /* Send binary data */
+                       LOG_TIMING("start-remote-send thread=%1", thread_id());
+                       video->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());
+               Data e (socket->read_uint32 ());
+               LOG_TIMING("start-remote-receive thread=%1", thread_id());
+               socket->read (e.data().get(), 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"), video->index());
+
+               if (_backoff > 0) {
+                       LOG_GENERAL ("%1 was lost, but now she is found; removing backoff", _server.host_name());
+               }
+
+               /* This job succeeded, so remove any backoff */
+               _backoff = 0;
+
+               return e;
+
+       } catch (std::exception& e) {
+               if (_backoff < 60) {
+                       _backoff += 10;
+               }
+               LOG_ERROR (
+                       N_("Remote encode of %1 on %2 failed (%3); thread sleeping for %4s"),
+                       video->index(), _server.host_name(), e.what(), _backoff
+                       );
+
+               boost::this_thread::sleep (boost::posix_time::seconds(_backoff));
+               return optional<Data>();
+       }
+}
+
diff --git a/src/lib/j2k_encoder_remote_backend.h b/src/lib/j2k_encoder_remote_backend.h
new file mode 100644 (file)
index 0000000..5e62cd9
--- /dev/null
@@ -0,0 +1,16 @@
+#include "encode_server_description.h"
+#include "j2k_encoder_backend.h"
+
+
+class J2KEncoderRemoteBackend : public J2KEncoderBackend
+{
+public:
+       J2KEncoderRemoteBackend (EncodeServerDescription server);
+       boost::optional<dcp::Data> encode (boost::shared_ptr<DCPVideo> video);
+
+private:
+       EncodeServerDescription _server;
+       int _backoff;
+};
+
+
index 3b14f8738312d7df6fc3aefbc7dfc65b1e1525d9..59cc145a25918aa172eda92a03837c133a8c4625 100644 (file)
@@ -125,9 +125,11 @@ sources = """
           image_proxy.cc
           isdcf_metadata.cc
           j2k_image_proxy.cc
+          j2k_encoder.cc
+          j2k_encoder_cpu_backend.cc
+          j2k_encoder_remote_backend.cc
           job.cc
           job_manager.cc
-          j2k_encoder.cc
           json_server.cc
           kdm_with_metadata.cc
           kdm_recipient.cc
index 99a6b4cafedf4d02b74bb48a5d3f8dc7837ce709..4f8d0b4d14048fa411ae17abfb5a8ed7cb46672e 100644 (file)
@@ -31,6 +31,8 @@
 #include "lib/player.h"
 #include "lib/player_video.h"
 #include "lib/encode_server_description.h"
+#include "lib/j2k_encoder_cpu_backend.h"
+#include "lib/j2k_encoder_remote_backend.h"
 #include <getopt.h>
 #include <iostream>
 #include <iomanip>
@@ -63,12 +65,14 @@ process_video (shared_ptr<PlayerVideo> pvf)
 
        ++frame_count;
 
-       Data local_encoded = local->encode_locally ();
+       J2KEncoderCPUBackend cpu_backend;
+       Data local_encoded = *cpu_backend.encode (local);
        Data remote_encoded;
 
        string remote_error;
        try {
-               remote_encoded = remote->encode_remotely (*server);
+               J2KEncoderRemoteBackend remote_backend(*server);
+               remote_encoded = *remote_backend.encode (remote);
        } catch (NetworkError& e) {
                remote_error = e.what ();
        }
index 6146bdeb07112980fd33d3c157ed336aacd4222d..c0c853fc11891f139a6c453f8116e90a46396b8a 100644 (file)
@@ -37,6 +37,8 @@
 #include "lib/encode_server_description.h"
 #include "lib/file_log.h"
 #include "lib/dcpomatic_log.h"
+#include "lib/j2k_encoder_cpu_backend.h"
+#include "lib/j2k_encoder_remote_backend.h"
 #include "test.h"
 #include <boost/test/unit_test.hpp>
 #include <boost/thread.hpp>
@@ -51,15 +53,16 @@ using namespace dcpomatic;
 
 
 void
-do_remote_encode (shared_ptr<DCPVideo> frame, EncodeServerDescription description, Data locally_encoded)
+do_remote_encode (shared_ptr<DCPVideo> frame, shared_ptr<J2KEncoderBackend> backend, Data locally_encoded)
 {
        Data remotely_encoded;
-       BOOST_REQUIRE_NO_THROW (remotely_encoded = frame->encode_remotely (description, 1200));
+       BOOST_REQUIRE_NO_THROW (remotely_encoded = *backend->encode(frame));
 
        BOOST_REQUIRE_EQUAL (locally_encoded.size(), remotely_encoded.size());
        BOOST_CHECK_EQUAL (memcmp (locally_encoded.data().get(), remotely_encoded.data().get(), locally_encoded.size()), 0);
 }
 
+
 BOOST_AUTO_TEST_CASE (client_server_test_rgb)
 {
        shared_ptr<Image> image (new Image (AV_PIX_FMT_RGB24, dcp::Size (1998, 1080), true));
@@ -119,7 +122,8 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb)
                        )
                );
 
-       Data locally_encoded = frame->encode_locally ();
+       J2KEncoderCPUBackend cpu;
+       Data locally_encoded = *cpu.encode(frame);
 
        EncodeServer* server = new EncodeServer (true, 2);
 
@@ -133,7 +137,8 @@ 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)));
+               shared_ptr<J2KEncoderRemoteBackend> backend (new J2KEncoderRemoteBackend(description));
+               threads.push_back (new thread (boost::bind (do_remote_encode, frame, backend, locally_encoded)));
        }
 
        for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
@@ -205,7 +210,8 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv)
                        )
                );
 
-       Data locally_encoded = frame->encode_locally ();
+       J2KEncoderCPUBackend cpu;
+       Data locally_encoded = *cpu.encode(frame);
 
        EncodeServer* server = new EncodeServer (true, 2);
 
@@ -219,7 +225,8 @@ 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)));
+               shared_ptr<J2KEncoderRemoteBackend> backend (new J2KEncoderRemoteBackend(description));
+               threads.push_back (new thread (boost::bind (do_remote_encode, frame, backend, locally_encoded)));
        }
 
        for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
@@ -276,7 +283,8 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
                        )
                );
 
-       Data raw_locally_encoded = raw_frame->encode_locally ();
+       J2KEncoderCPUBackend cpu;
+       Data raw_locally_encoded = *cpu.encode(raw_frame);
 
        shared_ptr<PlayerVideo> j2k_pvf (
                new PlayerVideo (
@@ -305,7 +313,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
                        )
                );
 
-       Data j2k_locally_encoded = j2k_frame->encode_locally ();
+       Data j2k_locally_encoded = *cpu.encode(j2k_frame);
 
        EncodeServer* server = new EncodeServer (true, 2);
 
@@ -319,7 +327,8 @@ 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)));
+               shared_ptr<J2KEncoderRemoteBackend> backend (new J2KEncoderRemoteBackend(description));
+               threads.push_back (new thread (boost::bind (do_remote_encode, j2k_frame, backend, j2k_locally_encoded)));
        }
 
        for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {