diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-04-13 21:09:37 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-04-13 21:09:37 +0200 |
| commit | d16267be986c0994f05fc6a3889b83ba53a230b0 (patch) | |
| tree | 8f416cd12b06f2a334023c891bb78bd0996bb518 /src | |
| parent | c325ab5f745c67e6381bcee582bf809018d809e0 (diff) | |
Don't bind a shared_ptr<PlayerVideo> to ImageChanged (#3013).
Otherwise if the GUI is busy when the emissions build up, each one holds
a reference to a potentially large image.
This caused enormous memory use when playing a DCP and verifying it at
the same time.
Diffstat (limited to 'src')
| -rw-r--r-- | src/tools/dcpomatic.cc | 6 | ||||
| -rw-r--r-- | src/wx/content_menu.cc | 2 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 10 | ||||
| -rw-r--r-- | src/wx/film_viewer.h | 10 | ||||
| -rw-r--r-- | src/wx/video_waveform_plot.cc | 7 | ||||
| -rw-r--r-- | src/wx/video_waveform_plot.h | 4 |
6 files changed, 32 insertions, 7 deletions
diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 78fce27f2..8677acc18 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -408,6 +408,12 @@ public: add_accelerators (); } + ~DOMFrame() + { + /* This holds a reference to FilmViewer, so get rid of it first */ + _video_waveform_dialog.reset(); + } + void add_accelerators () { #ifdef __WXOSX__ diff --git a/src/wx/content_menu.cc b/src/wx/content_menu.cc index 62421a20b..559b57553 100644 --- a/src/wx/content_menu.cc +++ b/src/wx/content_menu.cc @@ -586,7 +586,7 @@ ContentMenu::auto_crop () }); /* Also update the dialog and view when we're looking at a different frame */ - _auto_crop_viewer_connection = _viewer.ImageChanged.connect([this, guess_crop_for_content, update_viewer](shared_ptr<PlayerVideo>) { + _auto_crop_viewer_connection = _viewer.ImageChanged.connect([this, guess_crop_for_content, update_viewer]() { auto const crop = guess_crop_for_content(); _auto_crop_dialog->set(crop); update_viewer(crop); diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 957407338..0efa75380 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -864,7 +864,15 @@ FilmViewer::gets () const void FilmViewer::image_changed (shared_ptr<PlayerVideo> pv) { - emit (boost::bind(boost::ref(ImageChanged), pv)); + _last_image = pv; + emit(boost::bind(boost::ref(ImageChanged))); +} + + +shared_ptr<const PlayerVideo> +FilmViewer::last_image() const +{ + return _last_image; } diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 8f0cad545..c8aade6c0 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -155,7 +155,10 @@ public: Frame average_latency() const; - boost::signals2::signal<void (std::shared_ptr<PlayerVideo>)> ImageChanged; + /** The image we are viewing changed: call last_image() to get the image */ + boost::signals2::signal<void ()> ImageChanged; + std::shared_ptr<const PlayerVideo> last_image() const; + boost::signals2::signal<void ()> Started; boost::signals2::signal<void ()> Stopped; /** While playing back we reached the end of the film (emitted from GUI thread) */ @@ -222,5 +225,10 @@ private: boost::optional<dcpomatic::Rect<float>> _crop_guess; + /** Keep track of the image that we were talking about with the last + * emission of ImageChanged. + */ + std::shared_ptr<const PlayerVideo> _last_image; + boost::signals2::scoped_connection _config_changed_connection; }; diff --git a/src/wx/video_waveform_plot.cc b/src/wx/video_waveform_plot.cc index ebff68096..2827689a7 100644 --- a/src/wx/video_waveform_plot.cc +++ b/src/wx/video_waveform_plot.cc @@ -56,12 +56,13 @@ int const VideoWaveformPlot::_x_axis_width = 52; VideoWaveformPlot::VideoWaveformPlot(wxWindow* parent, weak_ptr<const Film> film, FilmViewer& viewer) : wxPanel (parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE) , _film (film) + , _viewer(viewer) { #ifndef __WXOSX__ SetDoubleBuffered (true); #endif - _viewer_connection = viewer.ImageChanged.connect(boost::bind(&VideoWaveformPlot::set_image, this, _1)); + _viewer_connection = _viewer.ImageChanged.connect(boost::bind(&VideoWaveformPlot::set_image, this)); Bind (wxEVT_PAINT, boost::bind(&VideoWaveformPlot::paint, this)); Bind (wxEVT_SIZE, boost::bind(&VideoWaveformPlot::sized, this, _1)); @@ -186,7 +187,7 @@ VideoWaveformPlot::create_waveform () void -VideoWaveformPlot::set_image (shared_ptr<PlayerVideo> image) +VideoWaveformPlot::set_image() { if (!_enabled) { return; @@ -195,7 +196,7 @@ VideoWaveformPlot::set_image (shared_ptr<PlayerVideo> image) /* We must copy the PlayerVideo here as we will call ::image() on it, potentially with a different pixel_format than was used when ::prepare() was called. */ - _image = DCPVideo::convert_to_xyz(image->shallow_copy()); + _image = DCPVideo::convert_to_xyz(_viewer.last_image()->shallow_copy()); _dirty = true; Refresh (); } diff --git a/src/wx/video_waveform_plot.h b/src/wx/video_waveform_plot.h index f482da8f8..e6e7a6f3d 100644 --- a/src/wx/video_waveform_plot.h +++ b/src/wx/video_waveform_plot.h @@ -56,7 +56,7 @@ private: void paint (); void sized (wxSizeEvent &); void create_waveform (); - void set_image (std::shared_ptr<PlayerVideo>); + void set_image(); void mouse_moved (wxMouseEvent &); std::weak_ptr<const Film> _film; @@ -67,6 +67,8 @@ private: int _component = 0; int _contrast = 0; + FilmViewer& _viewer; + static int const _vertical_margin; static int const _pixel_values; static int const _x_axis_width; |
