/*
- Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
-#include "video_waveform_plot.h"
+
#include "film_viewer.h"
+#include "video_waveform_plot.h"
#include "wx_util.h"
-#include "lib/image.h"
#include "lib/dcp_video.h"
+#include "lib/film.h"
+#include "lib/image.h"
+#include "lib/player_video.h"
#include <dcp/locale_convert.h>
#include <dcp/openjpeg_image.h>
#include <wx/rawbmp.h>
#include <wx/graphics.h>
-#include <boost/bind.hpp>
+#include <boost/bind/bind.hpp>
#include <iostream>
+
using std::cout;
-using std::min;
+using std::make_shared;
using std::max;
+using std::min;
+using std::shared_ptr;
using std::string;
-using boost::weak_ptr;
-using boost::shared_ptr;
+using std::weak_ptr;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
using dcp::locale_convert;
+
int const VideoWaveformPlot::_vertical_margin = 8;
int const VideoWaveformPlot::_pixel_values = 4096;
int const VideoWaveformPlot::_x_axis_width = 52;
-VideoWaveformPlot::VideoWaveformPlot (wxWindow* parent, weak_ptr<const Film> film, FilmViewer* viewer)
+
+VideoWaveformPlot::VideoWaveformPlot (wxWindow* parent, weak_ptr<const Film> film, weak_ptr<FilmViewer> viewer)
: wxPanel (parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
, _film (film)
- , _dirty (true)
- , _enabled (false)
- , _component (0)
- , _contrast (0)
{
#ifndef __WXOSX__
SetDoubleBuffered (true);
#endif
- _viewer_connection = viewer->ImageChanged.connect (boost::bind (&VideoWaveformPlot::set_image, this, _1));
+ auto fv = viewer.lock ();
+ DCPOMATIC_ASSERT (fv);
- Bind (wxEVT_PAINT, boost::bind (&VideoWaveformPlot::paint, this));
- Bind (wxEVT_SIZE, boost::bind (&VideoWaveformPlot::sized, this, _1));
- Bind (wxEVT_MOTION, boost::bind (&VideoWaveformPlot::mouse_moved, this, _1));
+ _viewer_connection = fv->ImageChanged.connect (boost::bind(&VideoWaveformPlot::set_image, this, _1));
+
+ Bind (wxEVT_PAINT, boost::bind(&VideoWaveformPlot::paint, this));
+ Bind (wxEVT_SIZE, boost::bind(&VideoWaveformPlot::sized, this, _1));
+ Bind (wxEVT_MOTION, boost::bind(&VideoWaveformPlot::mouse_moved, this, _1));
SetMinSize (wxSize (640, 512));
SetBackgroundColour (wxColour (0, 0, 0));
}
+
void
VideoWaveformPlot::paint ()
{
return;
}
- wxGraphicsContext* gc = wxGraphicsContext::Create (dc);
+ auto gc = wxGraphicsContext::Create (dc);
if (!gc) {
return;
}
}
for (int i = 0; i < label_gaps + 1; ++i) {
- wxGraphicsPath p = gc->CreatePath ();
+ auto p = gc->CreatePath ();
int const y = _vertical_margin + height - (i * height / label_gaps) - 1;
p.MoveToPoint (label_width + 8, y);
p.AddLineToPoint (_x_axis_width - 4, y);
} else if (n < 1000) {
x += extra[2];
}
- gc->DrawText (std_to_wx (locale_convert<string> (n)), x, y - (label_height / 2));
+ gc->DrawText (std_to_wx(locale_convert<string>(n)), x, y - (label_height / 2));
}
wxImage waveform (_waveform->size().width, height, _waveform->data()[0], true);
delete gc;
}
+
void
VideoWaveformPlot::create_waveform ()
{
return;
}
- dcp::Size const image_size = _image->size();
+ auto const image_size = _image->size();
int const waveform_height = GetSize().GetHeight() - _vertical_margin * 2;
- _waveform.reset (new Image (AV_PIX_FMT_RGB24, dcp::Size (image_size.width, waveform_height), true));
+ _waveform = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size (image_size.width, waveform_height), Image::Alignment::PADDED);
for (int x = 0; x < image_size.width; ++x) {
_waveform = _waveform->scale (
dcp::Size (GetSize().GetWidth() - _x_axis_width, waveform_height),
- dcp::YUV_TO_RGB_REC709, AV_PIX_FMT_RGB24, false, false
+ dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::COMPACT, false
);
}
-static void
-note ()
-{
-
-}
void
-VideoWaveformPlot::set_image (weak_ptr<PlayerVideo> image)
+VideoWaveformPlot::set_image (shared_ptr<PlayerVideo> image)
{
if (!_enabled) {
return;
}
- shared_ptr<PlayerVideo> pv = image.lock ();
- _image = DCPVideo::convert_to_xyz (pv, boost::bind (¬e));
+ /* 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(), [](dcp::NoteType, string) {});
_dirty = true;
Refresh ();
}
+
void
VideoWaveformPlot::sized (wxSizeEvent &)
{
_dirty = true;
}
+
void
VideoWaveformPlot::set_enabled (bool e)
{
_enabled = e;
}
+
void
VideoWaveformPlot::set_component (int c)
{
Refresh ();
}
+
/** Set `contrast', i.e. a fudge multiplication factor to make low-level signals easier to see,
* between 0 and 256.
*/
Refresh ();
}
+
void
VideoWaveformPlot::mouse_moved (wxMouseEvent& ev)
{
_dirty = false;
}
- shared_ptr<const Film> film = _film.lock ();
+ auto film = _film.lock ();
if (!film) {
return;
}
- dcp::Size const full = film->frame_size ();
+ auto const full = film->frame_size ();
- double const xs = static_cast<double> (full.width) / _waveform->size().width;
+ auto const xs = static_cast<double> (full.width) / _waveform->size().width;
int const x1 = max (0, min (full.width - 1, int (floor (ev.GetPosition().x - _x_axis_width - 0.5) * xs)));
int const x2 = max (0, min (full.width - 1, int (floor (ev.GetPosition().x - _x_axis_width + 0.5) * xs)));
- double const ys = static_cast<double> (_pixel_values) / _waveform->size().height;
+ auto const ys = static_cast<double> (_pixel_values) / _waveform->size().height;
int const fy = _waveform->size().height - (ev.GetPosition().y - _vertical_margin);
int const y1 = max (0, min (_pixel_values - 1, int (floor (fy - 0.5) * ys)));
int const y2 = max (0, min (_pixel_values - 1, int (floor (fy + 0.5) * ys)));