wip: encoding; crashes on startup.
authorCarl Hetherington <cth@carlh.net>
Fri, 14 Aug 2020 11:44:58 +0000 (13:44 +0200)
committerCarl Hetherington <cth@carlh.net>
Sun, 13 Sep 2020 18:23:29 +0000 (20:23 +0200)
15 files changed:
src/lib/encode_server.cc
src/lib/event_history.cc
src/lib/event_history.h
src/lib/j2k_encoder.cc
src/lib/j2k_encoder.h
src/lib/j2k_encoder_backend.h
src/lib/j2k_encoder_cpu_backend.cc
src/lib/j2k_encoder_cpu_backend.h
src/lib/j2k_encoder_remote_backend.cc
src/lib/j2k_encoder_remote_backend.h
src/lib/player_video.cc
src/lib/wscript
src/tools/server_test.cc
test/client_server_test.cc
wscript

index 85f3ca7b005cafee64914deaa93efd6de5d02ffe..acb40c1b22d96d3fefd391024709b6346c1c3d21 100644 (file)
@@ -142,10 +142,12 @@ EncodeServer::process (shared_ptr<Socket> socket, struct timeval& after_read, st
        }
 
        shared_ptr<DCPVideo> frame(new DCPVideo(pvf, xml));
+       vector<shared_ptr<DCPVideo> > frames;
+       frames.push_back (frame);
 
        gettimeofday (&after_read, 0);
 
-       Data encoded = *_cpu_encoder.encode (frame);
+       Data encoded = _cpu_encoder.encode (frames).front();
 
        gettimeofday (&after_encode, 0);
 
index efe80b243ce53f328609b1d8be2af1975a725b79..75ef3319e6f2b70e125784edfe246976287cf26b 100644 (file)
 #include "util.h"
 #include <boost/thread/mutex.hpp>
 
+
+using std::list;
+using std::make_pair;
+using std::pair;
 using boost::optional;
 
+
 EventHistory::EventHistory (int size)
        : _size (size)
 {
@@ -38,21 +43,26 @@ EventHistory::rate () const
                return optional<float>();
        }
 
+       int total = 0;
+       for (list<pair<struct timeval, int> >::const_iterator i = _history.begin(); i != _history.end(); ++i) {
+               total += i->second;
+       }
+
        struct timeval now;
        gettimeofday (&now, 0);
 
-       return _size / (seconds (now) - seconds (_history.back ()));
+       return total / (seconds(now) - seconds(_history.back().first));
 }
 
 void
-EventHistory::event ()
+EventHistory::event (int count)
 {
        boost::mutex::scoped_lock lock (_mutex);
 
        struct timeval tv;
        gettimeofday (&tv, 0);
-       _history.push_front (tv);
-       if (int (_history.size()) > _size) {
+       _history.push_front (make_pair(tv, count));
+       if (int(_history.size()) > _size) {
                _history.pop_back ();
        }
 }
index 4670e7bfe8069b215448d09c62f545af909c7d1c..51684ea1611d60620738c6f2c2cfdba07999575e 100644 (file)
@@ -31,7 +31,7 @@ public:
        explicit EventHistory (int size);
 
        boost::optional<float> rate () const;
-       void event ();
+       void event (int count = 1);
 
 private:
        /** Mutex for _history */
@@ -39,8 +39,8 @@ private:
        /** List of the times of the last _history_size events
            first is the most recently completed.
        */
-       std::list<struct timeval> _history;
-       /** Number of events that we should keep history for */
+       std::list<std::pair<struct timeval, int> > _history;
+       /** Maximum size of _history */
        int const _size;
 };
 
index ef38aaa55f859f7843ff388d21310c35d0f47ce0..8c915b567364deb25d4a919a8dcd0565a7128fef 100644 (file)
@@ -26,6 +26,7 @@
 #include "j2k_encoder_backend.h"
 #include "j2k_encoder_cpu_backend.h"
 #include "j2k_encoder_remote_backend.h"
+#include "j2k_encoder_fastvideo_backend.h"
 #include "util.h"
 #include "film.h"
 #include "log.h"
@@ -48,6 +49,7 @@
 using std::list;
 using std::cout;
 using std::exception;
