summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2016-05-12 00:18:18 +0100
committerCarl Hetherington <cth@carlh.net>2016-05-12 00:18:18 +0100
commit631f905234537d2b0a24e9b3ff40f08a17c0fd8b (patch)
treedc60d31714e5201028d679b41bef6c5658681a02 /src
parent396cddb7c112aedc80a106a785083aea05b8b741 (diff)
Optimise image scaling for the preview.
Diffstat (limited to 'src')
-rw-r--r--src/lib/dcp_video.cc5
-rw-r--r--src/lib/dcp_video.h3
-rw-r--r--src/lib/image.cc18
-rw-r--r--src/lib/image.h8
-rw-r--r--src/lib/player.cc3
-rw-r--r--src/lib/player_video.cc28
-rw-r--r--src/lib/player_video.h5
-rw-r--r--src/wx/film_viewer.cc16
-rw-r--r--src/wx/video_waveform_plot.cc2
9 files changed, 55 insertions, 33 deletions
diff --git a/src/lib/dcp_video.cc b/src/lib/dcp_video.cc
index cd7d5229e..fbe863a8e 100644
--- a/src/lib/dcp_video.cc
+++ b/src/lib/dcp_video.cc
@@ -1,6 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
- Taken from code Copyright (C) 2010-2011 Terrence Meiczinger
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -99,7 +98,7 @@ DCPVideo::convert_to_xyz (shared_ptr<const PlayerVideo> frame, dcp::NoteHandler
{
shared_ptr<dcp::OpenJPEGImage> xyz;
- shared_ptr<Image> image = frame->image (note);
+ shared_ptr<Image> image = frame->image (note, bind (&PlayerVideo::keep_xyz_or_rgb, _1), true, false);
if (frame->colour_conversion()) {
xyz = dcp::rgb_to_xyz (
image->data()[0],
diff --git a/src/lib/dcp_video.h b/src/lib/dcp_video.h
index a61a757bd..3809d2792 100644
--- a/src/lib/dcp_video.h
+++ b/src/lib/dcp_video.h
@@ -1,6 +1,5 @@
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
- Taken from code Copyright (C) 2010-2011 Terrence Meiczinger
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/lib/image.cc b/src/lib/image.cc
index 9ddccb75f..92b850a62 100644
--- a/src/lib/image.cc
+++ b/src/lib/image.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -110,10 +110,13 @@ Image::planes () const
return d->nb_components;
}
-/** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size' */
+/** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
+ * @param fast Try to be fast at the possible expense of quality; at present this means using
+ * fast bilinear rather than bicubic scaling.
+ */
shared_ptr<Image>
Image::crop_scale_window (
- Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned
+ Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast
) const
{
/* Empirical testing suggests that sws_scale() will crash if
@@ -156,7 +159,7 @@ Image::crop_scale_window (
struct SwsContext* scale_context = sws_getContext (
cropped_size.width, cropped_size.height, pixel_format(),
inter_size.width, inter_size.height, out_format,
- SWS_BICUBIC, 0, 0, 0
+ fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
);
if (!scale_context) {
@@ -213,8 +216,11 @@ Image::crop_scale_window (
return out;
}
+/** @param fast Try to be fast at the possible expense of quality; at present this means using
+ * fast bilinear rather than bicubic scaling.
+ */
shared_ptr<Image>
-Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned) const
+Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
{
/* Empirical testing suggests that sws_scale() will crash if
the input image is not aligned.
@@ -226,7 +232,7 @@ Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_fo
struct SwsContext* scale_context = sws_getContext (
size().width, size().height, pixel_format(),
out_size.width, out_size.height, out_format,
- SWS_BICUBIC, 0, 0, 0
+ fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
);
DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
diff --git a/src/lib/image.h b/src/lib/image.h
index 416ee3a8d..b8d48275a 100644
--- a/src/lib/image.h
+++ b/src/lib/image.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -57,8 +57,10 @@ public:
int line_factor (int) const;
dcp::Size sample_size (int) const;
- boost::shared_ptr<Image> scale (dcp::Size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat, bool aligned) const;
- boost::shared_ptr<Image> crop_scale_window (Crop c, dcp::Size, dcp::Size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat, bool aligned) const;
+ boost::shared_ptr<Image> scale (dcp::Size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat, bool aligned, bool fast) const;
+ boost::shared_ptr<Image> crop_scale_window (
+ Crop c, dcp::Size, dcp::Size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat, bool aligned, bool fast)
+ const;
void make_black ();
void make_transparent ();
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 30f36107f..d35c1b76b 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -318,7 +318,8 @@ Player::transform_image_subtitles (list<ImageSubtitle> subs) const
scaled_size,
dcp::YUV_TO_RGB_REC601,
i->image->pixel_format (),
- true
+ true,
+ _fast
),
Position<int> (
lrint (_video_container_size.width * i->rectangle.x),
diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc
index ba4503d8e..3129a1717 100644
--- a/src/lib/player_video.cc
+++ b/src/lib/player_video.cc
@@ -34,6 +34,7 @@ using std::cout;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
using boost::optional;
+using boost::function;
using dcp::Data;
PlayerVideo::PlayerVideo (
@@ -94,8 +95,14 @@ PlayerVideo::set_subtitle (PositionImage image)
_subtitle = image;
}
+/** Create an image for this frame.
+ * @param note Handler for any notes that are made during the process.
+ * @param pixel_format Function which is called to decide what pixel format the output image should be;
+ * it is passed the pixel format of the input image from the ImageProxy, and should return the desired
+ * output pixel format. Two functions always_rgb and keep_xyz_or_rgb are provided for use here.
+ */
shared_ptr<Image>
-PlayerVideo::image (dcp::NoteHandler note) const
+PlayerVideo::image (dcp::NoteHandler note, function<AVPixelFormat (AVPixelFormat)> pixel_format, bool aligned, bool fast) const
{
shared_ptr<Image> im = _in->image (optional<dcp::NoteHandler> (note));
@@ -122,10 +129,9 @@ PlayerVideo::image (dcp::NoteHandler note) const
yuv_to_rgb = _colour_conversion.get().yuv_to_rgb();
}
- /* If the input is XYZ, keep it otherwise convert to RGB */
- AVPixelFormat const p = _in->pixel_format() == AV_PIX_FMT_XYZ12LE ? AV_PIX_FMT_XYZ12LE : AV_PIX_FMT_RGB48LE;
-
- shared_ptr<Image> out = im->crop_scale_window (total_crop, _inter_size, _out_size, yuv_to_rgb, p, true);
+ shared_ptr<Image> out = im->crop_scale_window (
+ total_crop, _inter_size, _out_size, yuv_to_rgb, pixel_format (_in->pixel_format()), aligned, fast
+ );
if (_subtitle) {
out->alpha_blend (_subtitle->image, _subtitle->position);
@@ -230,3 +236,15 @@ PlayerVideo::same (shared_ptr<const PlayerVideo> other) const
return _in->same (other->_in);
}
+
+AVPixelFormat
+PlayerVideo::always_rgb (AVPixelFormat)
+{
+ return AV_PIX_FMT_RGB24;
+}
+
+AVPixelFormat
+PlayerVideo::keep_xyz_or_rgb (AVPixelFormat p)
+{
+ return p == AV_PIX_FMT_XYZ12LE ? AV_PIX_FMT_XYZ12LE : AV_PIX_FMT_RGB48LE;
+}
diff --git a/src/lib/player_video.h b/src/lib/player_video.h
index 01b1c74f5..8bd1c7be3 100644
--- a/src/lib/player_video.h
+++ b/src/lib/player_video.h
@@ -54,7 +54,10 @@ public:
void set_subtitle (PositionImage);
- boost::shared_ptr<Image> image (dcp::NoteHandler note) const;
+ boost::shared_ptr<Image> image (dcp::NoteHandler note, boost::function<AVPixelFormat (AVPixelFormat)> pixel_format, bool aligned, bool fast) const;
+
+ static AVPixelFormat always_rgb (AVPixelFormat);
+ static AVPixelFormat keep_xyz_or_rgb (AVPixelFormat);
void add_metadata (xmlpp::Node* node) const;
void send_binary (boost::shared_ptr<Socket> socket) const;
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index 9564c0fc9..2ae9bc1dd 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -153,6 +153,7 @@ FilmViewer::set_film (shared_ptr<Film> film)
try {
_player.reset (new Player (_film, _film->playlist ()));
+ _player->set_fast ();
} catch (bad_alloc) {
error_dialog (this, _("There is not enough free memory to do that."));
_film.reset ();
@@ -220,19 +221,12 @@ FilmViewer::get (DCPTime p, bool accurate)
pv = all_pv.front ();
}
- /* XXX: this could now give us a 48-bit image, which is a bit wasteful,
- or a XYZ image, which the code below will currently rely on FFmpeg
- to colourspace-convert.
- */
- _frame = pv->image (boost::bind (&Log::dcp_log, _film->log().get(), _1, _2));
- ImageChanged (pv);
+ _frame = pv->image (
+ bind (&Log::dcp_log, _film->log().get(), _1, _2), bind (&PlayerVideo::always_rgb, _1), false, true
+ );
- dcp::YUVToRGB yuv_to_rgb = dcp::YUV_TO_RGB_REC601;
- if (pv->colour_conversion()) {
- yuv_to_rgb = pv->colour_conversion().get().yuv_to_rgb();
- }
+ ImageChanged (pv);
- _frame = _frame->scale (_frame->size(), yuv_to_rgb, AV_PIX_FMT_RGB24, false);
_position = pv->time ();
_inter_position = pv->inter_position ();
_inter_size = pv->inter_size ();
diff --git a/src/wx/video_waveform_plot.cc b/src/wx/video_waveform_plot.cc
index 0dedd9bb1..357b2ca0c 100644
--- a/src/wx/video_waveform_plot.cc
+++ b/src/wx/video_waveform_plot.cc
@@ -166,7 +166,7 @@ VideoWaveformPlot::create_waveform ()
_waveform = _waveform->scale (
dcp::Size (GetSize().GetWidth() - 32, GetSize().GetHeight() - _vertical_margin * 2),
- dcp::YUV_TO_RGB_REC709, AV_PIX_FMT_RGB24, false
+ dcp::YUV_TO_RGB_REC709, AV_PIX_FMT_RGB24, false, true
);
}