X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Fwx%2Fsimple_video_view.cc;h=1e97adb30478eafb9e5b4a39195d41dcb2a8e23d;hp=56e50ebed24ed20ccb014f2f8aa4c5eeecfeefcd;hb=5eb8b5c3a1566aef638e9d9df03b88d320735092;hpb=64ff02a143c8364c49554d9631fb6be5f273b54d diff --git a/src/wx/simple_video_view.cc b/src/wx/simple_video_view.cc index 56e50ebed..1e97adb30 100644 --- a/src/wx/simple_video_view.cc +++ b/src/wx/simple_video_view.cc @@ -21,6 +21,7 @@ #include "simple_video_view.h" #include "film_viewer.h" #include "wx_util.h" +#include "closed_captions_dialog.h" #include "lib/image.h" #include "lib/dcpomatic_log.h" #include "lib/butler.h" @@ -31,6 +32,7 @@ using std::max; using std::string; using boost::optional; +using boost::shared_ptr; using namespace dcpomatic; SimpleVideoView::SimpleVideoView (FilmViewer* viewer, wxWindow* parent) @@ -83,10 +85,10 @@ SimpleVideoView::paint () #ifdef DCPOMATIC_VARIANT_SWAROOP DCPTime const period = DCPTime::from_seconds(Config::instance()->player_watermark_period() * 60); - int64_t n = _viewer->video_position().get() / period.get(); + int64_t n = _viewer->position().get() / period.get(); DCPTime from(n * period.get()); DCPTime to = from + DCPTime::from_seconds(Config::instance()->player_watermark_duration() / 1000.0); - if (from <= _viewer->video_position() && _viewer->video_position() <= to) { + if (from <= _viewer->position() && _viewer->position() <= to) { if (!_in_watermark) { _in_watermark = true; _watermark_x = rand() % panel_size.GetWidth(); @@ -147,7 +149,7 @@ SimpleVideoView::timer () return; } - _viewer->get (false); + get (false); DCPTime const next = _viewer->position() + _viewer->one_video_frame(); if (next >= _viewer->film()->length()) { @@ -157,9 +159,96 @@ SimpleVideoView::timer () } LOG_DEBUG_PLAYER("%1 -> %2; delay %3", next.seconds(), _viewer->time().seconds(), max((next.seconds() - _viewer->time().seconds()) * 1000, 1.0)); - _timer.Start (max ((next.seconds() - _viewer->time().seconds()) * 1000, 1.0), wxTIMER_ONE_SHOT); + _timer.Start (_viewer->time_until_next_frame(), wxTIMER_ONE_SHOT); - if (_viewer->_butler) { - _viewer->_butler->rethrow (); + if (_viewer->butler()) { + _viewer->butler()->rethrow (); } } + +void +SimpleVideoView::start () +{ + timer (); +} + +/** Try to get a frame from the butler and display it. + * @param lazy true to return false quickly if no video is available quickly (i.e. we are waiting for the butler). + * false to ask the butler to block until it has video (unless it is suspended). + * @return true on success, false if we did nothing because it would have taken too long. + */ +bool +SimpleVideoView::get (bool lazy) +{ + bool r = get_next_frame (lazy); + if (!r) { + if (lazy) { + /* No video available; return saying we failed */ + return false; + } else { + /* Player was suspended; come back later */ + signal_manager->when_idle (boost::bind(&SimpleVideoView::get, this, false)); + return false; + } + } + + display_player_video (); + _viewer->PositionChanged (); + + return true; +} + +void +SimpleVideoView::display_player_video () +{ + if (!_player_video.first) { + set_image (shared_ptr()); + _viewer->refresh_view (); + return; + } + + if (_viewer->playing() && (_viewer->time() - _player_video.second) > _viewer->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). + */ + _viewer->_video_position = _player_video.second; + ++_viewer->_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. + * 2. convert back to RGB for the preview display, compensating + * for the monitor etc. etc. + * + * but this is inefficient if the source is RGB. Since we don't + * (currently) care too much about the precise accuracy of the preview's + * colour mapping (and we care more about its speed) we try to short- + * circuit this "ideal" situation in some cases. + * + * The content's specified colour conversion indicates the colourspace + * which the content is in (according to the user). + * + * PlayerVideo::image (bound to PlayerVideo::force) will take the source + * image and convert it (from whatever the user has said it is) to RGB. + */ + + _viewer->_state_timer.set ("get image"); + + set_image ( + _player_video.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), false, true) + ); + + _viewer->_state_timer.set ("ImageChanged"); + _viewer->ImageChanged (_player_video.first); + _viewer->_state_timer.unset (); + + _viewer->_video_position = _player_video.second; + _viewer->_inter_position = _player_video.first->inter_position (); + _viewer->_inter_size = _player_video.first->inter_size (); + + _viewer->refresh_view (); + + _viewer->_closed_captions_dialog->update (_viewer->time()); +}