diff options
| author | Carl Hetherington <cth@carlh.net> | 2020-08-14 13:44:58 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2020-09-13 20:23:29 +0200 |
| commit | d89f53b1ad09cf0f739533483915b702a26594b4 (patch) | |
| tree | 133813acde125aa371b0a30f75af2812e6459aa9 | |
| parent | 50e85cf64504b7fc38b4129aa750c2def28b95fd (diff) | |
wip: encoding; crashes on startup.
| -rw-r--r-- | src/lib/encode_server.cc | 4 | ||||
| -rw-r--r-- | src/lib/event_history.cc | 18 | ||||
| -rw-r--r-- | src/lib/event_history.h | 6 | ||||
| -rw-r--r-- | src/lib/j2k_encoder.cc | 50 | ||||
| -rw-r--r-- | src/lib/j2k_encoder.h | 2 | ||||
| -rw-r--r-- | src/lib/j2k_encoder_backend.h | 7 | ||||
| -rw-r--r-- | src/lib/j2k_encoder_cpu_backend.cc | 12 | ||||
| -rw-r--r-- | src/lib/j2k_encoder_cpu_backend.h | 2 | ||||
| -rw-r--r-- | src/lib/j2k_encoder_remote_backend.cc | 14 | ||||
| -rw-r--r-- | src/lib/j2k_encoder_remote_backend.h | 2 | ||||
| -rw-r--r-- | src/lib/player_video.cc | 2 | ||||
| -rw-r--r-- | src/lib/wscript | 1 | ||||
| -rw-r--r-- | src/tools/server_test.cc | 9 | ||||
| -rw-r--r-- | test/client_server_test.cc | 25 | ||||
| -rw-r--r-- | wscript | 2 |
15 files changed, 112 insertions, 44 deletions
diff --git a/src/lib/encode_server.cc b/src/lib/encode_server.cc index 85f3ca7b0..acb40c1b2 100644 --- a/src/lib/encode_server.cc +++ b/src/lib/encode_server.cc @@ -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); diff --git a/src/lib/event_history.cc b/src/lib/event_history.cc index efe80b243..75ef3319e 100644 --- a/src/lib/event_history.cc +++ b/src/lib/event_history.cc @@ -22,8 +22,13 @@ #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 (); } } diff --git a/src/lib/event_history.h b/src/lib/event_history.h index 4670e7bfe..51684ea16 100644 --- a/src/lib/event_history.h +++ b/src/lib/event_history.h @@ -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; }; diff --git a/src/lib/j2k_encoder.cc b/src/lib/j2k_encoder.cc index ef38aaa55..8c915b567 100644 --- a/src/lib/j2k_encoder.cc +++ b/src/lib/j2k_encoder.cc @@ -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()); } diff --git a/src/lib/j2k_encoder.h b/src/lib/j2k_encoder.h index df23a5bae..cc782d96d 100644 --- a/src/lib/j2k_encoder.h +++ b/src/lib/j2k_encoder.h @@ -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 (); diff --git a/src/lib/j2k_encoder_backend.h b/src/lib/j2k_encoder_backend.h index 7688e5f15..a19beda53 100644 --- a/src/lib/j2k_encoder_backend.h +++ b/src/lib/j2k_encoder_backend.h @@ -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 diff --git a/src/lib/j2k_encoder_cpu_backend.cc b/src/lib/j2k_encoder_cpu_backend.cc index 732913c06..bdd393332 100644 --- a/src/lib/j2k_encoder_cpu_backend.cc +++ b/src/lib/j2k_encoder_cpu_backend.cc @@ -10,14 +10,18 @@ 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()); diff --git a/src/lib/j2k_encoder_cpu_backend.h b/src/lib/j2k_encoder_cpu_backend.h index 75d7c97a7..9518b5349 100644 --- a/src/lib/j2k_encoder_cpu_backend.h +++ b/src/lib/j2k_encoder_cpu_backend.h @@ -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 diff --git a/src/lib/j2k_encoder_remote_backend.cc b/src/lib/j2k_encoder_remote_backend.cc index 831134718..40d9a1871 100644 --- a/src/lib/j2k_encoder_remote_backend.cc +++ b/src/lib/j2k_encoder_remote_backend.cc @@ -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>(); } } diff --git a/src/lib/j2k_encoder_remote_backend.h b/src/lib/j2k_encoder_remote_backend.h index 5e62cd9a9..b17ac0407 100644 --- a/src/lib/j2k_encoder_remote_backend.h +++ b/src/lib/j2k_encoder_remote_backend.h @@ -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; diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc index 3c2f3f094..e88b65346 100644 --- a/src/lib/player_video.cc +++ b/src/lib/player_video.cc @@ -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; diff --git a/src/lib/wscript b/src/lib/wscript index 59cc145a2..64ddc0762 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -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 diff --git a/src/tools/server_test.cc b/src/tools/server_test.cc index 4f8d0b4d1..931b27082 100644 --- a/src/tools/server_test.cc +++ b/src/tools/server_test.cc @@ -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 (); } diff --git a/test/client_server_test.cc b/test/client_server_test.cc index c0c853fc1..6f49f68b5 100644 --- a/test/client_server_test.cc +++ b/test/client_server_test.cc @@ -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); @@ -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 |
