From: Carl Hetherington Date: Sun, 20 Oct 2019 22:55:52 +0000 (+0200) Subject: Barely-functioning GL playback with new arrangement. X-Git-Tag: v2.15.40^2~36 X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=5eb8b5c3a1566aef638e9d9df03b88d320735092;hp=ca3393a75c1685d1615ff678b58bd3b75fe79cd2 Barely-functioning GL playback with new arrangement. --- diff --git a/src/lib/cross.cc b/src/lib/cross.cc index 8d82f7a51..5d35d5a4b 100644 --- a/src/lib/cross.cc +++ b/src/lib/cross.cc @@ -75,6 +75,17 @@ dcpomatic_sleep_seconds (int s) #endif } +void +dcpomatic_sleep_milliseconds (int ms) +{ +#ifdef DCPOMATIC_POSIX + usleep (ms * 1000); +#endif +#ifdef DCPOMATIC_WINDOWS + Sleep (ms); +#endif +} + /** @return A string of CPU information (model name etc.) */ string cpu_info () diff --git a/src/lib/cross.h b/src/lib/cross.h index 67709463a..584fa2b42 100644 --- a/src/lib/cross.h +++ b/src/lib/cross.h @@ -39,6 +39,7 @@ class Log; struct AVIOContext; void dcpomatic_sleep_seconds (int); +void dcpomatic_sleep_milliseconds (int); extern std::string cpu_info (); extern void run_ffprobe (boost::filesystem::path, boost::filesystem::path); extern std::list > mount_info (); diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 68bf20732..47851a218 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -92,6 +92,9 @@ #include #include #include +#ifdef __WXGTK__ +#include +#endif #ifdef __WXMSW__ #include #endif @@ -1503,7 +1506,11 @@ public: : wxApp () , _frame (0) , _splash (0) - {} + { +#ifdef DCPOMATIC_LINUX + XInitThreads (); +#endif + } private: diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc index f68d0ead2..6bd5b36ff 100644 --- a/src/tools/dcpomatic_player.cc +++ b/src/tools/dcpomatic_player.cc @@ -66,6 +66,9 @@ #include #include #include +#ifdef __WXGTK__ +#include +#endif #ifdef __WXOSX__ #include #endif @@ -1044,7 +1047,11 @@ public: App () : wxApp () , _frame (0) - {} + { +#ifdef DCPOMATIC_LINUX + XInitThreads (); +#endif + } private: diff --git a/src/tools/wscript b/src/tools/wscript index 8fd23cfb3..3b2c0a04c 100644 --- a/src/tools/wscript +++ b/src/tools/wscript @@ -68,6 +68,8 @@ def build(bld): obj.uselib += ' WXWIDGETS' if not bld.env.TARGET_OSX: obj.uselib += ' GL GLU' + if bld.env.TARGET_LINUX: + obj.uselib += ' X11' obj.includes = ['..'] obj.use = ['libdcpomatic2', 'libdcpomatic2-wx'] obj.source = '%s.cc' % t diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 55356f188..a59468c36 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -153,6 +153,8 @@ private: /* XXX_b: to remove */ friend class SimpleVideoView; + friend class GLVideoView; + friend class VideoView; void video_view_sized (); void calculate_sizes (); diff --git a/src/wx/gl_video_view.cc b/src/wx/gl_video_view.cc index a0f83db6d..c69ab210a 100644 --- a/src/wx/gl_video_view.cc +++ b/src/wx/gl_video_view.cc @@ -23,6 +23,8 @@ #include "lib/image.h" #include "lib/dcpomatic_assert.h" #include "lib/exceptions.h" +#include "lib/cross.h" +#include "lib/player_video.h" #include #include @@ -52,9 +54,9 @@ using boost::optional; GLVideoView::GLVideoView (FilmViewer* viewer, wxWindow *parent) : VideoView (viewer) , _vsync_enabled (false) + , _thread (0) { _canvas = new wxGLCanvas (parent, wxID_ANY, 0, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE); - _context = new wxGLContext (_canvas); _canvas->Bind (wxEVT_PAINT, boost::bind(&GLVideoView::paint, this)); _canvas->Bind (wxEVT_SIZE, boost::bind(boost::ref(Sized))); @@ -93,8 +95,13 @@ GLVideoView::GLVideoView (FilmViewer* viewer, wxWindow *parent) GLVideoView::~GLVideoView () { + if (_thread) { + _thread->interrupt (); + _thread->join (); + } + delete _thread; + glDeleteTextures (1, &_id); - delete _context; } static void @@ -109,11 +116,14 @@ static void void GLVideoView::paint () { + /* XXX_b: can't do this yet */ +#if 0 _viewer->state_timer().set("paint-panel"); _canvas->SetCurrent (*_context); wxPaintDC dc (_canvas); draw (); _viewer->state_timer().unset(); +#endif } void @@ -122,8 +132,9 @@ GLVideoView::update () if (!_canvas->IsShownOnScreen()) { return; } - wxClientDC dc (_canvas); - draw (); + /* XXX_b */ +// wxClientDC dc (_canvas); +// draw (); } void @@ -248,3 +259,62 @@ GLVideoView::set_image (shared_ptr image) glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); check_gl_error ("glTexParameterf"); } + +void +GLVideoView::start () +{ + _thread = new boost::thread (boost::bind(&GLVideoView::thread, this)); +} + +void +GLVideoView::thread () +try +{ + /* XXX_b: check all calls and signal emissions in this method & protect them if necessary */ + { + boost::mutex::scoped_lock lm (_context_mutex); + _context = new wxGLContext (_canvas); + _canvas->SetCurrent (*_context); + } + + while (true) { + if (!_viewer->film() || !_viewer->playing()) { + dcpomatic_sleep_milliseconds (40); + continue; + } + + dcpomatic::DCPTime const next = _viewer->position() + _viewer->one_video_frame(); + + if (next >= _viewer->film()->length()) { + _viewer->stop (); + _viewer->Finished (); + return; + } + + 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"; + dcpomatic_sleep_milliseconds (_viewer->time_until_next_frame()); + } + + { + boost::mutex::scoped_lock lm (_context_mutex); + delete _context; + } +} +catch (boost::thread_interrupted& e) +{ + /* XXX_b: store exceptions here */ + delete _context; + return; +} + +wxGLContext * +GLVideoView::context () const +{ + boost::mutex::scoped_lock lm (_context_mutex); + return _context; +} diff --git a/src/wx/gl_video_view.h b/src/wx/gl_video_view.h index ba4c7cfdc..e32a1ede9 100644 --- a/src/wx/gl_video_view.h +++ b/src/wx/gl_video_view.h @@ -23,6 +23,7 @@ #include #include #include +#include #undef None #undef Success @@ -37,18 +38,25 @@ public: return _canvas; } void update (); + void start (); bool vsync_enabled () const { return _vsync_enabled; } private: - void paint (); - void draw (); + void paint (); + void draw (); + void thread (); + wxGLContext* context () const; wxGLCanvas* _canvas; - wxGLContext* _context; - GLuint _id; - boost::optional _size; + + wxGLContext* _context; + mutable boost::mutex _context_mutex; + + GLuint _id; + boost::optional _size; bool _vsync_enabled; + boost::thread* _thread; }; diff --git a/src/wx/simple_video_view.cc b/src/wx/simple_video_view.cc index c195bbc35..1e97adb30 100644 --- a/src/wx/simple_video_view.cc +++ b/src/wx/simple_video_view.cc @@ -159,7 +159,7 @@ 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 (_viewer->time_until_next_frame()), wxTIMER_ONE_SHOT); + _timer.Start (_viewer->time_until_next_frame(), wxTIMER_ONE_SHOT); if (_viewer->butler()) { _viewer->butler()->rethrow (); @@ -180,33 +180,16 @@ SimpleVideoView::start () bool SimpleVideoView::get (bool lazy) { - DCPOMATIC_ASSERT (_viewer->butler()); - _viewer->_gets++; - - do { - Butler::Error e; - _player_video = _viewer->butler()->get_video (!lazy, &e); - if (!_player_video.first && e == Butler::AGAIN) { - 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; - } + 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; } - } while ( - _player_video.first && - _viewer->film()->three_d() && - _viewer->_eyes != _player_video.first->eyes() && - _player_video.first->eyes() != EYES_BOTH - ); - - try { - _viewer->butler()->rethrow (); - } catch (DecodeError& e) { - error_dialog (get(), e.what()); } display_player_video (); diff --git a/src/wx/video_view.cc b/src/wx/video_view.cc index eb85079c3..22cad3979 100644 --- a/src/wx/video_view.cc +++ b/src/wx/video_view.cc @@ -19,6 +19,9 @@ */ #include "video_view.h" +#include "wx_util.h" +#include "film_viewer.h" +#include "lib/butler.h" void VideoView::clear () @@ -26,3 +29,34 @@ VideoView::clear () _player_video.first.reset (); _player_video.second = dcpomatic::DCPTime (); } + +/** @param non_blocking true to return false quickly if no video is available quickly. + * @return false if we gave up because it would take too long, otherwise true. + */ +bool +VideoView::get_next_frame (bool non_blocking) +{ + DCPOMATIC_ASSERT (_viewer->butler()); + _viewer->_gets++; + + do { + Butler::Error e; + _player_video = _viewer->butler()->get_video (!non_blocking, &e); + if (!_player_video.first && e == Butler::AGAIN) { + return false; + } + } while ( + _player_video.first && + _viewer->film()->three_d() && + _viewer->_eyes != _player_video.first->eyes() && + _player_video.first->eyes() != EYES_BOTH + ); + + try { + _viewer->butler()->rethrow (); + } catch (DecodeError& e) { + error_dialog (get(), e.what()); + } + + return true; +} diff --git a/src/wx/video_view.h b/src/wx/video_view.h index f4a8ea22b..827d1bf73 100644 --- a/src/wx/video_view.h +++ b/src/wx/video_view.h @@ -64,6 +64,8 @@ protected: /* XXX_b: to remove */ friend class FilmViewer; + bool get_next_frame (bool non_blocking); + FilmViewer* _viewer; std::pair, dcpomatic::DCPTime> _player_video; diff --git a/wscript b/wscript index 9f45778e9..fe1431316 100644 --- a/wscript +++ b/wscript @@ -444,6 +444,9 @@ def configure(conf): conf.env['CXXFLAGS_AVCODEC'] = [] conf.env['CXXFLAGS_AVUTIL'] = [] + if conf.env.TARGET_LINUX: + conf.env.LIB_X11 = ['X11'] + # Boost if conf.options.static_boost: conf.env.STLIB_BOOST_THREAD = ['boost_thread']