Basic stress-test function for player.
authorCarl Hetherington <cth@carlh.net>
Sat, 23 Nov 2019 09:44:39 +0000 (10:44 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 8 Jan 2020 20:56:47 +0000 (21:56 +0100)
hacks/stress.py [new file with mode: 0644]
src/tools/dcpomatic_player.cc
src/wx/controls.cc
src/wx/controls.h
src/wx/standard_controls.cc
src/wx/standard_controls.h
wscript

diff --git a/hacks/stress.py b/hacks/stress.py
new file mode 100644 (file)
index 0000000..46d0638
--- /dev/null
@@ -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)
+
+
index 6bd5b36..328093d 100644 (file)
@@ -73,6 +73,7 @@
 #include <ApplicationServices/ApplicationServices.h>
 #endif
 #include <boost/bind.hpp>
+#include <boost/algorithm/string.hpp>
 #include <iostream>
 
 #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<string> 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<int>(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<int>(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<string> 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<int>();
+                                               ++_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<Command> _commands;
+       list<Command>::const_iterator _current_command;
+       optional<int> _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<string> _stress;
+#endif
 };
 
 IMPLEMENT_APP (App)
index 0c12ba4..27139f1 100644 (file)
@@ -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
index 0144644..1b6a379 100644 (file)
@@ -53,6 +53,11 @@ public:
 
        virtual void log (wxString) {}
        virtual void set_film (boost::shared_ptr<Film> film);
+#ifdef DCPOMATIC_PLAYER_STRESS_TEST
+       virtual void play () {};
+       virtual void stop () {};
+       void seek (int slider);
+#endif
        boost::shared_ptr<Film> film () const;
        void back_frame ();
        void forward_frame ();
index 956f82c..e9a31c8 100644 (file)
@@ -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
index b485c48..f79e4a1 100644 (file)
@@ -25,6 +25,11 @@ class StandardControls : public Controls
 public:
        StandardControls (wxWindow* parent, boost::shared_ptr<FilmViewer> 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 fe14313..c61b867 100644 (file)
--- 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')