From 1d796edf59da644e91bd443505fb76e0397a1439 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 23 Nov 2019 10:44:39 +0100 Subject: [PATCH] Basic stress-test function for player. --- hacks/stress.py | 22 +++++ src/tools/dcpomatic_player.cc | 151 +++++++++++++++++++++++++++++++++- src/wx/controls.cc | 10 +++ src/wx/controls.h | 5 ++ src/wx/standard_controls.cc | 16 ++++ src/wx/standard_controls.h | 5 ++ wscript | 4 + 7 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 hacks/stress.py diff --git a/hacks/stress.py b/hacks/stress.py new file mode 100644 index 000000000..46d06382b --- /dev/null +++ b/hacks/stress.py @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import random + +def make(dcp, output, seeks): + with open(output, 'w') as f: + # Open the DCP and start it playing + print("O %s" % dcp, file=f) + print("P", file=f) + for i in range(seeks): + # Wait a bit + print("W %d" % random.randint(500, 60000), file=f) + # Seek + print("K %d" % random.randint(0, 4095), file=f) + # Make sure we're still playing + print("P", file=f) + print("S", file=f) + + +make("/home/carl/DCP/Examples/BohemianRhapsody_TLR-7_S_DE-XX_DE_51_2K_TCFG_20180514_TM_IOP_OV/", "boho", 64) + + diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc index 6bd5b36ff..328093d8a 100644 --- a/src/tools/dcpomatic_player.cc +++ b/src/tools/dcpomatic_player.cc @@ -73,6 +73,7 @@ #include #endif #include +#include #include #ifdef check @@ -93,8 +94,61 @@ using boost::optional; using boost::dynamic_pointer_cast; using boost::thread; using boost::bind; +using dcp::raw_convert; using namespace dcpomatic; +#ifdef DCPOMATIC_PLAYER_STRESS_TEST +#define STRESS_TEST_CHECK_INTERVAL 20 + +class Command +{ +public: + enum Type { + NONE, + OPEN, + PLAY, + WAIT, + STOP, + SEEK, + }; + + Command(string line) + : type (NONE) + , int_param (0) + { + vector bits; + boost::split (bits, line, boost::is_any_of(" ")); + if (bits[0] == "O") { + if (bits.size() != 2) { + return; + } + type = OPEN; + string_param = bits[1]; + } else if (bits[0] == "P") { + type = PLAY; + } else if (bits[0] == "W") { + if (bits.size() != 2) { + return; + } + type = WAIT; + int_param = raw_convert(bits[1]); + } else if (bits[0] == "S") { + type = STOP; + } else if (bits[0] == "K") { + if (bits.size() != 2) { + return; + } + type = SEEK; + int_param = raw_convert(bits[1]); + } + } + + Type type; + string string_param; + int int_param; +}; +#endif + enum { ID_file_open = 1, ID_file_add_ov, @@ -139,7 +193,10 @@ public: , _system_information_dialog (0) , _view_full_screen (0) , _view_dual_screen (0) - { +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + , _timer (this) +#endif +{ dcpomatic_log.reset (new NullLog()); #if defined(DCPOMATIC_WINDOWS) @@ -236,6 +293,70 @@ public: #endif } +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + void stress (boost::filesystem::path script_file) + { + Bind (wxEVT_TIMER, boost::bind(&DOMFrame::check_commands, this)); + _timer.Start(STRESS_TEST_CHECK_INTERVAL); + vector lines; + string const script = dcp::file_to_string(script_file); + boost::split (lines, script, boost::is_any_of("\n")); + BOOST_FOREACH (string i, lines) { + _commands.push_back (Command(i)); + } + _current_command = _commands.begin(); + } + + void check_commands () + { + if (_current_command == _commands.end()) { + _timer.Stop (); + cout << "ST: finished.\n"; + return; + } + + switch (_current_command->type) { + case Command::OPEN: + cout << "ST: load " << _current_command->string_param << "\n"; + load_dcp (_current_command->string_param); + ++_current_command; + break; + case Command::PLAY: + cout << "ST: play\n"; + _controls->play (); + ++_current_command; + break; + case Command::WAIT: + if (_wait_remaining) { + _wait_remaining = *_wait_remaining - STRESS_TEST_CHECK_INTERVAL; + if (_wait_remaining < 0) { + cout << "ST: wait done.\n"; + _wait_remaining = optional(); + ++_current_command; + } + } else { + _wait_remaining = _current_command->int_param; + cout << "ST: waiting for " << *_wait_remaining << ".\n"; + } + break; + case Command::STOP: + cout << "ST: stop\n"; + _controls->stop (); + ++_current_command; + break; + case Command::NONE: + ++_current_command; + break; + case Command::SEEK: + /* int_param here is a number between 0 and 4095, corresponding to the possible slider positions */ + cout << "ST: seek to " << _current_command->int_param << "\n"; + _controls->seek (_current_command->int_param); + ++_current_command; + break; + } + } +#endif + #ifdef DCPOMATIC_VARIANT_SWAROOP void monitor_checker_state_changed () { @@ -1004,11 +1125,20 @@ private: wxMenuItem* _tools_verify; wxMenuItem* _view_full_screen; wxMenuItem* _view_dual_screen; +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + wxTimer _timer; + list _commands; + list::const_iterator _current_command; + optional _wait_remaining; +#endif }; static const wxCmdLineEntryDesc command_line_description[] = { { wxCMD_LINE_PARAM, 0, 0, "DCP to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_OPTION, "c", "config", "Directory containing config.xml", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + { wxCMD_LINE_OPTION, "s", "stress", "File containing description of stress test", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, +#endif { wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 } }; @@ -1124,6 +1254,16 @@ private: } } +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + if (_stress) { + try { + _frame->stress (_stress.get()); + } catch (exception& e) { + error_dialog (0, wxString::Format("Could not load stress test file %s", std_to_wx(*_stress))); + } + } +#endif + Bind (wxEVT_IDLE, boost::bind (&App::idle, this)); if (Config::instance()->check_for_updates ()) { @@ -1157,6 +1297,12 @@ private: if (parser.Found("c", &config)) { Config::override_path = wx_to_std (config); } +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + wxString stress; + if (parser.Found("s", &stress)) { + _stress = wx_to_std (stress); + } +#endif return true; } @@ -1217,6 +1363,9 @@ private: DOMFrame* _frame; string _dcp_to_load; +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + boost::optional _stress; +#endif }; IMPLEMENT_APP (App) diff --git a/src/wx/controls.cc b/src/wx/controls.cc index 0c12ba463..27139f1f5 100644 --- a/src/wx/controls.cc +++ b/src/wx/controls.cc @@ -406,3 +406,13 @@ Controls::film_change (ChangeType type, Film::Property p) } } } + +#ifdef DCPOMATIC_PLAYER_STRESS_TEST +void +Controls::seek (int slider) +{ + _slider->SetValue (slider); + slider_moved (false); + slider_released (); +} +#endif diff --git a/src/wx/controls.h b/src/wx/controls.h index 014464456..1b6a379cc 100644 --- a/src/wx/controls.h +++ b/src/wx/controls.h @@ -53,6 +53,11 @@ public: virtual void log (wxString) {} virtual void set_film (boost::shared_ptr film); +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + virtual void play () {}; + virtual void stop () {}; + void seek (int slider); +#endif boost::shared_ptr film () const; void back_frame (); void forward_frame (); diff --git a/src/wx/standard_controls.cc b/src/wx/standard_controls.cc index 956f82c96..e9a31c86b 100644 --- a/src/wx/standard_controls.cc +++ b/src/wx/standard_controls.cc @@ -74,3 +74,19 @@ StandardControls::setup_sensitivity () bool const active_job = _active_job && *_active_job != "examine_content"; _play_button->Enable (_film && !_film->content().empty() && !active_job); } + +#ifdef DCPOMATIC_PLAYER_STRESS_TEST +void +StandardControls::play () +{ + _play_button->SetValue (true); + play_clicked (); +} + +void +StandardControls::stop () +{ + _play_button->SetValue (false); + play_clicked (); +} +#endif diff --git a/src/wx/standard_controls.h b/src/wx/standard_controls.h index b485c48cc..f79e4a178 100644 --- a/src/wx/standard_controls.h +++ b/src/wx/standard_controls.h @@ -25,6 +25,11 @@ class StandardControls : public Controls public: StandardControls (wxWindow* parent, boost::shared_ptr viewer, bool editor_controls); +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + void play (); + void stop (); +#endif + private: void check_play_state (); void play_clicked (); diff --git a/wscript b/wscript index fe1431316..c61b86782 100644 --- a/wscript +++ b/wscript @@ -73,6 +73,7 @@ def options(opt): opt.add_option('--workaround-gssapi', action='store_true', default=False, help='link to gssapi_krb5') opt.add_option('--force-cpp11', action='store_true', default=False, help='force use of C++11') opt.add_option('--variant', help='build variant (swaroop-studio, swaroop-theater)', choices=['swaroop-studio', 'swaroop-theater']) + opt.add_option('--enable-player-stress-test', action='store_true', default=False, help='build the player with stress testing enabled') opt.add_option('--use-lld', action='store_true', default=False, help='use lld linker') def configure(conf): @@ -133,6 +134,9 @@ def configure(conf): if conf.options.variant.startswith('swaroop-'): conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_VARIANT_SWAROOP') + if conf.options.enable_player_stress_test: + conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_PLAYER_STRESS_TEST') + if conf.options.use_lld: try: conf.find_program('ld.lld') -- 2.30.2