From 15a83d720780d58f905d40f8493cdcb86596eaee Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 10 May 2020 01:57:20 +0200 Subject: [PATCH] Change video content scaling so that it either: 1. scales the content up to fit the DCP container, preserving aspect ratio, or 2. stretches the content to a custom aspect ratio, or 3. scales the content to some custom size. --- src/lib/create_cli.cc | 29 +--- src/lib/create_cli.h | 1 - src/lib/film.cc | 10 +- src/lib/hints.cc | 2 +- src/lib/player.cc | 4 +- src/lib/player.h | 4 +- src/lib/player_video.cc | 2 +- src/lib/util.cc | 19 ++- src/lib/util.h | 1 + src/lib/video_content.cc | 118 ++++++++++--- src/lib/video_content.h | 39 ++++- src/lib/video_content_scale.cc | 171 ------------------- src/lib/video_content_scale.h | 81 --------- src/lib/wscript | 1 - src/tools/dcpomatic_cli.cc | 6 +- src/tools/dcpomatic_create.cc | 1 - src/wx/custom_scale_dialog.cc | 142 ++++++++++++++++ src/wx/custom_scale_dialog.h | 51 ++++++ src/wx/video_panel.cc | 132 +++++++++------ src/wx/video_panel.h | 10 +- src/wx/wscript | 3 +- test/4k_test.cc | 2 - test/create_cli_test.cc | 37 ++-- test/data | 2 +- test/empty_test.cc | 6 - test/ffmpeg_audio_test.cc | 2 - test/ffmpeg_dcp_test.cc | 2 - test/isdcf_name_test.cc | 8 +- test/player_test.cc | 4 +- test/recover_test.cc | 6 +- test/repeat_frame_test.cc | 4 +- test/scaling_test.cc | 16 +- test/skip_frame_test.cc | 1 - test/threed_test.cc | 2 - test/video_content_scale_test.cc | 282 ++++++++++++------------------- 35 files changed, 592 insertions(+), 609 deletions(-) delete mode 100644 src/lib/video_content_scale.cc delete mode 100644 src/lib/video_content_scale.h create mode 100644 src/wx/custom_scale_dialog.cc create mode 100644 src/wx/custom_scale_dialog.h diff --git a/src/lib/create_cli.cc b/src/lib/create_cli.cc index 878ee6fdd..b670282b4 100644 --- a/src/lib/create_cli.cc +++ b/src/lib/create_cli.cc @@ -42,7 +42,6 @@ string CreateCLI::_help = " -c, --dcp-content-type FTR, SHR, TLR, TST, XSN, RTG, TSR, POL, PSA or ADV\n" " -f, --dcp-frame-rate set DCP video frame rate (otherwise guessed from content)\n" " --container-ratio 119, 133, 137, 138, 166, 178, 185 or 239\n" - " --content-ratio 119, 133, 137, 138, 166, 178, 185 or 239\n" " -s, --still-length number of seconds that still content should last\n" " --standard SMPTE or interop (default SMPTE)\n" " --no-use-isdcf-name do not use an ISDCF name; use the specified name unmodified\n" @@ -79,7 +78,6 @@ CreateCLI::CreateCLI (int argc, char* argv[]) , threed (false) , dcp_content_type (0) , container_ratio (0) - , content_ratio (0) , still_length (10) , standard (dcp::SMPTE) , no_use_isdcf_name (false) @@ -87,7 +85,6 @@ CreateCLI::CreateCLI (int argc, char* argv[]) , fourk (false) { string dcp_content_type_string = "TST"; - string content_ratio_string; string container_ratio_string; string standard_string = "SMPTE"; int dcp_frame_rate_int = 0; @@ -136,7 +133,6 @@ CreateCLI::CreateCLI (int argc, char* argv[]) argument_option(i, argc, argv, "-c", "--dcp-content-type", &claimed, &error, &dcp_content_type_string); argument_option(i, argc, argv, "-f", "--dcp-frame-rate", &claimed, &error, &dcp_frame_rate_int); argument_option(i, argc, argv, "", "--container-ratio", &claimed, &error, &container_ratio_string); - argument_option(i, argc, argv, "", "--content-ratio", &claimed, &error, &content_ratio_string); argument_option(i, argc, argv, "-s", "--still-length", &claimed, &error, &still_length); argument_option(i, argc, argv, "", "--standard", &claimed, &error, &standard_string); argument_option(i, argc, argv, "", "--config", &claimed, &error, &config_dir_string); @@ -185,25 +181,12 @@ CreateCLI::CreateCLI (int argc, char* argv[]) return; } - if (content_ratio_string.empty()) { - error = String::compose("%1: missing required option --content-ratio", argv[0]); - return; - } - - content_ratio = Ratio::from_id (content_ratio_string); - if (!content_ratio) { - error = String::compose("%1: unrecognised content ratio %2", content_ratio_string); - return; - } - - if (container_ratio_string.empty()) { - container_ratio_string = content_ratio_string; - } - - container_ratio = Ratio::from_id (container_ratio_string); - if (!container_ratio) { - error = String::compose("%1: unrecognised container ratio %2", argv[0], container_ratio_string); - return; + if (!container_ratio_string.empty()) { + container_ratio = Ratio::from_id (container_ratio_string); + if (!container_ratio) { + error = String::compose("%1: unrecognised container ratio %2", argv[0], container_ratio_string); + return; + } } if (standard_string != "SMPTE" && standard_string != "interop") { diff --git a/src/lib/create_cli.h b/src/lib/create_cli.h index a9d9daa22..01e8e6633 100644 --- a/src/lib/create_cli.h +++ b/src/lib/create_cli.h @@ -45,7 +45,6 @@ public: DCPContentType const * dcp_content_type; boost::optional dcp_frame_rate; Ratio const * container_ratio; - Ratio const * content_ratio; int still_length; dcp::Standard standard; bool no_use_isdcf_name; diff --git a/src/lib/film.cc b/src/lib/film.cc index b233e5ee6..b1dcb46d7 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -132,8 +132,10 @@ string const Film::metadata_file = "metadata.xml"; * 36 -> 37 * TextContent can be in a Caption tag, and some of the tag names * have had Subtitle prefixes or suffixes removed. + * 37 -> 38 + * VideoContent scale expressed just as "guess" or "custom" */ -int const Film::current_state_version = 37; +int const Film::current_state_version = 38; /** Construct a Film object in a given directory. * @@ -787,11 +789,7 @@ Film::isdcf_name (bool if_created_now) const BOOST_FOREACH (shared_ptr i, content ()) { if (i->video) { /* Here's the first piece of video content */ - if (i->video->scale().ratio ()) { - content_ratio = i->video->scale().ratio (); - } else { - content_ratio = Ratio::from_ratio (i->video->size().ratio ()); - } + content_ratio = Ratio::nearest_from_ratio(i->video->scaled_size(frame_size()).ratio()); break; } } diff --git a/src/lib/hints.cc b/src/lib/hints.cc index 581d63972..0f18835ef 100644 --- a/src/lib/hints.cc +++ b/src/lib/hints.cc @@ -123,7 +123,7 @@ Hints::thread () int scope = 0; BOOST_FOREACH (shared_ptr i, content) { if (i->video) { - Ratio const * r = i->video->scale().ratio (); + Ratio const * r = Ratio::nearest_from_ratio(i->video->scaled_size(film->frame_size()).ratio()); if (r && r->id() == "239") { ++scope; } else if (r && r->id() != "239" && r->id() != "190") { diff --git a/src/lib/player.cc b/src/lib/player.cc index e41cecf13..059465724 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -864,9 +864,7 @@ Player::video (weak_ptr wp, ContentVideo video) video.image, piece->content->video->crop (), piece->content->video->fade (_film, video.frame), - piece->content->video->scale().size ( - piece->content->video, _video_container_size, _film->frame_size () - ), + scale_for_display(piece->content->video->scaled_size(_film->frame_size()), _video_container_size, _film->frame_size()), _video_container_size, video.eyes, video.part, diff --git a/src/lib/player.h b/src/lib/player.h index 51de78982..bb2a0c613 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -159,7 +159,9 @@ private: boost::atomic _suspended; std::list > _pieces; - /** Size of the image in the DCP (e.g. 1990x1080 for flat) */ + /** Size of the image we are rendering to; this may be the DCP frame size, or + * the size of preview in a window. + */ dcp::Size _video_container_size; boost::shared_ptr _black_image; diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc index cb2a55724..10e798ed5 100644 --- a/src/lib/player_video.cc +++ b/src/lib/player_video.cc @@ -339,7 +339,7 @@ PlayerVideo::reset_metadata (shared_ptr film, dcp::Size video_contai _crop = content->video->crop(); _fade = content->video->fade(film, _video_frame.get()); - _inter_size = content->video->scale().size(content->video, video_container_size, film_frame_size); + _inter_size = scale_for_display(content->video->scaled_size(film_frame_size), video_container_size, film_frame_size); _out_size = video_container_size; _colour_conversion = content->video->colour_conversion(); _video_range = content->video->range(); diff --git a/src/lib/util.cc b/src/lib/util.cc index d04bbdf24..c1ef4245f 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -394,7 +394,6 @@ dcpomatic_setup () Ratio::setup_ratios (); PresetColourConversion::setup_colour_conversion_presets (); - VideoContentScale::setup_scales (); DCPContentType::setup_dcp_content_types (); Filter::setup_filters (); CinemaSoundProcessor::setup_cinema_sound_processors (); @@ -1184,3 +1183,21 @@ linear_to_db (double linear) return 20 * log10(linear); } + +dcp::Size +scale_for_display (dcp::Size s, dcp::Size display_container, dcp::Size film_container) +{ + /* Now scale it down if the display container is smaller than the film container */ + if (display_container != film_container) { + float const scale = min ( + float (display_container.width) / film_container.width, + float (display_container.height) / film_container.height + ); + + s.width = lrintf (s.width * scale); + s.height = lrintf (s.height * scale); + } + + return s; +} + diff --git a/src/lib/util.h b/src/lib/util.h index f8e9409f1..f7b4704ac 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -116,6 +116,7 @@ extern void copy_in_bits (boost::filesystem::path from, boost::filesystem::path extern boost::shared_ptr read_swaroop_chain (boost::filesystem::path path); extern void write_swaroop_chain (boost::shared_ptr chain, boost::filesystem::path output); #endif +extern dcp::Size scale_for_display (dcp::Size s, dcp::Size display_container, dcp::Size film_container); template std::list diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc index 9e8659b98..b4ad30f70 100644 --- a/src/lib/video_content.cc +++ b/src/lib/video_content.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2019 Carl Hetherington + Copyright (C) 2013-2020 Carl Hetherington This file is part of DCP-o-matic. @@ -48,6 +48,8 @@ int const VideoContentProperty::COLOUR_CONVERSION = 5; int const VideoContentProperty::FADE_IN = 6; int const VideoContentProperty::FADE_OUT = 7; int const VideoContentProperty::RANGE = 8; +int const VideoContentProperty::CUSTOM_RATIO = 9; +int const VideoContentProperty::CUSTOM_SIZE = 10; using std::string; using std::setprecision; @@ -70,7 +72,6 @@ VideoContent::VideoContent (Content* parent) , _use (true) , _length (0) , _frame_type (VIDEO_FRAME_TYPE_2D) - , _scale (VideoContentScale (Ratio::from_id ("178"))) , _yuv (true) , _fade_in (0) , _fade_out (0) @@ -139,10 +140,29 @@ VideoContent::VideoContent (Content* parent, cxml::ConstNodePtr node, int versio if (version <= 7) { optional r = node->optional_string_child ("Ratio"); if (r) { - _scale = VideoContentScale (Ratio::from_id (r.get ())); + _legacy_ratio = Ratio::from_id(r.get())->ratio(); } + } else if (version <= 37) { + optional ratio = node->node_child("Scale")->optional_string_child("Ratio"); + if (ratio) { + _legacy_ratio = Ratio::from_id(ratio.get())->ratio(); + } + optional scale = node->node_child("Scale")->optional_bool_child("Scale"); + if (scale) { + if (*scale) { + /* This is what we used to call "no stretch" */ + _legacy_ratio = _size.ratio(); + } else { + /* This is what we used to call "no scale" */ + _custom_size = _size; + } + } + } else { - _scale = VideoContentScale (node->node_child ("Scale")); + _custom_ratio = node->optional_number_child("CustomRatio"); + if (node->optional_number_child("CustomWidth")) { + _custom_size = dcp::Size (node->number_child("CustomWidth"), node->number_child("CustomHeight")); + } } if (node->optional_node_child ("ColourConversion")) { @@ -190,8 +210,12 @@ VideoContent::VideoContent (Content* parent, vector > c) throw JoinError (_("Content to be joined must have the same crop.")); } - if (c[i]->video->scale() != ref->scale()) { - throw JoinError (_("Content to be joined must have the same scale setting.")); + if (c[i]->video->custom_ratio() != ref->custom_ratio()) { + throw JoinError (_("Content to be joined must have the same custom ratio setting.")); + } + + if (c[i]->video->custom_size() != ref->custom_size()) { + throw JoinError (_("Content to be joined must have the same custom size setting.")); } if (c[i]->video->colour_conversion() != ref->colour_conversion()) { @@ -213,7 +237,7 @@ VideoContent::VideoContent (Content* parent, vector > c) _size = ref->size (); _frame_type = ref->frame_type (); _crop = ref->crop (); - _scale = ref->scale (); + _custom_ratio = ref->custom_ratio (); _colour_conversion = ref->colour_conversion (); _fade_in = ref->fade_in (); _fade_out = ref->fade_out (); @@ -233,7 +257,13 @@ VideoContent::as_xml (xmlpp::Node* node) const node->add_child("SampleAspectRatio")->add_child_text (raw_convert (_sample_aspect_ratio.get ())); } _crop.as_xml (node); - _scale.as_xml (node->add_child("Scale")); + if (_custom_ratio) { + node->add_child("CustomRatio")->add_child_text(raw_convert(*_custom_ratio)); + } + if (_custom_size) { + node->add_child("CustomWidth")->add_child_text(raw_convert(_custom_size->width)); + node->add_child("CustomHeight")->add_child_text(raw_convert(_custom_size->height)); + } if (_colour_conversion) { _colour_conversion.get().as_xml (node->add_child("ColourConversion")); } @@ -265,15 +295,6 @@ VideoContent::take_from_examiner (shared_ptr d) _sample_aspect_ratio = ar; _yuv = yuv; _range = range; - - if (Config::instance()->default_scale_to ()) { - _scale = VideoContentScale (Config::instance()->default_scale_to ()); - } else { - /* Guess correct scale from size and sample aspect ratio */ - _scale = VideoContentScale ( - Ratio::nearest_from_ratio (double (_size.width) * ar.get_value_or (1) / _size.height) - ); - } } LOG_GENERAL ("Video length obtained from header as %1 frames", _length); @@ -289,13 +310,15 @@ VideoContent::identifier () const { char buffer[256]; snprintf ( - buffer, sizeof(buffer), "%d_%d_%d_%d_%d_%s_%" PRId64 "_%" PRId64 "_%d", + buffer, sizeof(buffer), "%d_%d_%d_%d_%d_%f_%d_%d%" PRId64 "_%" PRId64 "_%d", (_use ? 1 : 0), crop().left, crop().right, crop().top, crop().bottom, - scale().id().c_str(), + _custom_ratio.get_value_or(0), + _custom_size ? _custom_size->width : 0, + _custom_size ? _custom_size->height : 0, _fade_in, _fade_out, _range == VIDEO_RANGE_FULL ? 0 : 1 @@ -379,7 +402,7 @@ VideoContent::fade (shared_ptr film, Frame f) const } string -VideoContent::processing_description (shared_ptr film) const +VideoContent::processing_description (shared_ptr film) { string d; char buffer[256]; @@ -416,7 +439,7 @@ VideoContent::processing_description (shared_ptr film) const } dcp::Size const container_size = film->frame_size (); - dcp::Size const scaled = scale().size (shared_from_this(), container_size, container_size); + dcp::Size const scaled = scaled_size (container_size); if (scaled != size_after_crop ()) { d += String::compose ( @@ -489,11 +512,6 @@ VideoContent::set_bottom_crop (int c) maybe_set (_crop.bottom, c, VideoContentProperty::CROP); } -void -VideoContent::set_scale (VideoContentScale s) -{ - maybe_set (_scale, s, VideoContentProperty::SCALE); -} void VideoContent::set_frame_type (VideoFrameType t) @@ -551,7 +569,8 @@ VideoContent::take_settings_from (shared_ptr c) set_right_crop (c->_crop.right); set_top_crop (c->_crop.top); set_bottom_crop (c->_crop.bottom); - set_scale (c->_scale); + set_custom_ratio (c->_custom_ratio); + set_custom_size (c->_custom_size); set_fade_in (c->_fade_in); set_fade_out (c->_fade_out); } @@ -569,3 +588,48 @@ VideoContent::modify_trim_start (ContentTime& trim) const trim = trim.round (_parent->video_frame_rate().get()); } } + + +/** @param film_container The size of the container for the DCP that we are working on */ +dcp::Size +VideoContent::scaled_size (dcp::Size film_container) +{ + if (_custom_ratio) { + return fit_ratio_within(*_custom_ratio, film_container); + } + + if (_custom_size) { + return *_custom_size; + } + + dcp::Size size = size_after_crop (); + size.width *= _sample_aspect_ratio.get_value_or(1); + + /* This is what we will return unless there is any legacy stuff to take into account */ + dcp::Size auto_size = fit_ratio_within (size.ratio(), film_container); + + if (_legacy_ratio) { + if (fit_ratio_within(*_legacy_ratio, film_container) != auto_size) { + _custom_ratio = *_legacy_ratio; + _legacy_ratio = optional(); + return fit_ratio_within(*_custom_ratio, film_container); + } + _legacy_ratio = 0; + } + + return auto_size; +} + + +void +VideoContent::set_custom_ratio (optional ratio) +{ + maybe_set (_custom_ratio, ratio, VideoContentProperty::CUSTOM_RATIO); +} + + +void +VideoContent::set_custom_size (optional size) +{ + maybe_set (_custom_size, size, VideoContentProperty::CUSTOM_SIZE); +} diff --git a/src/lib/video_content.h b/src/lib/video_content.h index 9a7ad6dda..b478666bb 100644 --- a/src/lib/video_content.h +++ b/src/lib/video_content.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2019 Carl Hetherington + Copyright (C) 2013-2020 Carl Hetherington This file is part of DCP-o-matic. @@ -22,7 +22,6 @@ #define DCPOMATIC_VIDEO_CONTENT_H #include "colour_conversion.h" -#include "video_content_scale.h" #include "dcpomatic_time.h" #include "user_property.h" #include "types.h" @@ -48,6 +47,8 @@ public: static int const FADE_IN; static int const FADE_OUT; static int const RANGE; + static int const CUSTOM_RATIO; + static int const CUSTOM_SIZE; }; class VideoContent : public ContentPart, public boost::enable_shared_from_this @@ -87,7 +88,9 @@ public: void set_top_crop (int); void set_bottom_crop (int); - void set_scale (VideoContentScale); + void set_custom_ratio (boost::optional ratio); + void set_custom_size (boost::optional size); + void unset_colour_conversion (); void set_colour_conversion (ColourConversion); @@ -127,12 +130,19 @@ public: return _crop.bottom; } - /** @return Description of how to scale this content (if indeed it should be scaled) */ - VideoContentScale scale () const { + + boost::optional custom_ratio () const { boost::mutex::scoped_lock lm (_mutex); - return _scale; + return _custom_ratio; } + + boost::optional custom_size () const { + boost::mutex::scoped_lock lm (_mutex); + return _custom_size; + } + + boost::optional colour_conversion () const { boost::mutex::scoped_lock lm (_mutex); return _colour_conversion; @@ -168,12 +178,14 @@ public: return _use; } + /* XXX: names for these? */ dcp::Size size_after_3d_split () const; dcp::Size size_after_crop () const; + dcp::Size scaled_size (dcp::Size container_size); boost::optional fade (boost::shared_ptr film, Frame) const; - std::string processing_description (boost::shared_ptr film) const; + std::string processing_description (boost::shared_ptr film); void set_length (Frame); @@ -191,6 +203,9 @@ private: friend struct best_dcp_frame_rate_test_single; friend struct best_dcp_frame_rate_test_double; friend struct audio_sampling_rate_test; + friend struct scaled_size_test1; + friend struct scaled_size_test2; + friend struct scaled_size_legacy_test; VideoContent (Content* parent, cxml::ConstNodePtr, int); void setup_default_colour_conversion (); @@ -201,7 +216,15 @@ private: dcp::Size _size; VideoFrameType _frame_type; Crop _crop; - VideoContentScale _scale; + /** ratio to scale cropped image to (or none to guess); i.e. if set, scale to _custom_ratio:1 */ + boost::optional _custom_ratio; + /** size to scale cropped image to; only used if _custom_ratio is none */ + boost::optional _custom_size; + /** ratio obtained from an older metadata file; will be used to set up + * _custom_{ratio,size} (or not, if not required) on the first call to + * scaled_size() + */ + boost::optional _legacy_ratio; /** Sample aspect ratio obtained from the content file's header, if there is one */ boost::optional _sample_aspect_ratio; bool _yuv; diff --git a/src/lib/video_content_scale.cc b/src/lib/video_content_scale.cc deleted file mode 100644 index 73dfd27fe..000000000 --- a/src/lib/video_content_scale.cc +++ /dev/null @@ -1,171 +0,0 @@ -/* - Copyright (C) 2013-2018 Carl Hetherington - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see . - -*/ - -#include "video_content_scale.h" -#include "video_content.h" -#include "ratio.h" -#include "util.h" -#include -#include -#include -#include - -#include "i18n.h" - -using std::vector; -using std::string; -using std::min; -using std::cout; -using boost::shared_ptr; -using boost::optional; - -vector VideoContentScale::_scales; - -VideoContentScale::VideoContentScale (Ratio const * r) - : _ratio (r) - , _scale (true) -{ - -} - -VideoContentScale::VideoContentScale () - : _ratio (0) - , _scale (false) -{ - -} - -VideoContentScale::VideoContentScale (bool scale) - : _ratio (0) - , _scale (scale) -{ - -} - -VideoContentScale::VideoContentScale (shared_ptr node) - : _ratio (0) - , _scale (true) -{ - optional r = node->optional_string_child ("Ratio"); - if (r) { - _ratio = Ratio::from_id (r.get ()); - } else { - _scale = node->bool_child ("Scale"); - } -} - -void -VideoContentScale::as_xml (xmlpp::Node* node) const -{ - if (_ratio) { - node->add_child("Ratio")->add_child_text (_ratio->id ()); - } else { - node->add_child("Scale")->add_child_text (_scale ? "1" : "0"); - } -} - -string -VideoContentScale::id () const -{ - if (_ratio) { - return _ratio->id (); - } - - return (_scale ? "S1" : "S0"); -} - -string -VideoContentScale::name () const -{ - if (_ratio) { - return _ratio->image_nickname (); - } - - if (_scale) { - return _("No stretch"); - } - - return _("No scale"); -} - -/** @param display_container Size of the container that we are displaying this content in. - * @param film_container The size of the film's image. - * @return Size, in pixels that the VideoContent's image should be scaled to (taking into account its pixel aspect ratio) - */ -dcp::Size -VideoContentScale::size (shared_ptr c, dcp::Size display_container, dcp::Size film_container) const -{ - /* Work out the size of the content if it were put inside film_container */ - - dcp::Size video_size_after_crop = c->size_after_crop(); - video_size_after_crop.width *= c->sample_aspect_ratio().get_value_or(1); - - dcp::Size size; - - if (_ratio) { - /* Stretch to fit the requested ratio */ - size = fit_ratio_within (_ratio->ratio (), film_container); - } else if (_scale || video_size_after_crop.width > film_container.width || video_size_after_crop.height > film_container.height) { - /* Scale, preserving aspect ratio; this is either if we have been asked to scale with no stretch - or if the unscaled content is too big for film_container. - */ - size = fit_ratio_within (video_size_after_crop.ratio(), film_container); - } else { - /* No stretch nor scale */ - size = video_size_after_crop; - } - - /* Now scale it down if the display container is smaller than the film container */ - if (display_container != film_container) { - float const scale = min ( - float (display_container.width) / film_container.width, - float (display_container.height) / film_container.height - ); - - size.width = lrintf (size.width * scale); - size.height = lrintf (size.height * scale); - } - - return size; -} - -void -VideoContentScale::setup_scales () -{ - vector ratios = Ratio::all (); - for (vector::const_iterator i = ratios.begin(); i != ratios.end(); ++i) { - _scales.push_back (VideoContentScale (*i)); - } - - _scales.push_back (VideoContentScale (true)); - _scales.push_back (VideoContentScale (false)); -} - -bool -operator== (VideoContentScale const & a, VideoContentScale const & b) -{ - return (a.ratio() == b.ratio() && a.scale() == b.scale()); -} - -bool -operator!= (VideoContentScale const & a, VideoContentScale const & b) -{ - return (a.ratio() != b.ratio() || a.scale() != b.scale()); -} diff --git a/src/lib/video_content_scale.h b/src/lib/video_content_scale.h deleted file mode 100644 index 845c71a52..000000000 --- a/src/lib/video_content_scale.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright (C) 2013-2018 Carl Hetherington - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see . - -*/ - -#ifndef DCPOMATIC_VIDEO_CONTENT_SCALE_H -#define DCPOMATIC_VIDEO_CONTENT_SCALE_H - -#include -#include -#include - -namespace cxml { - class Node; -} - -namespace xmlpp { - class Node; -} - -class Ratio; -class VideoContent; - -class VideoContentScale -{ -public: - VideoContentScale (); - explicit VideoContentScale (Ratio const *); - explicit VideoContentScale (bool); - explicit VideoContentScale (boost::shared_ptr); - - dcp::Size size (boost::shared_ptr, dcp::Size display_container, dcp::Size film_container) const; - std::string id () const; - std::string name () const; - void as_xml (xmlpp::Node *) const; - - Ratio const * ratio () const { - return _ratio; - } - - bool scale () const { - return _scale; - } - - static void setup_scales (); - static std::vector all () { - return _scales; - } - -private: - /** a ratio to stretch the content to, or 0 for no stretch */ - Ratio const * _ratio; - /** true if we want to change the size of the content in any way */ - bool _scale; - - /* If _ratio is 0 and _scale is false there is no scale at all (i.e. - the content is used at its original size) - */ - - static std::vector _scales; -}; - -bool operator== (VideoContentScale const & a, VideoContentScale const & b); -bool operator!= (VideoContentScale const & a, VideoContentScale const & b); - -#endif diff --git a/src/lib/wscript b/src/lib/wscript index 0f2a5d197..fb222fcf4 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -177,7 +177,6 @@ sources = """ util.cc verify_dcp_job.cc video_content.cc - video_content_scale.cc video_decoder.cc video_filter_graph.cc video_mxf_content.cc diff --git a/src/tools/dcpomatic_cli.cc b/src/tools/dcpomatic_cli.cc index 6a243e126..edf4808a0 100644 --- a/src/tools/dcpomatic_cli.cc +++ b/src/tools/dcpomatic_cli.cc @@ -96,8 +96,10 @@ print_dump (shared_ptr film) << "\tcrop left " << c->video->left_crop() << " right " << c->video->right_crop() << " top " << c->video->top_crop() - << " bottom " << c->video->bottom_crop() << "\n" - << "\tscale " << c->video->scale().name() << "\n"; + << " bottom " << c->video->bottom_crop() << "\n"; + if (c->video->custom_ratio()) { + cout << "\tscale to custom ratio " << *c->video->custom_ratio() << ":1\n"; + } if (c->video->colour_conversion()) { if (c->video->colour_conversion().get().preset()) { cout << "\tcolour conversion " diff --git a/src/tools/dcpomatic_create.cc b/src/tools/dcpomatic_create.cc index 68ae09c31..bcfc2f68b 100644 --- a/src/tools/dcpomatic_create.cc +++ b/src/tools/dcpomatic_create.cc @@ -131,7 +131,6 @@ main (int argc, char* argv[]) BOOST_FOREACH (shared_ptr j, content) { if (j->video) { - j->video->set_scale (VideoContentScale(cc.content_ratio)); j->video->set_frame_type (i.frame_type); } } diff --git a/src/wx/custom_scale_dialog.cc b/src/wx/custom_scale_dialog.cc new file mode 100644 index 000000000..5725d2378 --- /dev/null +++ b/src/wx/custom_scale_dialog.cc @@ -0,0 +1,142 @@ +/* + Copyright (C) 2020 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + + +#include "custom_scale_dialog.h" +#include "wx_util.h" +#include "lib/util.h" +#include +#include +#include +#include + + +using boost::optional; +using namespace dcp; + + +CustomScaleDialog::CustomScaleDialog (wxWindow* parent, dcp::Size initial, dcp::Size film_container, optional custom_ratio, optional custom_size) + : TableDialog (parent, _("Custom scale"), 3, 1, true) + , _film_container (film_container) +{ + _ratio_to_fit = new wxRadioButton (this, wxID_ANY, _("Set ratio and fit to DCP container")); + add (_ratio_to_fit); + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _ratio = new wxTextCtrl (this, wxID_ANY, _(""), wxDefaultPosition, wxDefaultSize, 0, wxNumericPropertyValidator(wxNumericPropertyValidator::Float)); + s->Add (_ratio, 1, wxRIGHT, 4); + add_label_to_sizer (s, this, wxT(":1"), false); + add (s); + _size_from_ratio = new wxStaticText (this, wxID_ANY, wxT("")); + add (_size_from_ratio, 1, wxALIGN_CENTER_VERTICAL); + + _size = new wxRadioButton (this, wxID_ANY, _("Set size")); + add (_size); + s = new wxBoxSizer (wxHORIZONTAL); + _width = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(64, -1), wxSP_ARROW_KEYS, 1, film_container.width); + s->Add (_width, 1, wxRIGHT, 4); + add_label_to_sizer (s, this, wxT("x"), false); + _height = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(64, -1), wxSP_ARROW_KEYS, 1, film_container.height); + s->Add (_height, 1, wxRIGHT, 4); + add (s); + _ratio_from_size = new wxStaticText (this, wxID_ANY, wxT("")); + add (_ratio_from_size, 1, wxALIGN_CENTER_VERTICAL); + + if (custom_ratio) { + _ratio_to_fit->SetValue (true); + _size->SetValue (false); + _ratio->SetValue (wxString::Format("%.2f", *custom_ratio)); + _width->SetValue (initial.width); + _height->SetValue (initial.height); + } else if (custom_size) { + _ratio_to_fit->SetValue (false); + _size->SetValue (true); + _ratio->SetValue (wxString::Format("%.2f", initial.ratio())); + _width->SetValue (custom_size->width); + _height->SetValue (custom_size->height); + } else { + _ratio_to_fit->SetValue (true); + _size->SetValue (false); + _ratio->SetValue (wxString::Format("%.2f", initial.ratio())); + _width->SetValue (initial.width); + _height->SetValue (initial.height); + } + + setup_sensitivity (); + update_size_from_ratio (); + update_ratio_from_size (); + + layout (); + + _ratio_to_fit->Bind (wxEVT_RADIOBUTTON, boost::bind(&CustomScaleDialog::setup_sensitivity, this)); + _ratio->Bind (wxEVT_TEXT, boost::bind(&CustomScaleDialog::update_size_from_ratio, this)); + _size->Bind (wxEVT_RADIOBUTTON, boost::bind(&CustomScaleDialog::setup_sensitivity, this)); + _width->Bind (wxEVT_TEXT, boost::bind(&CustomScaleDialog::update_ratio_from_size, this)); + _height->Bind (wxEVT_TEXT, boost::bind(&CustomScaleDialog::update_ratio_from_size, this)); +} + + +void +CustomScaleDialog::update_size_from_ratio () +{ + dcp::Size const s = fit_ratio_within (raw_convert(wx_to_std(_ratio->GetValue())), _film_container); + _size_from_ratio->SetLabelMarkup (wxString::Format("%dx%d", s.width, s.height)); +} + + +void +CustomScaleDialog::update_ratio_from_size () +{ + float const ratio = _height->GetValue() > 0 ? (float(_width->GetValue()) / _height->GetValue()) : 2; + _ratio_from_size->SetLabelMarkup (wxString::Format("%.2f:1", ratio)); +} + + +void +CustomScaleDialog::setup_sensitivity () +{ + _ratio->Enable (_ratio_to_fit->GetValue()); + _size_from_ratio->Enable (_ratio_to_fit->GetValue()); + _width->Enable (_size->GetValue()); + _height->Enable (_size->GetValue()); + _ratio_from_size->Enable (_size->GetValue()); +} + + +optional +CustomScaleDialog::custom_ratio () const +{ + if (!_ratio_to_fit->GetValue()) { + return optional(); + } + + return raw_convert(wx_to_std(_ratio->GetValue())); +} + + +optional +CustomScaleDialog::custom_size () const +{ + if (!_size->GetValue()) { + return optional(); + } + + return dcp::Size (_width->GetValue(), _height->GetValue()); +} + diff --git a/src/wx/custom_scale_dialog.h b/src/wx/custom_scale_dialog.h new file mode 100644 index 000000000..4c9ccf388 --- /dev/null +++ b/src/wx/custom_scale_dialog.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2020 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + + +#include "table_dialog.h" +#include +#include +#include + + +class CustomScaleDialog : public TableDialog +{ +public: + CustomScaleDialog (wxWindow* parent, dcp::Size initial, dcp::Size film_container, boost::optional custom_ratio, boost::optional custom_size); + + boost::optional custom_ratio () const; + boost::optional custom_size () const; + +private: + void update_size_from_ratio (); + void update_ratio_from_size (); + void setup_sensitivity (); + + wxRadioButton* _ratio_to_fit; + wxTextCtrl* _ratio; + wxStaticText* _size_from_ratio; + wxRadioButton* _size; + wxSpinCtrl* _width; + wxSpinCtrl* _height; + wxStaticText* _ratio_from_size; + + dcp::Size _film_container; +}; + diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc index b01e9b8aa..8a9136008 100644 --- a/src/wx/video_panel.cc +++ b/src/wx/video_panel.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington + Copyright (C) 2012-2020 Carl Hetherington This file is part of DCP-o-matic. @@ -26,6 +26,7 @@ #include "content_panel.h" #include "static_text.h" #include "check_box.h" +#include "custom_scale_dialog.h" #include "dcpomatic_button.h" #include "lib/filter.h" #include "lib/ffmpeg_content.h" @@ -55,27 +56,6 @@ using boost::bind; using boost::optional; using namespace dcpomatic; -static VideoContentScale -index_to_scale (int n) -{ - vector scales = VideoContentScale::all (); - DCPOMATIC_ASSERT (n >= 0); - DCPOMATIC_ASSERT (n < int (scales.size ())); - return scales[n]; -} - -static int -scale_to_index (VideoContentScale scale) -{ - vector scales = VideoContentScale::all (); - for (size_t i = 0; i < scales.size(); ++i) { - if (scales[i] == scale) { - return i; - } - } - - DCPOMATIC_ASSERT (false); -} VideoPanel::VideoPanel (ContentPanel* p) : ContentSubPanel (p, _("Video")) @@ -150,22 +130,15 @@ VideoPanel::VideoPanel (ContentPanel* p) _fade_out_label = create_label (this, _("Fade out"), true); _fade_out = new Timecode (this); - _scale_to_label = create_label (this, _("Scale to"), true); - _scale = new ContentChoice ( - this, - new wxChoice (this, wxID_ANY), - VideoContentProperty::SCALE, - &Content::video, - boost::mem_fn (&VideoContent::scale), - boost::mem_fn (&VideoContent::set_scale), - &index_to_scale, - &scale_to_index - ); - wxClientDC dc (this); wxSize size = dc.GetTextExtent (wxT ("A quite long name")); size.SetHeight (-1); + _scale_label = create_label (this, _("Scale"), true); + _scale_fit = new wxRadioButton (this, wxID_ANY, _("to fit DCP")); + _scale_custom = new wxRadioButton (this, wxID_ANY, _("custom"), wxDefaultPosition, size); + _scale_custom_edit = new Button (this, _("Edit...")); + _filters_label = create_label (this, _("Filters"), true); _filters = new StaticText (this, _("None"), wxDefaultPosition, size); _filters_button = new Button (this, _("Edit...")); @@ -194,11 +167,6 @@ VideoPanel::VideoPanel (ContentPanel* p) _right_crop->wrapped()->SetRange (0, 4096); _bottom_crop->wrapped()->SetRange (0, 4096); - _scale->wrapped()->Clear (); - BOOST_FOREACH (VideoContentScale const & i, VideoContentScale::all ()) { - _scale->wrapped()->Append (std_to_wx (i.name ())); - } - _frame_type->wrapped()->Append (_("2D")); _frame_type->wrapped()->Append (_("3D")); _frame_type->wrapped()->Append (_("3D left/right")); @@ -215,6 +183,9 @@ VideoPanel::VideoPanel (ContentPanel* p) _use->Bind (wxEVT_CHECKBOX, boost::bind (&VideoPanel::use_clicked, this)); _reference->Bind (wxEVT_CHECKBOX, boost::bind (&VideoPanel::reference_clicked, this)); _filters_button->Bind (wxEVT_BUTTON, boost::bind (&VideoPanel::edit_filters_clicked, this)); + _scale_fit->Bind (wxEVT_RADIOBUTTON, boost::bind (&VideoPanel::scale_fit_clicked, this)); + _scale_custom->Bind (wxEVT_RADIOBUTTON, boost::bind (&VideoPanel::scale_custom_clicked, this)); + _scale_custom_edit->Bind (wxEVT_BUTTON, boost::bind (&VideoPanel::scale_custom_edit_clicked, this)); _colour_conversion->Bind (wxEVT_CHOICE, boost::bind (&VideoPanel::colour_conversion_changed, this)); _range->Bind (wxEVT_CHOICE, boost::bind (&VideoPanel::range_changed, this)); _edit_colour_conversion_button->Bind (wxEVT_BUTTON, boost::bind (&VideoPanel::edit_colour_conversion_clicked, this)); @@ -260,11 +231,13 @@ VideoPanel::add_to_grid () add_label_to_sizer (crop, _bottom_crop_label, true, wxGBPosition (cr, 2)); _bottom_crop->add (crop, wxGBPosition (cr, 3)); add_label_to_sizer (_grid, _crop_label, true, wxGBPosition(r, 0)); - _grid->Add (crop, wxGBPosition(r, 1), wxGBSpan(2, 3)); - r += 2; + _grid->Add (crop, wxGBPosition(r, 1)); + ++r; - _scale_to_label->Show (full); - _scale->show (full); + _scale_label->Show (full); + _scale_fit->Show (full); + _scale_custom->Show (full); + _scale_custom_edit->Show (full); _filters_label->Show (full); _filters->Show (full); _filters_button->Show (full); @@ -283,8 +256,16 @@ VideoPanel::add_to_grid () ++r; if (full) { - add_label_to_sizer (_grid, _scale_to_label, true, wxGBPosition (r, 0)); - _scale->add (_grid, wxGBPosition (r, 1), wxGBSpan (1, 2)); + add_label_to_sizer (_grid, _scale_label, true, wxGBPosition (r, 0)); + { + wxSizer* v = new wxBoxSizer (wxVERTICAL); + v->Add (_scale_fit, 0, wxBOTTOM, 4); + wxSizer* h = new wxBoxSizer (wxHORIZONTAL); + h->Add (_scale_custom, 1, wxRIGHT, 6); + h->Add (_scale_custom_edit, 0); + v->Add (h, 0); + _grid->Add (v, wxGBPosition(r, 1)); + } ++r; add_label_to_sizer (_grid, _filters_label, true, wxGBPosition (r, 0)); @@ -485,6 +466,20 @@ VideoPanel::film_content_changed (int property) checked_set (_range, 0); } + setup_sensitivity (); + } else if (property == VideoContentProperty::CUSTOM_RATIO || property == VideoContentProperty::CUSTOM_SIZE) { + set check; + BOOST_FOREACH (shared_ptr i, vc) { + check.insert (i->video->custom_ratio() || i->video->custom_size()); + } + + if (check.size() == 1) { + checked_set (_scale_fit, !vc.front()->video->custom_ratio() && !vc.front()->video->custom_size()); + checked_set (_scale_custom, vc.front()->video->custom_ratio() || vc.front()->video->custom_size()); + } else { + checked_set (_scale_fit, true); + checked_set (_scale_custom, false); + } setup_sensitivity (); } } @@ -576,7 +571,6 @@ VideoPanel::content_selection_changed () _right_crop->set_content (video_sel); _top_crop->set_content (video_sel); _bottom_crop->set_content (video_sel); - _scale->set_content (video_sel); film_content_changed (ContentProperty::VIDEO_FRAME_RATE); film_content_changed (VideoContentProperty::CROP); @@ -585,6 +579,8 @@ VideoPanel::content_selection_changed () film_content_changed (VideoContentProperty::FADE_OUT); film_content_changed (VideoContentProperty::RANGE); film_content_changed (VideoContentProperty::USE); + film_content_changed (VideoContentProperty::CUSTOM_RATIO); + film_content_changed (VideoContentProperty::CUSTOM_SIZE); film_content_changed (FFmpegContentProperty::FILTERS); film_content_changed (DCPContentProperty::REFERENCE_VIDEO); @@ -623,7 +619,9 @@ VideoPanel::setup_sensitivity () _bottom_crop->wrapped()->Enable (false); _fade_in->Enable (false); _fade_out->Enable (false); - _scale->wrapped()->Enable (false); + _scale_fit->Enable (false); + _scale_custom->Enable (false); + _scale_custom_edit->Enable (false); _description->Enable (false); _filters->Enable (false); _filters_button->Enable (false); @@ -641,7 +639,9 @@ VideoPanel::setup_sensitivity () _bottom_crop->wrapped()->Enable (true); _fade_in->Enable (!video_sel.empty ()); _fade_out->Enable (!video_sel.empty ()); - _scale->wrapped()->Enable (true); + _scale_fit->Enable (true); + _scale_custom->Enable (true); + _scale_custom_edit->Enable (_scale_custom->GetValue()); _description->Enable (true); _filters->Enable (true); _filters_button->Enable (single && !ffmpeg_sel.empty ()); @@ -703,3 +703,39 @@ VideoPanel::reference_clicked () d->set_reference_video (_reference->GetValue ()); } + + +void +VideoPanel::scale_fit_clicked () +{ + BOOST_FOREACH (shared_ptr i, _parent->selected_video()) { + i->video->set_custom_ratio (optional()); + } +} + + +void +VideoPanel::scale_custom_clicked () +{ + if (!scale_custom_edit_clicked()) { + _scale_fit->SetValue (true); + } +} + + +bool +VideoPanel::scale_custom_edit_clicked () +{ + shared_ptr vc = _parent->selected_video().front()->video; + CustomScaleDialog* d = new CustomScaleDialog (this, vc->size(), _parent->film()->frame_size(), vc->custom_ratio(), vc->custom_size()); + int const r = d->ShowModal (); + if (r == wxID_OK) { + BOOST_FOREACH (shared_ptr i, _parent->selected_video()) { + i->video->set_custom_ratio (d->custom_ratio()); + i->video->set_custom_size (d->custom_size()); + } + } + d->Destroy (); + return r == wxID_OK; +} + diff --git a/src/wx/video_panel.h b/src/wx/video_panel.h index 04063ef54..22c564482 100644 --- a/src/wx/video_panel.h +++ b/src/wx/video_panel.h @@ -25,7 +25,6 @@ #include "content_sub_panel.h" #include "content_widget.h" #include "timecode.h" -#include "lib/video_content_scale.h" #include "lib/film.h" class wxChoice; @@ -55,6 +54,9 @@ private: void fade_in_changed (); void fade_out_changed (); void add_to_grid (); + void scale_fit_clicked (); + void scale_custom_clicked (); + bool scale_custom_edit_clicked (); void setup_description (); void setup_sensitivity (); @@ -77,8 +79,10 @@ private: Timecode* _fade_in; wxStaticText* _fade_out_label; Timecode* _fade_out; - wxStaticText* _scale_to_label; - ContentChoice* _scale; + wxStaticText* _scale_label; + wxRadioButton* _scale_fit; + wxRadioButton* _scale_custom; + wxButton* _scale_custom_edit; wxStaticText* _description; wxStaticText* _filters_label; wxStaticText* _filters; diff --git a/src/wx/wscript b/src/wx/wscript index 22d9f0db6..a2fbe0c4e 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -49,6 +49,7 @@ sources = """ controls.cc closed_captions_dialog.cc credentials_download_certificate_panel.cc + custom_scale_dialog.cc dcp_panel.cc dcpomatic_button.cc disk_warning_dialog.cc @@ -165,7 +166,7 @@ sources = """ def configure(conf): - wx_libs = 'core,richtext,adv,html,xml' + wx_libs = 'core,richtext,adv,html,xml,propgrid' try: wx_config = '/usr/lib64/wx/config/gtk2-unicode-3.0' diff --git a/test/4k_test.cc b/test/4k_test.cc index 71d60f573..d8d3d66ec 100644 --- a/test/4k_test.cc +++ b/test/4k_test.cc @@ -50,8 +50,6 @@ BOOST_AUTO_TEST_CASE (fourk_test) film->examine_and_add_content (c); BOOST_REQUIRE (!wait_for_jobs()); - c->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); - film->make_dcp (); BOOST_REQUIRE (!wait_for_jobs()); diff --git a/test/create_cli_test.cc b/test/create_cli_test.cc index b92cb284b..5425969b6 100644 --- a/test/create_cli_test.cc +++ b/test/create_cli_test.cc @@ -70,60 +70,53 @@ BOOST_AUTO_TEST_CASE (create_cli_test) cc = run ("dcpomatic2_create -h"); BOOST_REQUIRE (cc.error); - cc = run ("dcpomatic2_create x --content-ratio 185 --name frobozz --template bar"); + cc = run ("dcpomatic2_create x --name frobozz --template bar"); BOOST_CHECK (!cc.error); BOOST_CHECK_EQUAL (cc.name, "frobozz"); BOOST_REQUIRE (cc.template_name); BOOST_CHECK_EQUAL (*cc.template_name, "bar"); - cc = run ("dcpomatic2_create x --content-ratio 185 --dcp-content-type FTR"); + cc = run ("dcpomatic2_create x --dcp-content-type FTR"); BOOST_CHECK (!cc.error); BOOST_CHECK_EQUAL (cc.dcp_content_type, DCPContentType::from_isdcf_name("FTR")); - cc = run ("dcpomatic2_create x --content-ratio 185 --dcp-frame-rate 30"); + cc = run ("dcpomatic2_create x --dcp-frame-rate 30"); BOOST_CHECK (!cc.error); BOOST_REQUIRE (cc.dcp_frame_rate); BOOST_CHECK_EQUAL (*cc.dcp_frame_rate, 30); - cc = run ("dcpomatic2_create x --content-ratio 185 --container-ratio 185"); + cc = run ("dcpomatic2_create x --container-ratio 185"); BOOST_CHECK (!cc.error); BOOST_CHECK_EQUAL (cc.container_ratio, Ratio::from_id("185")); - cc = run ("dcpomatic2_create x --content-ratio 185 --container-ratio XXX"); + cc = run ("dcpomatic2_create x --container-ratio XXX"); BOOST_CHECK (cc.error); - cc = run ("dcpomatic2_create x --content-ratio 185 --content-ratio 239"); - BOOST_CHECK (!cc.error); - BOOST_CHECK_EQUAL (cc.content_ratio, Ratio::from_id("239")); - - cc = run ("dcpomatic2_create x --content-ratio 240"); - BOOST_CHECK (cc.error); - - cc = run ("dcpomatic2_create x --content-ratio 185 --still-length 42"); + cc = run ("dcpomatic2_create x --still-length 42"); BOOST_CHECK (!cc.error); BOOST_CHECK_EQUAL (cc.still_length, 42); - cc = run ("dcpomatic2_create x --content-ratio 185 --standard SMPTE"); + cc = run ("dcpomatic2_create x --standard SMPTE"); BOOST_CHECK (!cc.error); BOOST_CHECK_EQUAL (cc.standard, dcp::SMPTE); - cc = run ("dcpomatic2_create x --content-ratio 185 --standard SMPTEX"); + cc = run ("dcpomatic2_create x --standard SMPTEX"); BOOST_CHECK (cc.error); - cc = run ("dcpomatic2_create x --content-ratio 185 --config foo/bar"); + cc = run ("dcpomatic2_create x --config foo/bar"); BOOST_CHECK (!cc.error); BOOST_REQUIRE (cc.config_dir); BOOST_CHECK_EQUAL (*cc.config_dir, "foo/bar"); - cc = run ("dcpomatic2_create x --content-ratio 185 --output fred/jim"); + cc = run ("dcpomatic2_create x --output fred/jim"); BOOST_CHECK (!cc.error); BOOST_REQUIRE (cc.output_dir); BOOST_CHECK_EQUAL (*cc.output_dir, "fred/jim"); - cc = run ("dcpomatic2_create x --content-ratio 185 --outputX fred/jim"); + cc = run ("dcpomatic2_create x --outputX fred/jim"); BOOST_CHECK (cc.error); - cc = run ("dcpomatic2_create --content-ratio 185 --config foo/bar --still-length 42 --output flaps fred jim sheila"); + cc = run ("dcpomatic2_create --config foo/bar --still-length 42 --output flaps fred jim sheila"); BOOST_CHECK (!cc.error); BOOST_REQUIRE (cc.config_dir); BOOST_CHECK_EQUAL (*cc.config_dir, "foo/bar"); @@ -138,7 +131,7 @@ BOOST_AUTO_TEST_CASE (create_cli_test) BOOST_CHECK_EQUAL (cc.content[2].path, "sheila"); BOOST_CHECK_EQUAL (cc.content[2].frame_type, VIDEO_FRAME_TYPE_2D); - cc = run ("dcpomatic2_create --content-ratio 185 --left-eye left.mp4 --right-eye right.mp4"); + cc = run ("dcpomatic2_create --left-eye left.mp4 --right-eye right.mp4"); BOOST_REQUIRE_EQUAL (cc.content.size(), 2); BOOST_CHECK_EQUAL (cc.content[0].path, "left.mp4"); BOOST_CHECK_EQUAL (cc.content[0].frame_type, VIDEO_FRAME_TYPE_3D_LEFT); @@ -146,13 +139,13 @@ BOOST_AUTO_TEST_CASE (create_cli_test) BOOST_CHECK_EQUAL (cc.content[1].frame_type, VIDEO_FRAME_TYPE_3D_RIGHT); BOOST_CHECK_EQUAL (cc.fourk, false); - cc = run ("dcpomatic2_create --fourk --content-ratio 185 foo.mp4"); + cc = run ("dcpomatic2_create --fourk foo.mp4"); BOOST_REQUIRE_EQUAL (cc.content.size(), 1); BOOST_CHECK_EQUAL (cc.content[0].path, "foo.mp4"); BOOST_CHECK_EQUAL (cc.fourk, true); BOOST_CHECK (!cc.error); - cc = run ("dcpomatic2_create --j2k-bandwidth 120 --content-ratio 185 foo.mp4"); + cc = run ("dcpomatic2_create --j2k-bandwidth 120 foo.mp4"); BOOST_REQUIRE_EQUAL (cc.content.size(), 1); BOOST_CHECK_EQUAL (cc.content[0].path, "foo.mp4"); BOOST_REQUIRE (cc.j2k_bandwidth); diff --git a/test/data b/test/data index 6b6948894..9ec245b7f 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 6b694889479064979b52c1839a1919dc5fde6731 +Subproject commit 9ec245b7f59b65ad6dd6d0f717686931ff66d748 diff --git a/test/empty_test.cc b/test/empty_test.cc index 029e83966..a2557d4d8 100644 --- a/test/empty_test.cc +++ b/test/empty_test.cc @@ -55,10 +55,8 @@ BOOST_AUTO_TEST_CASE (empty_test1) /* 0 1 2 3 4 5 6 7 * A A A B */ - contentA->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); contentA->video->set_length (3); contentA->set_position (film, DCPTime::from_frames (2, vfr)); - contentB->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); contentB->video->set_length (1); contentB->set_position (film, DCPTime::from_frames (7, vfr)); @@ -89,10 +87,8 @@ BOOST_AUTO_TEST_CASE (empty_test2) /* 0 1 2 3 4 5 6 7 * A A A B */ - contentA->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); contentA->video->set_length (3); contentA->set_position (film, DCPTime(0)); - contentB->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); contentB->video->set_length (1); contentB->set_position (film, DCPTime::from_frames(7, vfr)); @@ -129,10 +125,8 @@ BOOST_AUTO_TEST_CASE (empty_test3) /* 0 1 2 3 4 5 6 7 * A A A B */ - contentA->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); contentA->video->set_length (3); contentA->set_position (film, DCPTime(0)); - contentB->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); contentB->video->set_length (1); contentB->set_position (film, DCPTime::from_frames(7, vfr)); diff --git a/test/ffmpeg_audio_test.cc b/test/ffmpeg_audio_test.cc index 6ad6c1fdb..e9b0c7039 100644 --- a/test/ffmpeg_audio_test.cc +++ b/test/ffmpeg_audio_test.cc @@ -53,8 +53,6 @@ BOOST_AUTO_TEST_CASE (ffmpeg_audio_test) BOOST_REQUIRE (!wait_for_jobs()); - c->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); - film->set_container (Ratio::from_id ("185")); film->set_audio_channels (6); film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST")); diff --git a/test/ffmpeg_dcp_test.cc b/test/ffmpeg_dcp_test.cc index 78847e40b..ad09e5e1a 100644 --- a/test/ffmpeg_dcp_test.cc +++ b/test/ffmpeg_dcp_test.cc @@ -46,8 +46,6 @@ BOOST_AUTO_TEST_CASE (ffmpeg_dcp_test) BOOST_REQUIRE (!wait_for_jobs()); - c->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); - film->set_container (Ratio::from_id ("185")); film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST")); film->make_dcp (); diff --git a/test/isdcf_name_test.cc b/test/isdcf_name_test.cc index 3315833b0..487f80ea2 100644 --- a/test/isdcf_name_test.cc +++ b/test/isdcf_name_test.cc @@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE (isdcf_name_test) shared_ptr content (new ImageContent ("test/data/simple_testcard_640x480.png")); film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); - content->video->set_scale (VideoContentScale (Ratio::from_id ("133"))); + content->video->set_custom_ratio (1.33); film->set_container (Ratio::from_id ("185")); BOOST_CHECK_EQUAL (film->isdcf_name(false), "MyNiceFilmWith_TLR-2_F_DE-fr_US-R_MOS_4K_DI_20140704_PP_SMPTE_OV"); @@ -108,12 +108,12 @@ BOOST_AUTO_TEST_CASE (isdcf_name_test) /* And it should always be numeric */ - content->video->set_scale (VideoContentScale (Ratio::from_id ("239"))); + content->video->set_custom_ratio (2.39); BOOST_CHECK_EQUAL (film->isdcf_name(false), "MyNiceFilmWith_XSN-2_F-239_DE-fr_US-R_MOS_4K_DI_20140704_PP_SMPTE_OV"); - content->video->set_scale (VideoContentScale (Ratio::from_id ("190"))); + content->video->set_custom_ratio (1.9); BOOST_CHECK_EQUAL (film->isdcf_name(false), "MyNiceFilmWith_XSN-2_F-190_DE-fr_US-R_MOS_4K_DI_20140704_PP_SMPTE_OV"); - content->video->set_scale (VideoContentScale (Ratio::from_id ("133"))); + content->video->set_custom_ratio (1.33); /* Test 3D */ diff --git a/test/player_test.cc b/test/player_test.cc index 6877d7e21..2e979eb44 100644 --- a/test/player_test.cc +++ b/test/player_test.cc @@ -103,12 +103,12 @@ BOOST_AUTO_TEST_CASE (player_black_fill_test) film->examine_and_add_content (contentB); BOOST_REQUIRE (!wait_for_jobs()); - contentA->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); contentA->video->set_length (3); contentA->set_position (film, DCPTime::from_frames(2, film->video_frame_rate())); - contentB->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); + contentA->video->set_custom_ratio (1.85); contentB->video->set_length (1); contentB->set_position (film, DCPTime::from_frames(7, film->video_frame_rate())); + contentB->video->set_custom_ratio (1.85); film->make_dcp (); diff --git a/test/recover_test.cc b/test/recover_test.cc index e8194fd81..9c1ed7e66 100644 --- a/test/recover_test.cc +++ b/test/recover_test.cc @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE (recover_test_2d) film->make_dcp (); BOOST_REQUIRE (!wait_for_jobs()); - boost::filesystem::path const video = "build/test/recover_test_2d/video/185_2K_d4343facdd66ca71f62a964fbade89f3_24_100000000_P_S_0_1200000.mxf"; + boost::filesystem::path const video = "build/test/recover_test_2d/video/185_2K_02543352c540f4b083bff3f1e309d4a9_24_100000000_P_S_0_1200000.mxf"; boost::filesystem::copy_file ( video, "build/test/recover_test_2d/original.mxf" @@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE (recover_test_3d, * boost::unit_test::depends_on("recover_t film->make_dcp (); BOOST_REQUIRE (!wait_for_jobs()); - boost::filesystem::path const video = "build/test/recover_test_3d/video/185_2K_342fe9115d2b446914b31f7602e48cc6_24_100000000_P_S_3D_0_96000.mxf"; + boost::filesystem::path const video = "build/test/recover_test_3d/video/185_2K_70e6661af92ae94458784c16a21a9748_24_100000000_P_S_3D_0_96000.mxf"; boost::filesystem::copy_file ( video, @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE (recover_test_2d_encrypted, * boost::unit_test::depends_on( BOOST_REQUIRE (!wait_for_jobs()); boost::filesystem::path const video = - "build/test/recover_test_2d_encrypted/video/185_2K_d4343facdd66ca71f62a964fbade89f3_24_100000000_Eeafcb91c9f5472edf01f3a2404c57258_S_0_1200000.mxf"; + "build/test/recover_test_2d_encrypted/video/185_2K_02543352c540f4b083bff3f1e309d4a9_24_100000000_Eeafcb91c9f5472edf01f3a2404c57258_S_0_1200000.mxf"; boost::filesystem::copy_file ( video, diff --git a/test/repeat_frame_test.cc b/test/repeat_frame_test.cc index 1075f96fc..358e6fe8f 100644 --- a/test/repeat_frame_test.cc +++ b/test/repeat_frame_test.cc @@ -45,10 +45,8 @@ BOOST_AUTO_TEST_CASE (repeat_frame_test) film->set_interop (false); shared_ptr c (new FFmpegContent("test/data/red_24.mp4")); film->examine_and_add_content (c); - BOOST_REQUIRE (!wait_for_jobs()); - - c->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); + c->video->set_custom_ratio (1.85); film->set_video_frame_rate (48); film->make_dcp (); diff --git a/test/scaling_test.cc b/test/scaling_test.cc index 93c994741..dd3b6118e 100644 --- a/test/scaling_test.cc +++ b/test/scaling_test.cc @@ -34,9 +34,9 @@ using std::string; using boost::shared_ptr; -static void scaling_test_for (shared_ptr film, shared_ptr content, string image, string container) +static void scaling_test_for (shared_ptr film, shared_ptr content, float ratio, std::string image, string container) { - content->video->set_scale (VideoContentScale (Ratio::from_id (image))); + content->video->set_custom_ratio (ratio); film->set_container (Ratio::from_id (container)); film->set_interop (false); film->make_dcp (); @@ -71,16 +71,16 @@ BOOST_AUTO_TEST_CASE (scaling_test) imc->video->set_length (1); /* F-133: 133 image in a flat container */ - scaling_test_for (film, imc, "133", "185"); + scaling_test_for (film, imc, 4.0 / 3, "133", "185"); /* F: flat image in a flat container */ - scaling_test_for (film, imc, "185", "185"); + scaling_test_for (film, imc, 1.85, "185", "185"); /* F-S: scope image in a flat container */ - scaling_test_for (film, imc, "239", "185"); + scaling_test_for (film, imc, 2.38695, "239", "185"); /* S-133: 133 image in a scope container */ - scaling_test_for (film, imc, "133", "239"); + scaling_test_for (film, imc, 4.0 / 3, "133", "239"); /* S-F: flat image in a scope container */ - scaling_test_for (film, imc, "185", "239"); + scaling_test_for (film, imc, 1.85, "185", "239"); /* S: scope image in a scope container */ - scaling_test_for (film, imc, "239", "239"); + scaling_test_for (film, imc, 2.38695, "239", "239"); } diff --git a/test/skip_frame_test.cc b/test/skip_frame_test.cc index e30143b18..aea389ce3 100644 --- a/test/skip_frame_test.cc +++ b/test/skip_frame_test.cc @@ -48,7 +48,6 @@ BOOST_AUTO_TEST_CASE (skip_frame_test) BOOST_REQUIRE (!wait_for_jobs()); - c->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); film->write_metadata (); film->set_video_frame_rate (24); diff --git a/test/threed_test.cc b/test/threed_test.cc index 473cc00d3..266b7bf58 100644 --- a/test/threed_test.cc +++ b/test/threed_test.cc @@ -49,7 +49,6 @@ BOOST_AUTO_TEST_CASE (threed_test1) BOOST_REQUIRE (!wait_for_jobs()); c->video->set_frame_type (VIDEO_FRAME_TYPE_3D_LEFT_RIGHT); - c->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); film->set_container (Ratio::from_id ("185")); film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST")); @@ -72,7 +71,6 @@ BOOST_AUTO_TEST_CASE (threed_test2) BOOST_REQUIRE (!wait_for_jobs()); c->video->set_frame_type (VIDEO_FRAME_TYPE_3D_ALTERNATE); - c->video->set_scale (VideoContentScale (Ratio::from_id ("185"))); film->set_container (Ratio::from_id ("185")); film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST")); diff --git a/test/video_content_scale_test.cc b/test/video_content_scale_test.cc index 67bfda3e5..b3e3ff76c 100644 --- a/test/video_content_scale_test.cc +++ b/test/video_content_scale_test.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2015 Carl Hetherington + Copyright (C) 2020 Carl Hetherington This file is part of DCP-o-matic. @@ -18,188 +18,128 @@ */ -/** @file test/video_content_scale_test.cc - * @brief Test VideoContentScale - * @ingroup selfcontained - */ -#include "lib/ffmpeg_content.h" #include "lib/ratio.h" #include "lib/video_content.h" -#include #include -using std::list; -using std::string; -using std::cerr; -using boost::shared_ptr; -using boost::optional; -using dcp::raw_convert; -static -void -test (dcp::Size content_size, dcp::Size display_size, dcp::Size film_size, Crop crop, Ratio const * ratio, bool scale, dcp::Size correct) -{ - shared_ptr film; - string s = "" - "" - "FFmpeg" - "/home/c.hetherington/DCP/prophet_long_clip.mkv" - "f3f23663da5bef6d2cbaa0db066f3351314142710" - "0" - "0" - "0" - "2879" - "" + raw_convert(content_size.width) + "" - "" + raw_convert(content_size.height) + "" - "23.97602462768555" - "23.97602462768555" - "0" - "1" - "12" - "" + raw_convert(crop.left) + "" - "" + raw_convert(crop.right) + "" - "" + raw_convert(crop.top) + "" - "" + raw_convert(crop.bottom) + "" - ""; - - if (ratio) { - s += "" + ratio->id() + ""; - } else { - s += "" + string(scale ? "1" : "0") + ""; - } +static dcp::Size const FOUR_TO_THREE(1436, 1080); +static dcp::Size const FLAT(1998, 1080); +static dcp::Size const SCOPE(2048, 858); - s += "" - "" - "2.4" - "1" - "0.4124564" - "0.3575761" - "0.1804375" - "0.2126729" - "0.7151522" - "0.072175" - "0.0193339" - "0.119192" - "0.9503041" - "2.6" - "" - "0" - "0" - "0" - "0" - "0" - "0" - ""; - - shared_ptr doc (new cxml::Document ()); - doc->read_string (s); - - list notes; - shared_ptr vc (new FFmpegContent (doc, 10, notes)); - - optional sc; - if (ratio) { - sc = VideoContentScale (ratio); - } else { - sc = VideoContentScale (scale); - } - dcp::Size answer = sc.get().size (vc->video, display_size, film_size); - if (answer != correct) { - cerr << "Testing " << vc->video->size().width << "x" << vc->video->size().height << "\n"; - cerr << "Testing " << display_size.width << "x" << display_size.height << "\n"; - cerr << answer.width << "x" << answer.height << " instead of " << correct.width << "x" << correct.height << "\n"; - } - BOOST_CHECK (answer == correct); +/* Test VideoContent::scaled_size() without any legacy stuff */ +BOOST_AUTO_TEST_CASE (scaled_size_test1) +{ + VideoContent vc (0); + + /* Images at full size and in DCP-approved sizes that will not be scaled */ + // Flat/scope content into flat/scope container + vc._size = FLAT; + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), FLAT); + vc._size = SCOPE; + BOOST_CHECK_EQUAL (vc.scaled_size(SCOPE), SCOPE); + // 1.33:1 into flat container + vc._size = FOUR_TO_THREE; + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(FOUR_TO_THREE)); + // Scope into flat container + vc._size = SCOPE; + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(1998, 837)); + + /* Smaller images but in the same ratios */ + vc._size = dcp::Size(185, 100); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), FLAT); + vc._size = dcp::Size(955, 400); + BOOST_CHECK_EQUAL (vc.scaled_size(SCOPE), SCOPE); + // 1.33:1 into flat container + vc._size = dcp::Size(133, 100); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(FOUR_TO_THREE)); + // Scope into flat container + vc._size = dcp::Size(239, 100); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(1998, 836)); + + /* Images at full size that are not DCP-approved but will still remain unscaled */ + vc._size = dcp::Size(600, 1080); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(600, 1080)); + vc._size = dcp::Size(1700, 1080); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(1700, 1080)); + + /* Image at full size that is too big for the container and will be shrunk */ + vc._size = dcp::Size(3000, 1080); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(1998, 719)); } -/* Test scale and stretch to specified ratio */ -BOOST_AUTO_TEST_CASE (video_content_scale_test_to_ratio) + +/* Same as scaled_size_test1 but with a non-unity sample aspect ratio */ +BOOST_AUTO_TEST_CASE (scaled_size_test2) { - /* To DCP */ - - // Flat in flat container - test ( - dcp::Size (400, 200), - dcp::Size (1998, 1080), - dcp::Size (1998, 1080), - Crop (0, 0, 0, 0), - Ratio::from_id ("185"), - true, - dcp::Size (1998, 1080) - ); - - // Scope in flat container - test ( - dcp::Size (400, 200), - dcp::Size (1998, 1080), - dcp::Size (1998, 1080), - Crop (0, 0, 0, 0), - Ratio::from_id ("239"), - true, - dcp::Size (1998, 837) - ); - - // Flat in scope container - test ( - dcp::Size (400, 200), - dcp::Size (2048, 858), - dcp::Size (2048, 858), - Crop (0, 0, 0, 0), - Ratio::from_id ("185"), - true, - dcp::Size (1587, 858) - ); - - - /* To player */ - - // Flat in flat container - test ( - dcp::Size (400, 200), - dcp::Size (185, 100), - dcp::Size (1998, 1080), - Crop (0, 0, 0, 0), - Ratio::from_id ("185"), - true, - dcp::Size (185, 100) - ); - - // Scope in flat container - test ( - dcp::Size (400, 200), - dcp::Size (185, 100), - dcp::Size (1998, 1080), - Crop (0, 0, 0, 0), - Ratio::from_id ("239"), - true, - dcp::Size (185, 78) - ); - - // Flat in scope container - test ( - dcp::Size (400, 200), - dcp::Size (239, 100), - dcp::Size (2048, 858), - Crop (0, 0, 0, 0), - Ratio::from_id ("185"), - true, - dcp::Size (185, 100) - ); + VideoContent vc (0); + + vc._sample_aspect_ratio = 2; + + /* Images at full size and in DCP-approved sizes that will not be scaled */ + // Flat/scope content into flat/scope container + vc._size = dcp::Size (1998 / 2, 1080); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), FLAT); + vc._size = dcp::Size (2048 / 2, 858); + BOOST_CHECK_EQUAL (vc.scaled_size(SCOPE), SCOPE); + // 1.33:1 into flat container + vc._size = dcp::Size (1436 / 2, 1080); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(FOUR_TO_THREE)); + // Scope into flat container + vc._size = dcp::Size (2048 / 2, 858); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(1998, 837)); + + /* Smaller images but in the same ratios */ + vc._size = dcp::Size(185, 200); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), FLAT); + vc._size = dcp::Size(955, 800); + BOOST_CHECK_EQUAL (vc.scaled_size(SCOPE), SCOPE); + // 4:3 into flat container + vc._size = dcp::Size(133, 200); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(FOUR_TO_THREE)); + // Scope into flat container + vc._size = dcp::Size(239, 200); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(1998, 836)); + + /* Images at full size that are not DCP-approved but will still remain unscaled */ + vc._size = dcp::Size(600 / 2, 1080); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(600, 1080)); + vc._size = dcp::Size(1700 / 2, 1080); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(1700, 1080)); + + /* Image at full size that is too big for the container and will be shrunk */ + vc._size = dcp::Size(3000 / 2, 1080); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(1998, 719)); } -/* Test no scale */ -BOOST_AUTO_TEST_CASE (video_content_scale_no_scale) + +/* Test VideoContent::scaled_size() with some legacy stuff */ +BOOST_AUTO_TEST_CASE (scaled_size_legacy_test) { - /* No scale where the content is bigger than even the film container */ - test ( - dcp::Size (1920, 1080), - dcp::Size (887, 371), - dcp::Size (2048, 858), - Crop (), - 0, - false, - dcp::Size (659, 371) - ); + { + /* 640x480 content that the user had asked to be stretched to 1.85:1 */ + VideoContent vc (0); + vc._size = dcp::Size(640, 480); + vc._legacy_ratio = Ratio::from_id("185")->ratio(); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), FLAT); + } + + { + /* 640x480 content that the user had asked to be scaled to fit the container, without stretch */ + VideoContent vc (0); + vc._size = dcp::Size(640, 480); + vc._legacy_ratio = 1.33; + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), FOUR_TO_THREE); + } + + { + /* 640x480 content that the user had asked to be kept the same size */ + VideoContent vc (0); + vc._size = dcp::Size(640, 480); + vc._custom_size = dcp::Size(640, 480); + BOOST_CHECK_EQUAL (vc.scaled_size(FLAT), dcp::Size(640, 480)); + } } + -- 2.30.2