+using std::vector;
 using boost::shared_ptr;
 using boost::weak_ptr;
 using boost::optional;
@@ -130,12 +132,15 @@ J2KEncoder::end ()
        BOOST_FOREACH (shared_ptr<DCPVideo> i, _queue) {
                LOG_GENERAL (N_("Encode left-over frame %1"), i->index());
                try {
+                       /* XXX: ewww */
+                       vector<shared_ptr<DCPVideo> > frames;
+                       frames.push_back (i);
                        _writer->write (
-                               *_cpu_backend->encode(i),
+                               _cpu_backend->encode(frames).front(),
                                i->index(),
                                i->frame()->eyes()
                                );
-                       frame_done ();
+                       frames_done (1);
                } catch (std::exception& e) {
                        LOG_ERROR (N_("Local encode failed (%1)"), e.what ());
                }
@@ -164,9 +169,9 @@ J2KEncoder::video_frames_enqueued () const
 
 /** Should be called when a frame has been encoded successfully */
 void
-J2KEncoder::frame_done ()
+J2KEncoder::frames_done (int number)
 {
-       _history.event ();
+       _history.event (number);
 }
 
 /** Called to request encoding of the next video frame in the DCP.  This is called in order,
@@ -208,7 +213,7 @@ J2KEncoder::encode (shared_ptr<PlayerVideo> pv, DCPTime time)
                /* We can fake-write this frame */
                LOG_DEBUG_ENCODE("Frame @ %1 FAKE", to_string(time));
                _writer->fake_write (position, pv->eyes ());
-               frame_done ();
+               frames_done (1);
        } else if (pv->has_j2k() && !_film->reencode_j2k()) {
                LOG_DEBUG_ENCODE("Frame @ %1 J2K", to_string(time));
                /* This frame already has J2K data, so just write it */
@@ -271,34 +276,44 @@ try
 
                LOG_TIMING ("encoder-sleep thread=%1", thread_id ());
                boost::mutex::scoped_lock lock (_queue_mutex);
-               while (_queue.empty ()) {
+               while (static_cast<int>(_queue.size()) < backend->quantity()) {
                        _empty_condition.wait (lock);
                }
 
                LOG_TIMING ("encoder-wake thread=%1 queue=%2", thread_id(), _queue.size());
-               shared_ptr<DCPVideo> vf = _queue.front ();
+               vector<shared_ptr<DCPVideo> > video;
+               for (int i = 0; i < backend->quantity(); ++i) {
+                       video.push_back (_queue.front());
+               }
 
-               /* We're about to commit to either encoding this frame or putting it back onto the queue,
+               /* We're about to commit to either encoding these frame(s) or putting them back onto the queue,
                   so we must not be interrupted until one or other of these things have happened.  This
                   block has thread interruption disabled.
                */
                {
                        boost::this_thread::disable_interruption dis;
 
-                       LOG_TIMING ("encoder-pop thread=%1 frame=%2 eyes=%3", thread_id(), vf->index(), (int) vf->frame()->eyes());
-                       _queue.pop_front ();
+                       LOG_TIMING ("encoder-pop thread=%1 frames=%2 eyes=%3", thread_id(), video.size());
+                       for (int i = 0; i < backend->quantity(); ++i) {
+                               _queue.pop_front ();
+                       }
 
                        lock.unlock ();
 
-                       optional<Data> encoded = backend->encode (vf);
+                       vector<Data> encoded = backend->encode (video);
 
-                       if (encoded) {
-                               _writer->write (encoded.get(), vf->index (), vf->frame()->eyes());
-                               frame_done ();
+                       if (!encoded.empty()) {
+                               DCPOMATIC_ASSERT (static_cast<int>(encoded.size()) == backend->quantity());
+                               for (int i = 0; i < backend->quantity(); ++i) {
+                                       _writer->write (encoded[i], video[i]->index(), video[i]->frame()->eyes());
+                               }
+                               frames_done (backend->quantity());
                        } else {
                                lock.lock ();
-                               LOG_GENERAL (N_("[%1] J2KEncoder thread pushes frame %2 back onto queue after failure"), thread_id(), vf->index());
-                               _queue.push_front (vf);
+                               LOG_GENERAL (N_("[%1] J2KEncoder thread pushes %2 frames back onto queue after failure"), thread_id(), video.size());
+                               for (vector<shared_ptr<DCPVideo> >::const_reverse_iterator i = video.rbegin(); i != video.rend(); ++i) {
+                                       _queue.push_front (*i);
+                               }
                                lock.unlock ();
                        }
                }
@@ -350,5 +365,8 @@ J2KEncoder::servers_list_changed ()
                }
        }
 
+       shared_ptr<J2KEncoderFastvideoBackend> fastvideo(new J2KEncoderFastvideoBackend());
+       _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, fastvideo));
+
        _writer->set_encoder_threads (_threads->size());
 }
