X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fwx%2Fgl_video_view.cc;h=a87249fafdd73d637bfc4649e36ea8137e32a0c3;hb=6eba051dcbb8c56e3e2efea946ce0380d17a7b33;hp=ddae9bb3c4861b0406550cd9ad542ec1c0881b3d;hpb=706f73390eb37f16b220177650ea7e70c2462150;p=dcpomatic.git diff --git a/src/wx/gl_video_view.cc b/src/wx/gl_video_view.cc index ddae9bb3c..a87249faf 100644 --- a/src/wx/gl_video_view.cc +++ b/src/wx/gl_video_view.cc @@ -55,8 +55,8 @@ using boost::optional; GLVideoView::GLVideoView (FilmViewer* viewer, wxWindow *parent) : VideoView (viewer) + , _have_storage (false) , _vsync_enabled (false) - , _thread (0) , _playing (false) , _one_shot (false) { @@ -104,9 +104,12 @@ GLVideoView::GLVideoView (FilmViewer* viewer, wxWindow *parent) GLVideoView::~GLVideoView () { - _thread->interrupt (); - _thread->join (); - delete _thread; + try { + _thread.interrupt (); + _thread.join (); + } catch (...) { + + } glDeleteTextures (1, &_id); } @@ -114,6 +117,10 @@ GLVideoView::~GLVideoView () void GLVideoView::check_for_butler_errors () { + if (!_viewer->butler()) { + return; + } + try { _viewer->butler()->rethrow (); } catch (DecodeError& e) { @@ -173,7 +180,9 @@ GLVideoView::draw (Position inter_position, dcp::Size inter_size) glMatrixMode (GL_PROJECTION); glLoadIdentity (); +DCPOMATIC_DISABLE_WARNINGS gluOrtho2D (0, canvas_size.GetWidth(), canvas_size.GetHeight(), 0); +DCPOMATIC_ENABLE_WARNINGS check_gl_error ("gluOrtho2d"); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); @@ -264,11 +273,21 @@ GLVideoView::set_image (shared_ptr image) DCPOMATIC_ASSERT (image->pixel_format() == AV_PIX_FMT_RGB24); DCPOMATIC_ASSERT (!image->aligned()); + if (image->size() != _size) { + _have_storage = false; + } + _size = image->size (); glPixelStorei (GL_UNPACK_ALIGNMENT, 1); check_gl_error ("glPixelStorei"); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB8, _size->width, _size->height, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data()[0]); - check_gl_error ("glTexImage2D"); + if (_have_storage) { + glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, _size->width, _size->height, GL_RGB, GL_UNSIGNED_BYTE, image->data()[0]); + check_gl_error ("glTexSubImage2D"); + } else { + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB8, _size->width, _size->height, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data()[0]); + _have_storage = true; + check_gl_error ("glTexImage2D"); + } glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -286,7 +305,7 @@ GLVideoView::start () boost::mutex::scoped_lock lm (_playing_mutex); _playing = true; - _playing_condition.notify_all (); + _thread_work_condition.notify_all (); } void @@ -296,6 +315,44 @@ GLVideoView::stop () _playing = false; } + +void +GLVideoView::thread_playing () +{ + if (length() != dcpomatic::DCPTime()) { + dcpomatic::DCPTime const next = position() + one_video_frame(); + + if (next >= length()) { + _viewer->finished (); + return; + } + + get_next_frame (false); + set_image_and_draw (); + } + + while (true) { + optional n = time_until_next_frame(); + if (!n || *n > 5) { + break; + } + get_next_frame (true); + add_dropped (); + } +} + + +void +GLVideoView::set_image_and_draw () +{ + shared_ptr pv = player_video().first; + if (pv) { + set_image (pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), false, true)); + draw (pv->inter_position(), pv->inter_size()); + } +} + + void GLVideoView::thread () try @@ -309,38 +366,19 @@ try while (true) { boost::mutex::scoped_lock lm (_playing_mutex); while (!_playing && !_one_shot) { - _playing_condition.wait (lm); + _thread_work_condition.wait (lm); } - _one_shot = false; lm.unlock (); - Position inter_position; - dcp::Size inter_size; - if (length() != dcpomatic::DCPTime()) { - dcpomatic::DCPTime const next = position() + one_video_frame(); - - if (next >= length()) { - _viewer->finished (); - continue; - } - - get_next_frame (false); - shared_ptr pv = player_video().first; - if (pv) { - set_image (pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), false, true)); - inter_position = pv->inter_position(); - inter_size = pv->inter_size(); - } - } - draw (inter_position, inter_size); - - while (time_until_next_frame() < 5) { - get_next_frame (true); - add_dropped (); + if (_playing) { + thread_playing (); + } else if (_one_shot) { + _one_shot = false; + set_image_and_draw (); } boost::this_thread::interruption_point (); - dcpomatic_sleep_milliseconds (time_until_next_frame()); + dcpomatic_sleep_milliseconds (time_until_next_frame().get_value_or(0)); } /* XXX: leaks _context, but that seems preferable to deleting it here @@ -365,13 +403,13 @@ GLVideoView::request_one_shot () { boost::mutex::scoped_lock lm (_playing_mutex); _one_shot = true; - _playing_condition.notify_all (); + _thread_work_condition.notify_all (); } void GLVideoView::create () { - if (!_thread) { - _thread = new boost::thread (boost::bind(&GLVideoView::thread, this)); + if (!_thread.joinable()) { + _thread = boost::thread (boost::bind(&GLVideoView::thread, this)); } }