/** Ask for ::get() to be called next time we are idle */
void
-FilmViewer::request_idle_get ()
+FilmViewer::request_idle_display_next_frame ()
{
if (_idle_get) {
return;
return;
}
- if (_video_view->get(true)) {
+ if (_video_view->display_next_frame(true)) {
_idle_get = false;
} else {
/* get() could not complete quickly so we'll try again later */
}
_film = film;
- _video_position = DCPTime ();
_video_view->clear ();
_video_view->set_image (shared_ptr<Image>());
--_suspended;
if (_playing && !_suspended) {
if (_audio.isStreamOpen()) {
- _audio.setStreamTime (_video_position.seconds());
+ _audio.setStreamTime (_video_view->position().seconds());
_audio.startStream ();
}
_video_view->start ();
}
if (_audio.isStreamOpen()) {
- _audio.setStreamTime (_video_position.seconds());
+ _audio.setStreamTime (_video_view->position().seconds());
_audio.startStream ();
}
void
FilmViewer::slow_refresh ()
{
- seek (_video_position, true);
+ seek (_video_view->position(), true);
}
/** Try to re-get the current frame quickly by resetting the metadata
_butler->seek (t, accurate);
if (!_playing) {
- request_idle_get ();
+ request_idle_display_next_frame ();
+ } else {
+ while (!_video_view->display_next_frame(false)) {}
}
resume ();
return DCPTime::from_seconds (const_cast<RtAudio*>(&_audio)->getStreamTime());
}
- return _video_position;
+ return _video_view->position();
}
DCPTime
DCPTime::from_frames (average_latency(), _film->audio_frame_rate());
}
- return _video_position;
+ return _video_view->position();
}
int
void
FilmViewer::seek_by (DCPTime by, bool accurate)
{
- seek (_video_position + by, accurate);
+ seek (_video_view->position() + by, accurate);
}
void
FilmViewer::time_until_next_frame () const
{
DCPTime const next = position() + one_video_frame();
- return max ((next.seconds() - time().seconds()) * 1000, 1.0);
+ std::cout << to_string(next) << " " << to_string(time()) << " " << ((next.seconds() - time().seconds()) * 1000) << "\n";
+ if (next < time()) {
+ return 0;
+ }
+ return (next.seconds() - time().seconds()) * 1000;
}
void seek_by (dcpomatic::DCPTime by, bool accurate);
/** @return our `playhead' position; this may not lie exactly on a frame boundary */
dcpomatic::DCPTime position () const {
- return _video_position;
+ return _video_view->position();
}
dcpomatic::DCPTime one_video_frame () const;
void calculate_sizes ();
void player_change (ChangeType type, int, bool);
void idle_handler ();
- void request_idle_get ();
+ void request_idle_display_next_frame ();
void film_change (ChangeType, Film::Property);
void recreate_butler ();
void config_changed (Config::Property);
bool _coalesce_player_changes;
std::list<int> _pending_player_changes;
- dcpomatic::DCPTime _video_position;
Position<int> _inter_position;
dcp::Size _inter_size;
: VideoView (viewer)
, _vsync_enabled (false)
, _thread (0)
+ , _one_shot (false)
{
_canvas = new wxGLCanvas (parent, wxID_ANY, 0, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE);
_canvas->Bind (wxEVT_PAINT, boost::bind(&GLVideoView::paint, this));
}
static void
- check_gl_error (char const * last)
+check_gl_error (char const * last)
{
GLenum const e = glGetError ();
if (e != GL_NO_ERROR) {
}
while (true) {
- if (!_viewer->film() || !_viewer->playing()) {
+ if ((!_viewer->film() || !_viewer->playing()) && !_one_shot) {
dcpomatic_sleep_milliseconds (40);
continue;
}
+ _one_shot = false;
+
dcpomatic::DCPTime const next = _viewer->position() + _viewer->one_video_frame();
if (next >= _viewer->film()->length()) {
_viewer->stop ();
_viewer->Finished ();
- return;
+ continue;
}
get_next_frame (false);
set_image (_player_video.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), false, true));
draw ();
- _viewer->_video_position = _player_video.second;
- std::cout << "sleep " << _viewer->time_until_next_frame() << "\n";
+ while (_viewer->time_until_next_frame() < 5) {
+ get_next_frame (true);
+ }
+
dcpomatic_sleep_milliseconds (_viewer->time_until_next_frame());
}
boost::mutex::scoped_lock lm (_context_mutex);
return _context;
}
+
+bool
+GLVideoView::display_next_frame (bool non_blocking)
+{
+ bool const g = get_next_frame (non_blocking);
+ _one_shot = true;
+ return g;
+}
void update ();
void start ();
+ bool display_next_frame (bool);
+
bool vsync_enabled () const {
return _vsync_enabled;
}
boost::optional<dcp::Size> _size;
bool _vsync_enabled;
boost::thread* _thread;
+ bool _one_shot;
};
return;
}
- get (false);
+ display_next_frame (false);
DCPTime const next = _viewer->position() + _viewer->one_video_frame();
if (next >= _viewer->film()->length()) {
}
/** 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).
+ * @param non_blocking 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)
+SimpleVideoView::display_next_frame (bool non_blocking)
{
- bool r = get_next_frame (lazy);
+ bool r = get_next_frame (non_blocking);
if (!r) {
- if (lazy) {
+ if (non_blocking) {
/* 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));
+ signal_manager->when_idle (boost::bind(&SimpleVideoView::display_next_frame, this, false));
return false;
}
}
/* 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;
}
_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 ();
}
void update ();
-
void start ();
+ bool display_next_frame (bool non_blocking);
private:
void paint ();
void timer ();
- /* XXX_b: rename this (there's already a get() in the parent) */
- bool get (bool lazy);
void display_player_video ();
wxPanel* _panel;
boost::signals2::signal<void()> Sized;
- /* XXX_b: to remove */
- virtual bool get (bool) {
- return true;
- }
+ virtual bool display_next_frame (bool) = 0;
+
/* XXX_b: to remove */
virtual void display_player_video () {}
+ dcpomatic::DCPTime position () const {
+ return _player_video.second;
+ }
+
protected:
/* XXX_b: to remove */
friend class FilmViewer;