index df23a5bae4e75d54aa3625e3d4ce361905be32e8..cc782d96d949ba7bd76114191eb5e28af45edbad 100644 (file)
@@ -81,7 +81,7 @@ private:
 
        static void call_servers_list_changed (boost::weak_ptr<J2KEncoder> encoder);
 
-       void frame_done ();
+       void frames_done (int number);
 
        void encoder_thread (boost::shared_ptr<J2KEncoderBackend> backend);
        void terminate_threads ();
index 7688e5f153ff5afe6032d671e4e1183e355ad7c5..a19beda530ef42f4c4f81aa2d97910677f5d5805 100644 (file)
@@ -2,6 +2,7 @@
 #define DCPOMATIC_J2K_ENCODER_BACKEND_H
 
 #include <dcp/data.h>
+#include <boost/foreach.hpp>
 #include <boost/noncopyable.hpp>
 #include <boost/optional.hpp>
 #include <boost/shared_ptr.hpp>
@@ -13,7 +14,11 @@ class DCPVideo;
 class J2KEncoderBackend : public boost::noncopyable
 {
 public:
-       virtual boost::optional<dcp::Data> encode (boost::shared_ptr<DCPVideo> video) = 0;
+       virtual std::vector<dcp::Data> encode (std::vector<boost::shared_ptr<DCPVideo> > video) = 0;
+
+       virtual int quantity () const {
+               return 1;
+       }
 };
 
 #endif
index 732913c068f92cd1d3201ce27d01abd7ebd14eb1..bdd393332d3dd2e831fc8c5b6c96b2f13b798463 100644 (file)
 
 
 using std::string;
+using std::vector;
 using boost::optional;
 using boost::shared_ptr;
 using dcp::Data;
 
 
-optional<Data>
-J2KEncoderCPUBackend::encode (shared_ptr<DCPVideo> video)
+vector<Data>
+J2KEncoderCPUBackend::encode (vector<shared_ptr<DCPVideo> > all_video)
 {
+       DCPOMATIC_ASSERT (all_video.size() == 1);
+       shared_ptr<DCPVideo> video = all_video.front();
+
        try {
                LOG_TIMING ("start-local-encode thread=%1 frame=%2", thread_id(), video->index());
                string const comment = Config::instance()->dcp_j2k_comment();
@@ -46,7 +50,9 @@ J2KEncoderCPUBackend::encode (shared_ptr<DCPVideo> video)
                }
 
                LOG_TIMING ("finish-local-encode thread=%1 frame=%2", thread_id(), video->index());
-               return enc;
+               vector<Data> data;
+               data.push_back (enc);
+               return data;
        } 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());
index 75d7c97a795003ddeab01cdc9d0ad8576a6b8953..9518b5349dd698e9d33a96771ac1d42900435ab2 100644 (file)
@@ -8,7 +8,7 @@
 class J2KEncoderCPUBackend : public J2KEncoderBackend
 {
 public:
-       boost::optional<dcp::Data> encode (boost::shared_ptr<DCPVideo> video);
+       std::vector<dcp::Data> encode (std::vector<boost::shared_ptr<DCPVideo> > video);
 };
 
 #endif
index 8311347180b7a4dbec88ef4f693ee08d741b6446..40d9a187109604341e381fdfdd56dc5fb9d9d4be 100644 (file)
@@ -18,6 +18,7 @@ DCPOMATIC_ENABLE_WARNINGS
 
 
 using std::string;
+using std::vector;
 using boost::optional;
 using boost::shared_ptr;
 using dcp::Data;
