X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fwx%2Fvideo_view.cc;h=c271cb65e83e213edb54f566c5b4098b351b968f;hb=da13c2af9e8f19229061ca1939cbe8bd37c72eba;hp=3e21e709dd2b5fc1749540ed9c4087d5aeddb20c;hpb=8fedaaa75c4586a4cc7ffb393bd71d1fdb091dc8;p=dcpomatic.git diff --git a/src/wx/video_view.cc b/src/wx/video_view.cc index 3e21e709d..c271cb65e 100644 --- a/src/wx/video_view.cc +++ b/src/wx/video_view.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2019 Carl Hetherington + Copyright (C) 2019-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,30 +18,32 @@ */ + #include "video_view.h" #include "wx_util.h" #include "film_viewer.h" #include "lib/butler.h" #include "lib/dcpomatic_log.h" #include +#include + -using std::pair; using std::shared_ptr; using boost::optional; + +static constexpr int TOO_MANY_DROPPED_FRAMES = 20; +static constexpr int TOO_MANY_DROPPED_PERIOD = 5.0; + + VideoView::VideoView (FilmViewer* viewer) : _viewer (viewer) , _state_timer ("viewer") - , _video_frame_rate (0) - , _eyes (Eyes::LEFT) - , _three_d (false) - , _dropped (0) - , _errored (0) - , _gets (0) { } + void VideoView::clear () { @@ -50,6 +52,7 @@ VideoView::clear () _player_video.second = dcpomatic::DCPTime (); } + /** Could be called from any thread. * @param non_blocking true to return false quickly if no video is available quickly. * @return FAIL if there's no frame, AGAIN if the method should be called again, or SUCCESS @@ -62,7 +65,7 @@ VideoView::get_next_frame (bool non_blocking) return FAIL; } - shared_ptr butler = _viewer->butler (); + auto butler = _viewer->butler (); if (!butler) { return FAIL; } @@ -72,12 +75,12 @@ VideoView::get_next_frame (bool non_blocking) do { Butler::Error e; - pair, dcpomatic::DCPTime> pv = butler->get_video (!non_blocking, &e); - if (e.code == Butler::Error::DIED) { + auto pv = butler->get_video (non_blocking ? Butler::Behaviour::NON_BLOCKING : Butler::Behaviour::BLOCKING, &e); + if (e.code == Butler::Error::Code::DIED) { LOG_ERROR ("Butler died with %1", e.summary()); } if (!pv.first) { - return e.code == Butler::Error::AGAIN ? AGAIN : FAIL; + return e.code == Butler::Error::Code::AGAIN ? AGAIN : FAIL; } _player_video = pv; } while ( @@ -94,19 +97,21 @@ VideoView::get_next_frame (bool non_blocking) return SUCCESS; } + dcpomatic::DCPTime VideoView::one_video_frame () const { return dcpomatic::DCPTime::from_frames (1, video_frame_rate()); } + /** @return Time in ms until the next frame is due, or empty if nothing is due */ optional VideoView::time_until_next_frame () const { if (length() == dcpomatic::DCPTime()) { /* There's no content, so this doesn't matter */ - return optional(); + return {}; } auto const next = position() + one_video_frame(); @@ -117,14 +122,17 @@ VideoView::time_until_next_frame () const return (next.seconds() - time.seconds()) * 1000; } + void VideoView::start () { boost::mutex::scoped_lock lm (_mutex); _dropped = 0; _errored = 0; + gettimeofday(&_dropped_check_period_start, nullptr); } + bool VideoView::reset_metadata (shared_ptr film, dcp::Size player_video_container_size) { @@ -141,3 +149,39 @@ VideoView::reset_metadata (shared_ptr film, dcp::Size player_video_c return true; } + +void +VideoView::add_dropped () +{ + bool too_many = false; + + { + boost::mutex::scoped_lock lm (_mutex); + ++_dropped; + if (_dropped > TOO_MANY_DROPPED_FRAMES) { + struct timeval now; + gettimeofday (&now, nullptr); + double const elapsed = seconds(now) - seconds(_dropped_check_period_start); + too_many = elapsed < TOO_MANY_DROPPED_PERIOD; + _dropped = 0; + _dropped_check_period_start = now; + } + } + + if (too_many) { + emit (boost::bind(boost::ref(TooManyDropped))); + } +} + + +wxColour +VideoView::pad_colour () const +{ + if (_viewer->pad_black()) { + return wxColour(0, 0, 0); + } else if (gui_is_dark()) { + return wxColour(50, 50, 50); + } else { + return wxColour(240, 240, 240); + } +}