Primitive dropped frame count in display.
[dcpomatic.git] / src / wx / film_viewer.cc
index 83a179f26d554298cc75fc73285ec120f3d6c2e0..036646ba5179f78aa62a21c9a39100341c821dc9 100644 (file)
@@ -72,7 +72,7 @@ rtaudio_callback (void* out, void *, unsigned int frames, double, RtAudioStreamS
        return reinterpret_cast<FilmViewer*>(data)->audio_callback (out, frames);
 }
 
-FilmViewer::FilmViewer (wxWindow* p)
+FilmViewer::FilmViewer (wxWindow* p, bool outline_content, bool jump_to_selected)
        : wxPanel (p)
        , _panel (new wxPanel (this))
        , _outline_content (new wxCheckBox (this, wxID_ANY, _("Outline content")))
@@ -93,6 +93,7 @@ FilmViewer::FilmViewer (wxWindow* p)
        , _audio_block_size (1024)
        , _playing (false)
        , _latency_history_count (0)
+       , _dropped (0)
 {
 #ifndef __WXOSX__
        _panel->SetDoubleBuffered (true);
@@ -106,10 +107,14 @@ FilmViewer::FilmViewer (wxWindow* p)
        _v_sizer->Add (_panel, 1, wxEXPAND);
 
        wxBoxSizer* view_options = new wxBoxSizer (wxHORIZONTAL);
-       view_options->Add (_outline_content, 0, wxRIGHT, DCPOMATIC_SIZER_GAP);
+       if (outline_content) {
+               view_options->Add (_outline_content, 0, wxRIGHT, DCPOMATIC_SIZER_GAP);
+       }
        view_options->Add (_left_eye, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP);
        view_options->Add (_right_eye, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP);
-       view_options->Add (_jump_to_selected, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP);
+       if (jump_to_selected) {
+               view_options->Add (_jump_to_selected, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP);
+       }
        _v_sizer->Add (view_options, 0, wxALL, DCPOMATIC_SIZER_GAP);
 
        wxBoxSizer* h_sizer = new wxBoxSizer (wxHORIZONTAL);
@@ -135,9 +140,10 @@ FilmViewer::FilmViewer (wxWindow* p)
        _outline_content->Bind  (wxEVT_CHECKBOX,          boost::bind (&FilmViewer::refresh_panel,   this));
        _left_eye->Bind         (wxEVT_RADIOBUTTON,       boost::bind (&FilmViewer::refresh,         this));
        _right_eye->Bind        (wxEVT_RADIOBUTTON,       boost::bind (&FilmViewer::refresh,         this));
-       _slider->Bind           (wxEVT_SCROLL_THUMBTRACK, boost::bind (&FilmViewer::slider_moved,    this));
-       _slider->Bind           (wxEVT_SCROLL_PAGEUP,     boost::bind (&FilmViewer::slider_moved,    this));
-       _slider->Bind           (wxEVT_SCROLL_PAGEDOWN,   boost::bind (&FilmViewer::slider_moved,    this));
+       _slider->Bind           (wxEVT_SCROLL_THUMBTRACK, boost::bind (&FilmViewer::slider_moved,    this, false));
+       _slider->Bind           (wxEVT_SCROLL_PAGEUP,     boost::bind (&FilmViewer::slider_moved,    this, false));
+       _slider->Bind           (wxEVT_SCROLL_PAGEDOWN,   boost::bind (&FilmViewer::slider_moved,    this, false));
+       _slider->Bind           (wxEVT_SCROLL_CHANGED,    boost::bind (&FilmViewer::slider_moved,    this, true));
        _play_button->Bind      (wxEVT_TOGGLEBUTTON,      boost::bind (&FilmViewer::play_clicked,    this));
        _timer.Bind             (wxEVT_TIMER,             boost::bind (&FilmViewer::timer,           this));
        _back_button->Bind      (wxEVT_LEFT_DOWN,         boost::bind (&FilmViewer::back_clicked,    this, _1));
@@ -238,7 +244,7 @@ FilmViewer::recreate_butler ()
                map.set (2, 1, 1 / sqrt(2)); // C -> R
        }
 
-       _butler.reset (new Butler (_film, _player, map, _audio_channels));
+       _butler.reset (new Butler (_player, _film->log(), map, _audio_channels));
        if (!Config::instance()->preview_sound()) {
                _butler->disable_audio ();
        }
@@ -276,6 +282,15 @@ FilmViewer::get ()
                return;
        }
 
+       if ((time() - video.second) > one_video_frame()) {
+               /* Too late; just drop this frame before we try to get its image (which will be the time-consuming
+                  part if this frame is J2K).
+               */
+               _video_position = video.second;
+               ++_dropped;
+               return;
+       }
+
        /* In an ideal world, what we would do here is:
         *
         * 1. convert to XYZ exactly as we do in the DCP creation path.
@@ -319,7 +334,7 @@ FilmViewer::timer ()
        get ();
        update_position_label ();
        update_position_slider ();
-       DCPTime const next = _video_position + DCPTime::from_frames (1, _film->video_frame_rate ());
+       DCPTime const next = _video_position + one_video_frame();
 
        if (next >= _film->length()) {
                stop ();
@@ -371,19 +386,23 @@ FilmViewer::paint_panel ()
 }
 
 void
-FilmViewer::slider_moved ()
+FilmViewer::slider_moved (bool update_slider)
 {
        if (!_film) {
                return;
        }
 
+
        DCPTime t (_slider->GetValue() * _film->length().get() / 4096);
        /* Ensure that we hit the end of the film at the end of the slider */
        if (t >= _film->length ()) {
-               t = _film->length() - DCPTime::from_frames (1, _film->video_frame_rate ());
+               t = _film->length() - one_video_frame();
        }
        seek (t, false);
        update_position_label ();
+       if (update_slider) {
+               update_position_slider ();
+       }
 }
 
 void
@@ -456,7 +475,8 @@ FilmViewer::start ()
        }
 
        _playing = true;
-       _timer.Start (0, wxTIMER_ONE_SHOT);
+       _dropped = 0;
+       timer ();
 }
 
 bool
@@ -521,7 +541,7 @@ FilmViewer::active_jobs_changed (optional<string> j)
 DCPTime
 FilmViewer::nudge_amount (wxMouseEvent& ev)
 {
-       DCPTime amount = DCPTime::from_frames (1, _film->video_frame_rate ());
+       DCPTime amount = one_video_frame ();
 
        if (ev.ShiftDown() && !ev.ControlDown()) {
                amount = DCPTime::from_seconds (1);
@@ -778,3 +798,15 @@ FilmViewer::average_latency () const
 
         return total / _latency_history.size();
 }
+
+void
+FilmViewer::set_dcp_decode_reduction (optional<int> reduction)
+{
+       _player->set_dcp_decode_reduction (reduction);
+}
+
+DCPTime
+FilmViewer::one_video_frame () const
+{
+       return DCPTime::from_frames (1, _film->video_frame_rate());
+}