@@ -32,9 +33,12 @@ J2KEncoderRemoteBackend::J2KEncoderRemoteBackend (EncodeServerDescription server
 }
 
 
-optional<Data>
-J2KEncoderRemoteBackend::encode (shared_ptr<DCPVideo> video)
+vector<Data>
+J2KEncoderRemoteBackend::encode (vector<shared_ptr<DCPVideo> > all_video)
 {
+       DCPOMATIC_ASSERT (all_video.size() == 1);
+       shared_ptr<DCPVideo> video = all_video.front();
+
        int const timeout = 30;
 
        try {
@@ -90,7 +94,9 @@ J2KEncoderRemoteBackend::encode (shared_ptr<DCPVideo> video)
                /* This job succeeded, so remove any backoff */
                _backoff = 0;
 
-               return e;
+               vector<Data> data;
+               data.push_back(e);
+               return data;
 
        } catch (std::exception& e) {
                if (_backoff < 60) {
@@ -102,7 +108,7 @@ J2KEncoderRemoteBackend::encode (shared_ptr<DCPVideo> video)
                        );
 
                boost::this_thread::sleep (boost::posix_time::seconds(_backoff));
-               return optional<Data>();
+               return vector<Data>();
        }
 }
 
index 5e62cd9a9a42ff934f0ffe3b7dfb7e69c4fcf2b4..b17ac04078b7c3a80b842e27373179105e0ef5c7 100644 (file)
@@ -6,7 +6,7 @@ class J2KEncoderRemoteBackend : public J2KEncoderBackend
 {
 public:
        J2KEncoderRemoteBackend (EncodeServerDescription server);
-       boost::optional<dcp::Data> encode (boost::shared_ptr<DCPVideo> video);
+       std::vector<dcp::Data> encode (std::vector<boost::shared_ptr<DCPVideo> > video);
 
 private:
        EncodeServerDescription _server;
index 3c2f3f0948b85f5c9b10422ddb3d5fb76c22bc24..e88b653467a25c59585ee4e049f9eb5e37098546 100644 (file)
@@ -117,7 +117,7 @@ PlayerVideo::image (function<AVPixelFormat (AVPixelFormat)> pixel_format, bool a
 
        boost::mutex::scoped_lock lm (_mutex);
        if (!_image || _crop != _image_crop || _inter_size != _image_inter_size || _out_size != _image_out_size || _fade != _image_fade) {
-               timestamped_printf("_________________!!! make_image() for %d [%d]\n", time.frames_round(24), !_image);
+               //timestamped_printf("_________________!!! make_image() for %d [%d]\n", time.frames_round(24), !_image);
                make_image (pixel_format, aligned, fast);
        }
        return _image;
index 59cc145a25918aa172eda92a03837c133a8c4625..64ddc07623ce7cecb38a760adc627c36b1443028 100644 (file)
@@ -127,6 +127,7 @@ sources = """
           j2k_image_proxy.cc
           j2k_encoder.cc
           j2k_encoder_cpu_backend.cc
+          j2k_encoder_fastvideo_backend.cc
           j2k_encoder_remote_backend.cc
           job.cc
           job_manager.cc
index 4f8d0b4d14048fa411ae17abfb5a8ed7cb46672e..931b27082c9f8216e31a08c6f6241a726a75b79a 100644 (file)
@@ -42,6 +42,7 @@ using std::cout;
 using std::cerr;
 using std::string;
 using std::pair;
+using std::vector;
 using boost::shared_ptr;
 using boost::optional;
 using boost::bind;
@@ -58,7 +59,11 @@ void
 process_video (shared_ptr<PlayerVideo> pvf)
 {
        shared_ptr<DCPVideo> local  (new DCPVideo (pvf, frame_count, film->video_frame_rate(), 250000000, RESOLUTION_2K));
+       vector<shared_ptr<DCPVideo> > locals;
+       locals.push_back (local);
        shared_ptr<DCPVideo> remote (new DCPVideo (pvf, frame_count, film->video_frame_rate(), 250000000, RESOLUTION_2K));
+       vector<shared_ptr<DCPVideo> > remotes;
+       remotes.push_back (remote);
 
        cout << "Frame " << frame_count << ": ";
        cout.flush ();
@@ -66,13 +71,13 @@ process_video (shared_ptr<PlayerVideo> pvf)
        ++frame_count;
 
        J2KEncoderCPUBackend cpu_backend;
-       Data local_encoded = *cpu_backend.encode (local);
+       Data local_encoded = cpu_backend.encode(locals).front();
        Data remote_encoded;
 
        string remote_error;
        try {
                J2KEncoderRemoteBackend remote_backend(*server);
-               remote_encoded = *remote_backend.encode (remote);
+               remote_encoded = remote_backend.encode(remotes).front();
        } catch (NetworkError& e) {
                remote_error = e.what ();
        }
index c0c853fc11891f139a6c453f8116e90a46396b8a..6f49f68b5ef6e9da75089334112b2925d7725a07 100644 (file)
@@ -44,6 +44,7 @@
 #include <boost/thread.hpp>
 
 using std::list;
+using std::vector;
 using boost::shared_ptr;
 using boost::thread;
 using boost::optional;
@@ -56,7 +57,9 @@ void
 do_remote_encode (shared_ptr<DCPVideo> frame, shared_ptr<J2KEncoderBackend> backend, Data locally_encoded)
 {
        Data remotely_encoded;
-       BOOST_REQUIRE_NO_THROW (remotely_encoded = *backend->encode(frame));
+       vector<shared_ptr<DCPVideo> > frames;
+       frames.push_back (frame);
+       BOOST_REQUIRE_NO_THROW (remotely_encoded = backend->encode(frames).front());
 
        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);
@@ -122,8 +125,11 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb)
                        )
                );
 
+       vector<shared_ptr<DCPVideo> > frames;
+       frames.push_back (frame);
+
        J2KEncoderCPUBackend cpu;
-       Data locally_encoded = *cpu.encode(frame);
+       Data locally_encoded = cpu.encode(frames).front();
 
        EncodeServer* server = new EncodeServer (true, 2);
 
@@ -210,8 +216,11 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv)
                        )
                );
 
+       vector<shared_ptr<DCPVideo> > frames;
+       frames.push_back (frame);
+
        J2KEncoderCPUBackend cpu;
-       Data locally_encoded = *cpu.encode(frame);
+       Data locally_encoded = cpu.encode(frames).front();
 
        EncodeServer* server = new EncodeServer (true, 2);
 
@@ -283,8 +292,11 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
                        )
                );
 
+       vector<shared_ptr<DCPVideo> > raw_frames;
+       raw_frames.push_back (raw_frame);
+
        J2KEncoderCPUBackend cpu;
-       Data raw_locally_encoded = *cpu.encode(raw_frame);
+       Data raw_locally_encoded = cpu.encode(raw_frames).front();
 
        shared_ptr<PlayerVideo> j2k_pvf (
                new PlayerVideo (
@@ -313,7 +325,10 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
                        )
                );
 
-       Data j2k_locally_encoded = *cpu.encode(j2k_frame);
+       vector<shared_ptr<DCPVideo> > j2k_frames;
+       j2k_frames.push_back (j2k_frame);
+
+       Data j2k_locally_encoded = cpu.encode(j2k_frames).front();
 
        EncodeServer* server = new EncodeServer (true, 2);
 
diff --git a/wscript b/wscript
index 010fe8791193599b4a38911849411eb668cec7bd..523052ee460772c6937d6a262f8f2bfe13f93968 100644 (file)
--- a/wscript
+++ b/wscript
@@ -571,7 +571,7 @@ def configure(conf):
     if conf.options.fastvideo_sdk is not None:
         conf.env.INCLUDES_FASTVIDEO = [os.path.join(conf.options.fastvideo_sdk, "fastvideo_sdk", "inc") ]
         conf.env.LIBPATH_FASTVIDEO = [ os.path.join(conf.options.fastvideo_sdk, "fastvideo_sdk", "lib") ]
-        conf.env.LIB_FASTVIDEO = [ 'fastvideo_decoder_j2k', 'fastvideo_sdk', 'cuda', 'cudart' ]
+        conf.env.LIB_FASTVIDEO = [ 'fastvideo_decoder_j2k', 'fastvideo_encoder_j2k', 'fastvideo_sdk', 'cuda', 'cudart', 'omp5' ]
 
 
     # Other stuff