summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2020-05-12 20:34:42 +0200
committerCarl Hetherington <cth@carlh.net>2020-05-12 20:34:42 +0200
commit4edc14c8b1410e24f68b510cc14409b96c0338a3 (patch)
tree20669816386ba0cd28d1cef2c4c7836cb47098f5
parent3e96f929fdf740f414b114c5d9765e22fcc46de6 (diff)
parentc6475f24a7b21fe2291ebc809431ecc2654d3355 (diff)
Re-work scaling following excellent insights by Carsten Kurz, described
on #1669. Now the scaling of video content is guessed based on its aspect ratio (taking into account pixel aspect ratio) and there is a "custom" option for overriding incorrectly-marked-up content or content which actually needs its shape to be changed. Essentially we are defaulting to what used to be called "no stretch". This commit also adds buttons to change left/right and top/bottom crop together, and auto-guessing of DCP container size when any change results in there being just one piece of video content in a project. These changes include breaking changes to metadata.xml; old projects should load (with new settings that preserve the project's apperance) but once saved they will not load into 2.14.x. DCP-o-matic saves a backup file (metadata.37.xml) when 2.15.x loads an old project.
-rw-r--r--graphics/link.pngbin0 -> 334 bytes
-rw-r--r--graphics/src/link.svg78
-rwxr-xr-xgraphics/update3
-rw-r--r--graphics/web/favicon-128x128.pngbin25054 -> 25054 bytes
-rw-r--r--graphics/web/favicon-16x16.pngbin1977 -> 1977 bytes
-rw-r--r--graphics/web/favicon-32x32.pngbin3755 -> 3755 bytes
-rw-r--r--graphics/web/favicon-64x64.pngbin9595 -> 9595 bytes
-rw-r--r--src/lib/config.cc12
-rw-r--r--src/lib/config.h9
-rw-r--r--src/lib/create_cli.cc29
-rw-r--r--src/lib/create_cli.h1
-rw-r--r--src/lib/dcp.cc4
-rw-r--r--src/lib/film.cc83
-rw-r--r--src/lib/film.h7
-rw-r--r--src/lib/hints.cc2
-rw-r--r--src/lib/player.cc4
-rw-r--r--src/lib/player.h4
-rw-r--r--src/lib/player_video.cc2
-rw-r--r--src/lib/util.cc19
-rw-r--r--src/lib/util.h1
-rw-r--r--src/lib/video_content.cc141
-rw-r--r--src/lib/video_content.h42
-rw-r--r--src/lib/video_content_scale.cc171
-rw-r--r--src/lib/video_content_scale.h81
-rw-r--r--src/lib/wscript1
-rw-r--r--src/tools/dcpomatic.cc25
-rw-r--r--src/tools/dcpomatic_cli.cc6
-rw-r--r--src/tools/dcpomatic_create.cc9
-rw-r--r--src/wx/content_widget.h19
-rw-r--r--src/wx/custom_scale_dialog.cc142
-rw-r--r--src/wx/custom_scale_dialog.h51
-rw-r--r--src/wx/full_config_dialog.cc35
-rw-r--r--src/wx/timeline_dialog.cc21
-rw-r--r--src/wx/timeline_dialog.h1
-rw-r--r--src/wx/video_panel.cc245
-rw-r--r--src/wx/video_panel.h20
-rw-r--r--src/wx/wscript3
-rw-r--r--src/wx/wx_util.cc23
-rw-r--r--src/wx/wx_util.h2
-rw-r--r--test/4k_test.cc2
-rw-r--r--test/create_cli_test.cc37
m---------test/data0
-rw-r--r--test/empty_test.cc6
-rw-r--r--test/ffmpeg_audio_test.cc2
-rw-r--r--test/ffmpeg_dcp_test.cc2
-rw-r--r--test/isdcf_name_test.cc8
-rw-r--r--test/player_test.cc4
-rw-r--r--test/recover_test.cc6
-rw-r--r--test/repeat_frame_test.cc4
-rw-r--r--test/scaling_test.cc16
-rw-r--r--test/skip_frame_test.cc1
-rw-r--r--test/threed_test.cc2
-rw-r--r--test/video_content_scale_test.cc282
53 files changed, 903 insertions, 765 deletions
diff --git a/graphics/link.png b/graphics/link.png
new file mode 100644
index 000000000..69af402f6
--- /dev/null
+++ b/graphics/link.png
Binary files differ
diff --git a/graphics/src/link.svg b/graphics/src/link.svg
new file mode 100644
index 000000000..bf58ad7de
--- /dev/null
+++ b/graphics/src/link.svg
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="40.736046mm"
+ height="72.459007mm"
+ viewBox="0 0 40.736045 72.459008"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)"
+ sodipodi:docname="link.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="30.0516"
+ inkscape:cy="107.36255"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1680"
+ inkscape:window-height="995"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ fit-margin-top="1"
+ fit-margin-left="1"
+ fit-margin-right="1"
+ fit-margin-bottom="1" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-43.172802,-2.2134689)">
+ <g
+ id="g11"
+ transform="matrix(-3.0676153e-5,-1.0020549,1.0020464,-0.00413633,25.020746,102.13853)"
+ style="stroke-width:0.99795336">
+ <path
+ sodipodi:nodetypes="ccsccccccscscccccsssccc"
+ inkscape:connector-curvature="0"
+ id="rect819"
+ d="m 65.199219,27.601562 0.3125,0.01172 c 0,0 -1.921609,-0.08686 -3.953125,0.625 -2.031517,0.711861 -4.556382,2.227912 -6.824219,5.013672 l 6.205078,5.050781 c 1.370276,-1.683216 2.525799,-2.25443 3.265625,-2.513672 0.739826,-0.259241 0.679688,-0.199218 0.679688,-0.199218 l 0.15625,0.01172 h 19.550781 c 2.172037,0.06924 3.36417,0.821834 4.335937,2.03125 0.973224,1.211229 1.583731,3.040311 1.589844,4.931641 0.0061,1.89133 -0.59167,3.751118 -1.582031,5.015625 -0.986061,1.259016 -2.231578,2.067616 -4.441406,2.205078 h -15.51516 l -3.779762,8 h 19.626953 l 0.11914,-0.0078 c 4.347056,-0.25782 8.013718,-2.360449 10.289063,-5.26564 2.275345,-2.905192 3.294538,-6.465865 3.283203,-9.972657 C 98.506244,39.032271 97.46527,35.48507 95.164062,32.621094 92.862855,29.757118 89.15903,27.737178 84.832031,27.603516 l -0.0625,-0.002 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.98362684;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccscscccccccccccscscccc"
+ inkscape:connector-curvature="0"
+ id="rect819-7"
+ d="m 41.986328,19.101562 -0.117187,0.0059 c -4.347056,0.257804 -8.013718,2.360434 -10.289063,5.265625 -2.275345,2.905191 -3.296491,6.467818 -3.285156,9.974609 0.01133,3.506791 1.054262,7.05204 3.355469,9.916016 2.301207,2.863976 6.005032,4.885869 10.332031,5.019531 l 0.0625,0.002 h 19.570312 l -0.3125,-0.01172 c 0,0 1.921609,0.08491 3.953125,-0.626954 2.031517,-0.711861 4.556382,-2.227911 6.824219,-5.013672 L 65.875,38.582031 c -1.370276,1.683217 -2.525798,2.256384 -3.265625,2.515625 -0.739827,0.259242 -0.681641,0.199219 -0.681641,0.199219 l -0.15625,-0.01172 H 42.220703 c -2.172033,-0.06924 -3.362218,-0.821835 -4.333984,-2.03125 -0.973223,-1.211229 -1.585684,-3.04031 -1.591797,-4.93164 -0.0061,-1.891331 0.59167,-3.751118 1.582031,-5.015625 0.984624,-1.257182 2.229804,-2.06585 4.433594,-2.205079 h 14.957961 l 4.346726,-8 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.98362684;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ </g>
+ </g>
+</svg>
diff --git a/graphics/update b/graphics/update
index 9b75493db..f0a7fd597 100755
--- a/graphics/update
+++ b/graphics/update
@@ -84,6 +84,9 @@ else
$INKSCAPE tick.png src/tick.svg -w 16 -h 16
$INKSCAPE no_tick.png src/no_tick.svg -w 16 -h 16
+ # Link icon
+ $INKSCAPE link.png src/link.svg -w 9 -h 16
+
# favicon
mkdir -p web
convert src/web.png -resize 256x256 -transparent white web/favicon-256x256.png
diff --git a/graphics/web/favicon-128x128.png b/graphics/web/favicon-128x128.png
index 621455641..9330c0cdc 100644
--- a/graphics/web/favicon-128x128.png
+++ b/graphics/web/favicon-128x128.png
Binary files differ
diff --git a/graphics/web/favicon-16x16.png b/graphics/web/favicon-16x16.png
index 4c31c0258..82639fddf 100644
--- a/graphics/web/favicon-16x16.png
+++ b/graphics/web/favicon-16x16.png
Binary files differ
diff --git a/graphics/web/favicon-32x32.png b/graphics/web/favicon-32x32.png
index 847bc813a..e9772da24 100644
--- a/graphics/web/favicon-32x32.png
+++ b/graphics/web/favicon-32x32.png
Binary files differ
diff --git a/graphics/web/favicon-64x64.png b/graphics/web/favicon-64x64.png
index e836814d1..0ff824f40 100644
--- a/graphics/web/favicon-64x64.png
+++ b/graphics/web/favicon-64x64.png
Binary files differ
diff --git a/src/lib/config.cc b/src/lib/config.cc
index ebb6ece93..18955a896 100644
--- a/src/lib/config.cc
+++ b/src/lib/config.cc
@@ -99,7 +99,6 @@ Config::set_defaults ()
_language = optional<string> ();
_default_still_length = 10;
_default_container = Ratio::from_id ("185");
- _default_scale_to = 0;
_default_dcp_content_type = DCPContentType::from_isdcf_name ("FTR");
_default_dcp_audio_channels = 6;
_default_j2k_bandwidth = 150000000;
@@ -309,11 +308,6 @@ try
_default_container = Ratio::from_id ("185");
}
- c = f.optional_string_child ("DefaultScaleTo");
- if (c) {
- _default_scale_to = Ratio::from_id (c.get ());
- }
-
_default_dcp_content_type = DCPContentType::from_isdcf_name(f.optional_string_child("DefaultDCPContentType").get_value_or("FTR"));
_default_dcp_audio_channels = f.optional_number_child<int>("DefaultDCPAudioChannels").get_value_or (6);
@@ -719,12 +713,6 @@ Config::write_config () const
*/
root->add_child("DefaultContainer")->add_child_text (_default_container->id ());
}
- if (_default_scale_to) {
- /* [XML:opt] DefaultScaleTo ID of default ratio to scale content to when creating new films
- (see <code>DefaultContainer</code> for IDs).
- */
- root->add_child("DefaultScaleTo")->add_child_text (_default_scale_to->id ());
- }
if (_default_dcp_content_type) {
/* [XML:opt] DefaultDCPContentType Default content type ot use when creating new films (<code>FTR</code>, <code>SHR</code>,
<code>TLR</code>, <code>TST</code>, <code>XSN</code>, <code>RTG</code>, <code>TSR</code>, <code>POL</code>,
diff --git a/src/lib/config.h b/src/lib/config.h
index f54ca3814..23f7ce0b3 100644
--- a/src/lib/config.h
+++ b/src/lib/config.h
@@ -186,10 +186,6 @@ public:
return _default_container;
}
- Ratio const * default_scale_to () const {
- return _default_scale_to;
- }
-
DCPContentType const * default_dcp_content_type () const {
return _default_dcp_content_type;
}
@@ -686,10 +682,6 @@ public:
maybe_set (_default_container, c);
}
- void set_default_scale_to (Ratio const * c) {
- maybe_set (_default_scale_to, c);
- }
-
void set_default_dcp_content_type (DCPContentType const * t) {
maybe_set (_default_dcp_content_type, t);
}
@@ -1233,7 +1225,6 @@ private:
/** Default length of still image content (seconds) */
int _default_still_length;
Ratio const * _default_container;
- Ratio const * _default_scale_to;
DCPContentType const * _default_dcp_content_type;
int _default_dcp_audio_channels;
std::string _dcp_issuer;
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 <type> FTR, SHR, TLR, TST, XSN, RTG, TSR, POL, PSA or ADV\n"
" -f, --dcp-frame-rate <rate> set DCP video frame rate (otherwise guessed from content)\n"
" --container-ratio <ratio> 119, 133, 137, 138, 166, 178, 185 or 239\n"
- " --content-ratio <ratio> 119, 133, 137, 138, 166, 178, 185 or 239\n"
" -s, --still-length <n> number of seconds that still content should last\n"
" --standard <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<int> 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/dcp.cc b/src/lib/dcp.cc
index c62b339fa..477b61e9f 100644
--- a/src/lib/dcp.cc
+++ b/src/lib/dcp.cc
@@ -75,9 +75,9 @@ DCP::cpls () const
list<dcp::VerificationNote> notes;
dcp->read (&notes, true);
if (!_tolerant) {
- /** We accept and ignore EmptyAssetPathError but everything else is bad */
+ /** We accept and ignore EMPTY_ASSET_PATH and EXTERNAL_ASSET but everything else is bad */
BOOST_FOREACH (dcp::VerificationNote j, notes) {
- if (j.code() == dcp::VerificationNote::EMPTY_ASSET_PATH) {
+ if (j.code() == dcp::VerificationNote::EMPTY_ASSET_PATH || j.code() == dcp::VerificationNote::EXTERNAL_ASSET) {
LOG_WARNING("Empty path in ASSETMAP of %1", i.string());
} else {
boost::throw_exception(dcp::ReadError(dcp::note_to_string(j)));
diff --git a/src/lib/film.cc b/src/lib/film.cc
index b233e5ee6..2f631bd89 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.
*
@@ -162,6 +164,8 @@ Film::Film (optional<boost::filesystem::path> dir)
, _upload_after_make_dcp (Config::instance()->default_upload_after_make_dcp())
, _reencode_j2k (false)
, _user_explicit_video_frame_rate (false)
+ , _user_explicit_container (false)
+ , _user_explicit_resolution (false)
, _state_version (current_state_version)
, _dirty (false)
, _tolerant (false)
@@ -464,6 +468,8 @@ Film::metadata (bool with_content_paths) const
i.as_xml (root->add_child("Rating"));
}
root->add_child("ContentVersion")->add_child_text(_content_version);
+ root->add_child("UserExplicitContainer")->add_child_text(_user_explicit_container ? "1" : "0");
+ root->add_child("UserExplicitResolution")->add_child_text(_user_explicit_resolution ? "1" : "0");
_playlist->as_xml (root->add_child ("Playlist"), with_content_paths);
return doc;
@@ -613,6 +619,10 @@ Film::read_metadata (optional<boost::filesystem::path> path)
_content_version = f.optional_string_child("ContentVersion").get_value_or("");
+ /* Disable guessing for files made in previous DCP-o-matic versions */
+ _user_explicit_container = f.optional_bool_child("UserExplicitContainer").get_value_or(true);
+ _user_explicit_resolution = f.optional_bool_child("UserExplicitResolution").get_value_or(true);
+
list<string> notes;
_playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes);
@@ -787,11 +797,7 @@ Film::isdcf_name (bool if_created_now) const
BOOST_FOREACH (shared_ptr<Content> 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;
}
}
@@ -971,20 +977,39 @@ Film::set_dcp_content_type (DCPContentType const * t)
_dcp_content_type = t;
}
+
+/** @param explicit_user true if this is being set because of
+ * a direct user request, false if it is being done because
+ * DCP-o-matic is guessing the best container to use.
+ */
void
-Film::set_container (Ratio const * c)
+Film::set_container (Ratio const * c, bool explicit_user)
{
ChangeSignaller<Film> ch (this, CONTAINER);
_container = c;
+
+ if (explicit_user) {
+ _user_explicit_container = true;
+ }
}
+
+/** @param explicit_user true if this is being set because of
+ * a direct user request, false if it is being done because
+ * DCP-o-matic is guessing the best resolution to use.
+ */
void
-Film::set_resolution (Resolution r)
+Film::set_resolution (Resolution r, bool explicit_user)
{
ChangeSignaller<Film> ch (this, RESOLUTION);
_resolution = r;
+
+ if (explicit_user) {
+ _user_explicit_resolution = true;
+ }
}
+
void
Film::set_j2k_bandwidth (int b)
{
@@ -1269,12 +1294,54 @@ Film::add_content (shared_ptr<Content> c)
}
_playlist->add (shared_from_this(), c);
+
+ maybe_set_container_and_resolution ();
+}
+
+
+void
+Film::maybe_set_container_and_resolution ()
+{
+ /* Get the only piece of video content, if there is only one */
+ shared_ptr<VideoContent> video;
+ BOOST_FOREACH (shared_ptr<const Content> i, _playlist->content()) {
+ if (i->video) {
+ if (!video) {
+ video = i->video;
+ } else {
+ video.reset ();
+ }
+ }
+ }
+
+ if (video) {
+ /* This is the only piece of video content in this Film. Use it to make a guess for
+ * DCP container size and resolution, unless the user has already explicitly set these
+ * things.
+ */
+ if (!_user_explicit_container) {
+ if (video->size().ratio() > 2.3) {
+ set_container (Ratio::from_id("239"), false);
+ } else {
+ set_container (Ratio::from_id("185"), false);
+ }
+ }
+
+ if (!_user_explicit_resolution) {
+ if (video->size_after_crop().width > 2048 || video->size_after_crop().height > 1080) {
+ set_resolution (RESOLUTION_4K, false);
+ } else {
+ set_resolution (RESOLUTION_2K, false);
+ }
+ }
+ }
}
void
Film::remove_content (shared_ptr<Content> c)
{
_playlist->remove (c);
+ maybe_set_container_and_resolution ();
}
void
diff --git a/src/lib/film.h b/src/lib/film.h
index 40d366f8f..b03b0258e 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -351,8 +351,8 @@ public:
void move_content_earlier (boost::shared_ptr<Content>);
void move_content_later (boost::shared_ptr<Content>);
void set_dcp_content_type (DCPContentType const *);
- void set_container (Ratio const *);
- void set_resolution (Resolution);
+ void set_container (Ratio const *, bool user_explicit = true);
+ void set_resolution (Resolution, bool user_explicit = true);
void set_signed (bool);
void set_encrypted (bool);
void set_key (dcp::Key key);
@@ -409,6 +409,7 @@ private:
void maybe_add_content (boost::weak_ptr<Job>, boost::weak_ptr<Content>, bool disable_audio_analysis);
void audio_analysis_finished ();
void check_settings_consistency ();
+ void maybe_set_container_and_resolution ();
static std::string const metadata_file;
@@ -462,6 +463,8 @@ private:
bool _reencode_j2k;
/** true if the user has ever explicitly set the video frame rate of this film */
bool _user_explicit_video_frame_rate;
+ bool _user_explicit_container;
+ bool _user_explicit_resolution;
std::map<dcp::Marker, dcpomatic::DCPTime> _markers;
std::vector<dcp::Rating> _ratings;
std::string _content_version;
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<const Content> 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<Piece> 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<int> _suspended;
std::list<boost::shared_ptr<Piece> > _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<Image> _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<const Film> 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<dcp::CertificateChain> read_swaroop_chain (boost::filesystem::path path);
extern void write_swaroop_chain (boost::shared_ptr<const dcp::CertificateChain> chain, boost::filesystem::path output);
#endif
+extern dcp::Size scale_for_display (dcp::Size s, dcp::Size display_container, dcp::Size film_container);
template <class T>
std::list<T>
diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc
index 685336367..b4ad30f70 100644
--- a/src/lib/video_content.cc
+++ b/src/lib/video_content.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2020 Carl Hetherington <cth@carlh.net>
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<string> 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<string> ratio = node->node_child("Scale")->optional_string_child("Ratio");
+ if (ratio) {
+ _legacy_ratio = Ratio::from_id(ratio.get())->ratio();
+ }
+ optional<bool> 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<float>("CustomRatio");
+ if (node->optional_number_child<int>("CustomWidth")) {
+ _custom_size = dcp::Size (node->number_child<int>("CustomWidth"), node->number_child<int>("CustomHeight"));
+ }
}
if (node->optional_node_child ("ColourConversion")) {
@@ -190,8 +210,12 @@ VideoContent::VideoContent (Content* parent, vector<shared_ptr<Content> > 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<shared_ptr<Content> > 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<string> (_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<string>(*_custom_ratio));
+ }
+ if (_custom_size) {
+ node->add_child("CustomWidth")->add_child_text(raw_convert<string>(_custom_size->width));
+ node->add_child("CustomHeight")->add_child_text(raw_convert<string>(_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<VideoExaminer> 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
@@ -354,29 +377,6 @@ VideoContent::size_after_crop () const
return crop().apply (size_after_3d_split ());
}
-void
-VideoContent::scale_and_crop_to_fit_width (shared_ptr<const Film> film)
-{
- set_scale (VideoContentScale(film->container()));
-
- int const crop = max (0, int (size().height - double (film->frame_size().height) * size().width / film->frame_size().width));
- set_left_crop (0);
- set_right_crop (0);
- set_top_crop (crop / 2);
- set_bottom_crop (crop / 2);
-}
-
-void
-VideoContent::scale_and_crop_to_fit_height (shared_ptr<const Film> film)
-{
- set_scale (VideoContentScale(film->container()));
-
- int const crop = max (0, int (size().width - double (film->frame_size().width) * size().height / film->frame_size().height));
- set_left_crop (crop / 2);
- set_right_crop (crop / 2);
- set_top_crop (0);
- set_bottom_crop (0);
-}
/** @param f Frame index within the whole (untrimmed) content.
* @return Fade factor (between 0 and 1) or unset if there is no fade.
@@ -402,7 +402,7 @@ VideoContent::fade (shared_ptr<const Film> film, Frame f) const
}
string
-VideoContent::processing_description (shared_ptr<const Film> film) const
+VideoContent::processing_description (shared_ptr<const Film> film)
{
string d;
char buffer[256];
@@ -439,7 +439,7 @@ VideoContent::processing_description (shared_ptr<const Film> 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 (
@@ -512,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)
@@ -574,7 +569,8 @@ VideoContent::take_settings_from (shared_ptr<const VideoContent> 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);
}
@@ -592,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<float>();
+ return fit_ratio_within(*_custom_ratio, film_container);
+ }
+ _legacy_ratio = 0;
+ }
+
+ return auto_size;
+}
+
+
+void
+VideoContent::set_custom_ratio (optional<float> ratio)
+{
+ maybe_set (_custom_ratio, ratio, VideoContentProperty::CUSTOM_RATIO);
+}
+
+
+void
+VideoContent::set_custom_size (optional<dcp::Size> size)
+{
+ maybe_set (_custom_size, size, VideoContentProperty::CUSTOM_SIZE);
+}
diff --git a/src/lib/video_content.h b/src/lib/video_content.h
index 37223c457..b478666bb 100644
--- a/src/lib/video_content.h
+++ b/src/lib/video_content.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2020 Carl Hetherington <cth@carlh.net>
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<VideoContent>
@@ -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<float> ratio);
+ void set_custom_size (boost::optional<dcp::Size> 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<float> custom_ratio () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _custom_ratio;
+ }
+
+
+ boost::optional<dcp::Size> custom_size () const {
boost::mutex::scoped_lock lm (_mutex);
- return _scale;
+ return _custom_size;
}
+
boost::optional<ColourConversion> colour_conversion () const {
boost::mutex::scoped_lock lm (_mutex);
return _colour_conversion;
@@ -168,15 +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<double> fade (boost::shared_ptr<const Film> film, Frame) const;
- void scale_and_crop_to_fit_width (boost::shared_ptr<const Film> film);
- void scale_and_crop_to_fit_height (boost::shared_ptr<const Film> film);
-
- std::string processing_description (boost::shared_ptr<const Film> film) const;
+ std::string processing_description (boost::shared_ptr<const Film> film);
void set_length (Frame);
@@ -194,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 ();
@@ -204,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<float> _custom_ratio;
+ /** size to scale cropped image to; only used if _custom_ratio is none */
+ boost::optional<dcp::Size> _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<float> _legacy_ratio;
/** Sample aspect ratio obtained from the content file's header, if there is one */
boost::optional<double> _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 <cth@carlh.net>
-
- 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 <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "video_content_scale.h"
-#include "video_content.h"
-#include "ratio.h"
-#include "util.h"
-#include <libcxml/cxml.h>
-#include <libxml++/libxml++.h>
-#include <boost/optional.hpp>
-#include <iostream>
-
-#include "i18n.h"
-
-using std::vector;
-using std::string;
-using std::min;
-using std::cout;
-using boost::shared_ptr;
-using boost::optional;
-
-vector<VideoContentScale> 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<cxml::Node> node)
- : _ratio (0)
- , _scale (true)
-{
- optional<string> 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<const VideoContent> 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<Ratio const *> ratios = Ratio::all ();
- for (vector<Ratio const *>::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 <cth@carlh.net>
-
- 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 <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef DCPOMATIC_VIDEO_CONTENT_SCALE_H
-#define DCPOMATIC_VIDEO_CONTENT_SCALE_H
-
-#include <dcp/util.h>
-#include <boost/shared_ptr.hpp>
-#include <vector>
-
-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<cxml::Node>);
-
- dcp::Size size (boost::shared_ptr<const VideoContent>, 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<VideoContentScale> 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<VideoContentScale> _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.cc b/src/tools/dcpomatic.cc
index f69ab5a6a..13569d11d 100644
--- a/src/tools/dcpomatic.cc
+++ b/src/tools/dcpomatic.cc
@@ -222,8 +222,6 @@ enum {
ID_file_close = 100,
ID_edit_copy,
ID_edit_paste,
- ID_content_scale_to_fit_width,
- ID_content_scale_to_fit_height,
ID_jobs_make_dcp,
ID_jobs_make_dcp_batch,
ID_jobs_make_kdms,
@@ -316,8 +314,6 @@ public:
Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_copy, this), ID_edit_copy);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_paste, this), ID_edit_paste);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_preferences, this), wxID_PREFERENCES);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::content_scale_to_fit_width, this), ID_content_scale_to_fit_width);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::content_scale_to_fit_height, this), ID_content_scale_to_fit_height);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_dcp, this), ID_jobs_make_dcp);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_kdms, this), ID_jobs_make_kdms);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_dkdms, this), ID_jobs_make_dkdms);
@@ -983,22 +979,6 @@ private:
d->Destroy ();
}
- void content_scale_to_fit_width ()
- {
- ContentList vc = _film_editor->content_panel()->selected_video ();
- for (ContentList::iterator i = vc.begin(); i != vc.end(); ++i) {
- (*i)->video->scale_and_crop_to_fit_width (_film);
- }
- }
-
- void content_scale_to_fit_height ()
- {
- ContentList vc = _film_editor->content_panel()->selected_video ();
- for (ContentList::iterator i = vc.begin(); i != vc.end(); ++i) {
- (*i)->video->scale_and_crop_to_fit_height (_film);
- }
- }
-
void jobs_send_dcp_to_tms ()
{
_film->send_dcp_to_tms ();
@@ -1323,10 +1303,6 @@ private:
add_item (edit, _("&Preferences...\tCtrl-P"), wxID_PREFERENCES, ALWAYS);
#endif
- wxMenu* content = new wxMenu;
- add_item (content, _("Scale to fit &width"), ID_content_scale_to_fit_width, NEEDS_FILM | NEEDS_SELECTED_VIDEO_CONTENT);
- add_item (content, _("Scale to fit &height"), ID_content_scale_to_fit_height, NEEDS_FILM | NEEDS_SELECTED_VIDEO_CONTENT);
-
wxMenu* jobs_menu = new wxMenu;
add_item (jobs_menu, _("&Make DCP\tCtrl-M"), ID_jobs_make_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION);
add_item (jobs_menu, _("Make DCP in &batch converter\tCtrl-B"), ID_jobs_make_dcp_batch, NEEDS_FILM | NOT_DURING_DCP_CREATION);
@@ -1365,7 +1341,6 @@ private:
m->Append (_file_menu, _("&File"));
m->Append (edit, _("&Edit"));
- m->Append (content, _("&Content"));
m->Append (jobs_menu, _("&Jobs"));
m->Append (view, _("&View"));
m->Append (tools, _("&Tools"));
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> 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..857359117 100644
--- a/src/tools/dcpomatic_create.cc
+++ b/src/tools/dcpomatic_create.cc
@@ -96,14 +96,18 @@ main (int argc, char* argv[])
}
film->set_name (cc.name);
- film->set_container (cc.container_ratio);
+ if (cc.container_ratio) {
+ film->set_container (cc.container_ratio);
+ }
film->set_dcp_content_type (cc.dcp_content_type);
film->set_interop (cc.standard == dcp::INTEROP);
film->set_use_isdcf_name (!cc.no_use_isdcf_name);
film->set_signed (!cc.no_sign);
film->set_encrypted (cc.encrypt);
film->set_three_d (cc.threed);
- film->set_resolution (cc.fourk ? RESOLUTION_4K : RESOLUTION_2K);
+ if (cc.fourk) {
+ film->set_resolution (RESOLUTION_4K);
+ }
if (cc.j2k_bandwidth) {
film->set_j2k_bandwidth (*cc.j2k_bandwidth);
}
@@ -131,7 +135,6 @@ main (int argc, char* argv[])
BOOST_FOREACH (shared_ptr<Content> 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/content_widget.h b/src/wx/content_widget.h
index c4ae4d591..de7ebedc5 100644
--- a/src/wx/content_widget.h
+++ b/src/wx/content_widget.h
@@ -52,6 +52,7 @@ public:
* @param part Part of Content that the property is in (e.g. &Content::video)
* @param model_getter Function on the Content to get the value.
* @param model_setter Function on the Content to set the value.
+ * @param view_changed Function called when the view has changed; useful for linking controls.
* @param view_to_model Function to convert a view value to a model value.
* @param model_to_view Function to convert a model value to a view value.
*/
@@ -62,6 +63,7 @@ public:
boost::function<boost::shared_ptr<S> (Content*)> part,
boost::function<U (S*)> model_getter,
boost::function<void (S*, U)> model_setter,
+ boost::function<void ()> view_changed,
boost::function<U (V)> view_to_model,
boost::function<V (U)> model_to_view
)
@@ -72,6 +74,7 @@ public:
, _part (part)
, _model_getter (model_getter)
, _model_setter (model_setter)
+ , _view_changed (view_changed)
, _view_to_model (view_to_model)
, _model_to_view (model_to_view)
, _ignore_model_changes (false)
@@ -146,6 +149,9 @@ public:
for (size_t i = 0; i < _content.size(); ++i) {
boost::bind (_model_setter, _part (_content[i].get()).get(), _view_to_model (wx_get (_wrapped))) ();
}
+ if (_view_changed) {
+ _view_changed ();
+ }
_ignore_model_changes = false;
}
@@ -207,6 +213,7 @@ private:
boost::function<boost::shared_ptr<S> (Content *)> _part;
boost::function<U (S*)> _model_getter;
boost::function<void (S*, U)> _model_setter;
+ boost::function<void ()> _view_changed;
boost::function<U (V)> _view_to_model;
boost::function<V (U)> _model_to_view;
std::list<boost::signals2::connection> _connections;
@@ -229,7 +236,8 @@ public:
int property,
boost::function<boost::shared_ptr<S> (Content *)> part,
boost::function<int (S*)> getter,
- boost::function<void (S*, int)> setter
+ boost::function<void (S*, int)> setter,
+ boost::function<void ()> view_changed = boost::function<void ()>()
)
: ContentWidget<S, wxSpinCtrl, int, int> (
parent,
@@ -237,6 +245,7 @@ public:
property,
part,
getter, setter,
+ view_changed,
&caster<int, int>,
&caster<int, int>
)
@@ -255,7 +264,8 @@ public:
int property,
boost::function<boost::shared_ptr<S> (Content *)> part,
boost::function<double (S*)> getter,
- boost::function<void (S*, double)> setter
+ boost::function<void (S*, double)> setter,
+ boost::function<void ()> view_changed = boost::function<void ()>()
)
: ContentWidget<S, wxSpinCtrlDouble, double, double> (
parent,
@@ -263,6 +273,7 @@ public:
property,
part,
getter, setter,
+ view_changed,
&caster<double, double>,
&caster<double, double>
)
@@ -283,7 +294,8 @@ public:
boost::function<U (S*)> getter,
boost::function<void (S*, U)> setter,
boost::function<U (int)> view_to_model,
- boost::function<int (U)> model_to_view
+ boost::function<int (U)> model_to_view,
+ boost::function<void ()> view_changed = boost::function<void()>()
)
: ContentWidget<S, wxChoice, U, int> (
parent,
@@ -292,6 +304,7 @@ public:
part,
getter,
setter,
+ view_changed,
view_to_model,
model_to_view
)
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 <cth@carlh.net>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "custom_scale_dialog.h"
+#include "wx_util.h"
+#include "lib/util.h"
+#include <dcp/raw_convert.h>
+#include <wx/wx.h>
+#include <wx/propgrid/property.h>
+#include <wx/propgrid/props.h>
+
+
+using boost::optional;
+using namespace dcp;
+
+
+CustomScaleDialog::CustomScaleDialog (wxWindow* parent, dcp::Size initial, dcp::Size film_container, optional<float> custom_ratio, optional<dcp::Size> 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<float>(wx_to_std(_ratio->GetValue())), _film_container);
+ _size_from_ratio->SetLabelMarkup (wxString::Format("<i>%dx%d</i>", 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("<i>%.2f:1</i>", 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<float>
+CustomScaleDialog::custom_ratio () const
+{
+ if (!_ratio_to_fit->GetValue()) {
+ return optional<float>();
+ }
+
+ return raw_convert<float>(wx_to_std(_ratio->GetValue()));
+}
+
+
+optional<dcp::Size>
+CustomScaleDialog::custom_size () const
+{
+ if (!_size->GetValue()) {
+ return optional<dcp::Size>();
+ }
+
+ 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 <cth@carlh.net>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "table_dialog.h"
+#include <dcp/types.h>
+#include <wx/wx.h>
+#include <wx/spinctrl.h>
+
+
+class CustomScaleDialog : public TableDialog
+{
+public:
+ CustomScaleDialog (wxWindow* parent, dcp::Size initial, dcp::Size film_container, boost::optional<float> custom_ratio, boost::optional<dcp::Size> custom_size);
+
+ boost::optional<float> custom_ratio () const;
+ boost::optional<dcp::Size> 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/full_config_dialog.cc b/src/wx/full_config_dialog.cc
index 370ec35a1..fff0d2035 100644
--- a/src/wx/full_config_dialog.cc
+++ b/src/wx/full_config_dialog.cc
@@ -340,10 +340,6 @@ private:
_container = new wxChoice (_panel, wxID_ANY);
table->Add (_container);
- add_label_to_sizer (table, _panel, _("Default scale-to"), true);
- _scale_to = new wxChoice (_panel, wxID_ANY);
- table->Add (_scale_to);
-
add_label_to_sizer (table, _panel, _("Default content type"), true);
_dcp_content_type = new wxChoice (_panel, wxID_ANY);
table->Add (_dcp_content_type);
@@ -400,14 +396,6 @@ private:
_container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
- _scale_to->Append (_("Guess from content"));
-
- BOOST_FOREACH (Ratio const * i, Ratio::all()) {
- _scale_to->Append (std_to_wx(i->image_nickname()));
- }
-
- _scale_to->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::scale_to_changed, this));
-
BOOST_FOREACH (DCPContentType const * i, DCPContentType::all()) {
_dcp_content_type->Append (std_to_wx (i->pretty_name ()));
}
@@ -441,17 +429,6 @@ private:
}
}
- vector<Ratio const *> ratios = Ratio::all ();
- for (size_t i = 0; i < ratios.size(); ++i) {
- if (ratios[i] == config->default_scale_to ()) {
- _scale_to->SetSelection (i + 1);
- }
- }
-
- if (!config->default_scale_to()) {
- _scale_to->SetSelection (0);
- }
-
vector<DCPContentType const *> const ct = DCPContentType::all ();
for (size_t i = 0; i < ct.size(); ++i) {
if (ct[i] == config->default_dcp_content_type ()) {
@@ -519,17 +496,6 @@ private:
Config::instance()->set_default_container (ratio[_container->GetSelection()]);
}
- void scale_to_changed ()
- {
- int const s = _scale_to->GetSelection ();
- if (s == 0) {
- Config::instance()->set_default_scale_to (0);
- } else {
- vector<Ratio const *> ratio = Ratio::all ();
- Config::instance()->set_default_scale_to (ratio[s - 1]);
- }
- }
-
void dcp_content_type_changed ()
{
vector<DCPContentType const *> ct = DCPContentType::all ();
@@ -558,7 +524,6 @@ private:
wxDirPickerCtrl* _kdm_directory;
#endif
wxChoice* _container;
- wxChoice* _scale_to;
wxChoice* _dcp_content_type;
wxChoice* _dcp_audio_channels;
wxChoice* _standard;
diff --git a/src/wx/timeline_dialog.cc b/src/wx/timeline_dialog.cc
index 3a720cfec..0d0d4f9f9 100644
--- a/src/wx/timeline_dialog.cc
+++ b/src/wx/timeline_dialog.cc
@@ -93,27 +93,6 @@ TimelineDialog::TimelineDialog (ContentPanel* cp, shared_ptr<Film> film, weak_pt
_film_changed_connection = film->Change.connect (bind (&TimelineDialog::film_change, this, _1, _2));
}
-wxString
-TimelineDialog::bitmap_path (string name)
-{
- boost::filesystem::path base;
-
-#ifdef DCPOMATIC_DEBUG
- /* Hack to allow OS X to find icons when running from the source tree */
- char* path = getenv ("DCPOMATIC_GRAPHICS");
- if (path) {
- base = path;
- } else {
- base = shared_path();
- }
-#else
- base = shared_path();
-#endif
-
- boost::filesystem::path p = base / String::compose("%1.png", name);
- return std_to_wx (p.string());
-}
-
void
TimelineDialog::film_change (ChangeType type, Film::Property p)
{
diff --git a/src/wx/timeline_dialog.h b/src/wx/timeline_dialog.h
index 62649a5f2..77dfede50 100644
--- a/src/wx/timeline_dialog.h
+++ b/src/wx/timeline_dialog.h
@@ -35,7 +35,6 @@ public:
private:
void film_change (ChangeType type, Film::Property);
void tool_clicked (wxCommandEvent& id);
- wxString bitmap_path (std::string name);
boost::weak_ptr<Film> _film;
Timeline _timeline;
diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc
index 992ddf115..24099e1cc 100644
--- a/src/wx/video_panel.cc
+++ b/src/wx/video_panel.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
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"
@@ -37,6 +38,7 @@
#include "lib/dcp_content.h"
#include "lib/video_content.h"
#include <wx/spinctrl.h>
+#include <wx/tglbtn.h>
#include <boost/foreach.hpp>
#include <boost/unordered_set.hpp>
#include <boost/functional/hash.hpp>
@@ -55,27 +57,6 @@ using boost::bind;
using boost::optional;
using namespace dcpomatic;
-static VideoContentScale
-index_to_scale (int n)
-{
- vector<VideoContentScale> scales = VideoContentScale::all ();
- DCPOMATIC_ASSERT (n >= 0);
- DCPOMATIC_ASSERT (n < int (scales.size ()));
- return scales[n];
-}
-
-static int
-scale_to_index (VideoContentScale scale)
-{
- vector<VideoContentScale> 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"))
@@ -102,44 +83,59 @@ VideoPanel::VideoPanel (ContentPanel* p)
&caster<VideoFrameType, int>
);
- _left_crop_label = create_label (this, _("Left crop"), true);
+ _crop_label = create_label (this, _("Crop"), true);
+
+ int const crop_width = 56;
+ int const link_height = 28;
+
+ _left_crop_label = create_label (this, _("Left"), true);
_left_crop = new ContentSpinCtrl<VideoContent> (
this,
- new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)),
+ new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(crop_width, -1)),
VideoContentProperty::CROP,
&Content::video,
boost::mem_fn (&VideoContent::left_crop),
- boost::mem_fn (&VideoContent::set_left_crop)
+ boost::mem_fn (&VideoContent::set_left_crop),
+ boost::bind (&VideoPanel::left_crop_changed, this)
);
- _right_crop_label = create_label (this, _("Right crop"), true);
+ _left_right_link = new wxToggleButton (this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(22, link_height));
+ _left_right_link->SetBitmap (wxBitmap(bitmap_path("link"), wxBITMAP_TYPE_PNG));
+
+ _right_crop_label = create_label (this, _("Right"), true);
_right_crop = new ContentSpinCtrl<VideoContent> (
this,
- new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)),
+ new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(crop_width, -1)),
VideoContentProperty::CROP,
&Content::video,
boost::mem_fn (&VideoContent::right_crop),
- boost::mem_fn (&VideoContent::set_right_crop)
+ boost::mem_fn (&VideoContent::set_right_crop),
+ boost::bind (&VideoPanel::right_crop_changed, this)
);
- _top_crop_label = create_label (this, _("Top crop"), true);
+ _top_crop_label = create_label (this, _("Top"), true);
_top_crop = new ContentSpinCtrl<VideoContent> (
this,
- new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)),
+ new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(crop_width, -1)),
VideoContentProperty::CROP,
&Content::video,
boost::mem_fn (&VideoContent::top_crop),
- boost::mem_fn (&VideoContent::set_top_crop)
+ boost::mem_fn (&VideoContent::set_top_crop),
+ boost::bind (&VideoPanel::top_crop_changed, this)
);
- _bottom_crop_label = create_label (this, _("Bottom crop"), true);
+ _top_bottom_link = new wxToggleButton (this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(22, link_height));
+ _top_bottom_link->SetBitmap (wxBitmap(bitmap_path("link"), wxBITMAP_TYPE_PNG));
+
+ _bottom_crop_label = create_label (this, _("Bottom"), true);
_bottom_crop = new ContentSpinCtrl<VideoContent> (
this,
- new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)),
+ new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(crop_width, -1)),
VideoContentProperty::CROP,
&Content::video,
boost::mem_fn (&VideoContent::bottom_crop),
- boost::mem_fn (&VideoContent::set_bottom_crop)
+ boost::mem_fn (&VideoContent::set_bottom_crop),
+ boost::bind (&VideoPanel::bottom_crop_changed, this)
);
_fade_in_label = create_label (this, _("Fade in"), true);
@@ -148,22 +144,15 @@ VideoPanel::VideoPanel (ContentPanel* p)
_fade_out_label = create_label (this, _("Fade out"), true);
_fade_out = new Timecode<ContentTime> (this);
- _scale_to_label = create_label (this, _("Scale to"), true);
- _scale = new ContentChoice<VideoContent, VideoContentScale> (
- 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..."));
@@ -192,11 +181,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"));
@@ -213,9 +197,14 @@ 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));
+ _left_right_link->Bind (wxEVT_TOGGLEBUTTON, boost::bind(&VideoPanel::left_right_link_clicked, this));
+ _top_bottom_link->Bind (wxEVT_TOGGLEBUTTON, boost::bind(&VideoPanel::top_bottom_link_clicked, this));
add_to_grid ();
}
@@ -250,18 +239,23 @@ VideoPanel::add_to_grid ()
wxGridBagSizer* crop = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
add_label_to_sizer (crop, _left_crop_label, true, wxGBPosition (cr, 0));
_left_crop->add (crop, wxGBPosition (cr, 1));
- add_label_to_sizer (crop, _right_crop_label, true, wxGBPosition (cr, 2));
- _right_crop->add (crop, wxGBPosition (cr, 3));
+ crop->Add (_left_right_link, wxGBPosition(cr, 2));
+ add_label_to_sizer (crop, _right_crop_label, true, wxGBPosition (cr, 3));
+ _right_crop->add (crop, wxGBPosition (cr, 4));
++cr;
add_label_to_sizer (crop, _top_crop_label, true, wxGBPosition (cr, 0));
_top_crop->add (crop, wxGBPosition (cr, 1));
- add_label_to_sizer (crop, _bottom_crop_label, true, wxGBPosition (cr, 2));
- _bottom_crop->add (crop, wxGBPosition (cr, 3));
- _grid->Add (crop, wxGBPosition (r, 0), wxGBSpan (2, 4));
- r += 2;
+ crop->Add (_top_bottom_link, wxGBPosition(cr, 2));
+ add_label_to_sizer (crop, _bottom_crop_label, true, wxGBPosition (cr, 3));
+ _bottom_crop->add (crop, wxGBPosition (cr, 4));
+ add_label_to_sizer (_grid, _crop_label, true, wxGBPosition(r, 0));
+ _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);
@@ -280,8 +274,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));
@@ -483,6 +485,20 @@ VideoPanel::film_content_changed (int property)
}
setup_sensitivity ();
+ } else if (property == VideoContentProperty::CUSTOM_RATIO || property == VideoContentProperty::CUSTOM_SIZE) {
+ set<Frame> check;
+ BOOST_FOREACH (shared_ptr<const Content> 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 ();
}
}
@@ -573,7 +589,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);
@@ -582,6 +597,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);
@@ -620,7 +637,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);
@@ -638,7 +657,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 ());
@@ -700,3 +721,99 @@ VideoPanel::reference_clicked ()
d->set_reference_video (_reference->GetValue ());
}
+
+
+void
+VideoPanel::scale_fit_clicked ()
+{
+ BOOST_FOREACH (shared_ptr<Content> i, _parent->selected_video()) {
+ i->video->set_custom_ratio (optional<float>());
+ }
+}
+
+
+void
+VideoPanel::scale_custom_clicked ()
+{
+ if (!scale_custom_edit_clicked()) {
+ _scale_fit->SetValue (true);
+ }
+}
+
+
+bool
+VideoPanel::scale_custom_edit_clicked ()
+{
+ shared_ptr<const VideoContent> 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<Content> 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;
+}
+
+
+void
+VideoPanel::left_right_link_clicked ()
+{
+ right_crop_changed ();
+}
+
+
+void
+VideoPanel::top_bottom_link_clicked ()
+{
+ bottom_crop_changed ();
+}
+
+
+void
+VideoPanel::left_crop_changed ()
+{
+ if (_left_right_link->GetValue()) {
+ BOOST_FOREACH (shared_ptr<Content> i, _parent->selected_video()) {
+ i->video->set_right_crop (i->video->left_crop());
+ }
+ }
+}
+
+
+void
+VideoPanel::right_crop_changed ()
+{
+ if (_left_right_link->GetValue()) {
+ BOOST_FOREACH (shared_ptr<Content> i, _parent->selected_video()) {
+ i->video->set_left_crop (i->video->right_crop());
+ }
+ }
+}
+
+
+void
+VideoPanel::top_crop_changed ()
+{
+ if (_top_bottom_link->GetValue()) {
+ BOOST_FOREACH (shared_ptr<Content> i, _parent->selected_video()) {
+ i->video->set_bottom_crop (i->video->top_crop());
+ }
+ }
+}
+
+
+void
+VideoPanel::bottom_crop_changed ()
+{
+ if (_top_bottom_link->GetValue()) {
+ BOOST_FOREACH (shared_ptr<Content> i, _parent->selected_video()) {
+ i->video->set_top_crop (i->video->bottom_crop());
+ }
+ }
+}
+
+
+
diff --git a/src/wx/video_panel.h b/src/wx/video_panel.h
index ad0ba402a..31aeed2e1 100644
--- a/src/wx/video_panel.h
+++ b/src/wx/video_panel.h
@@ -25,13 +25,13 @@
#include "content_sub_panel.h"
#include "content_widget.h"
#include "timecode.h"
-#include "lib/video_content_scale.h"
#include "lib/film.h"
class wxChoice;
class wxStaticText;
class wxSpinCtrl;
class wxButton;
+class wxToggleButton;
/** @class VideoPanel
* @brief The video tab of the film editor.
@@ -55,6 +55,15 @@ 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 left_right_link_clicked ();
+ void top_bottom_link_clicked ();
+ void left_crop_changed ();
+ void right_crop_changed ();
+ void top_crop_changed ();
+ void bottom_crop_changed ();
void setup_description ();
void setup_sensitivity ();
@@ -64,20 +73,25 @@ private:
wxCheckBox* _use;
wxStaticText* _type_label;
ContentChoice<VideoContent, VideoFrameType>* _frame_type;
+ wxStaticText* _crop_label;
wxStaticText* _left_crop_label;
ContentSpinCtrl<VideoContent>* _left_crop;
+ wxToggleButton* _left_right_link;
wxStaticText* _right_crop_label;
ContentSpinCtrl<VideoContent>* _right_crop;
wxStaticText* _top_crop_label;
ContentSpinCtrl<VideoContent>* _top_crop;
+ wxToggleButton* _top_bottom_link;
wxStaticText* _bottom_crop_label;
ContentSpinCtrl<VideoContent>* _bottom_crop;
wxStaticText* _fade_in_label;
Timecode<dcpomatic::ContentTime>* _fade_in;
wxStaticText* _fade_out_label;
Timecode<dcpomatic::ContentTime>* _fade_out;
- wxStaticText* _scale_to_label;
- ContentChoice<VideoContent, VideoContentScale>* _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/src/wx/wx_util.cc b/src/wx/wx_util.cc
index 6eef0d147..f8756549b 100644
--- a/src/wx/wx_util.cc
+++ b/src/wx/wx_util.cc
@@ -567,3 +567,26 @@ get_offsets (vector<Offset>& offsets)
return utc;
}
+
+
+wxString
+bitmap_path (string name)
+{
+ boost::filesystem::path base;
+
+#ifdef DCPOMATIC_DEBUG
+ /* Hack to allow OS X to find icons when running from the source tree */
+ char* path = getenv ("DCPOMATIC_GRAPHICS");
+ if (path) {
+ base = path;
+ } else {
+ base = shared_path();
+ }
+#else
+ base = shared_path();
+#endif
+
+ boost::filesystem::path p = base / String::compose("%1.png", name);
+ return std_to_wx (p.string());
+}
+
diff --git a/src/wx/wx_util.h b/src/wx/wx_util.h
index 8e0befba9..bff58a323 100644
--- a/src/wx/wx_util.h
+++ b/src/wx/wx_util.h
@@ -87,7 +87,7 @@ extern wxSplashScreen* maybe_show_splash ();
extern double calculate_mark_interval (double start);
extern bool display_progress (wxString title, wxString task);
extern bool report_errors_from_last_job (wxWindow* parent);
-
+extern wxString bitmap_path (std::string name);
struct Offset
{
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
-Subproject 6b694889479064979b52c1839a1919dc5fde673
+Subproject 3b21196b894bfbc096a5e90ee11dcf5f50bd4bf
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<ImageContent> 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<FFmpegContent> 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> film, shared_ptr<Content> content, string image, string container)
+static void scaling_test_for (shared_ptr<Film> film, shared_ptr<Content> 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 <cth@carlh.net>
+ Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
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 <dcp/raw_convert.h>
#include <boost/test/unit_test.hpp>
-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> film;
- string s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
- "<Content>"
- "<Type>FFmpeg</Type>"
- "<Path>/home/c.hetherington/DCP/prophet_long_clip.mkv</Path>"
- "<Digest>f3f23663da5bef6d2cbaa0db066f3351314142710</Digest>"
- "<Position>0</Position>"
- "<TrimStart>0</TrimStart>"
- "<TrimEnd>0</TrimEnd>"
- "<VideoLength>2879</VideoLength>"
- "<VideoWidth>" + raw_convert<string>(content_size.width) + "</VideoWidth>"
- "<VideoHeight>" + raw_convert<string>(content_size.height) + "</VideoHeight>"
- "<VideoFrameRate>23.97602462768555</VideoFrameRate>"
- "<OriginalVideoFrameRate>23.97602462768555</OriginalVideoFrameRate>"
- "<VideoFrameType>0</VideoFrameType>"
- "<SampleAspectRatio>1</SampleAspectRatio>"
- "<BitsPerPixel>12</BitsPerPixel>"
- "<LeftCrop>" + raw_convert<string>(crop.left) + "</LeftCrop>"
- "<RightCrop>" + raw_convert<string>(crop.right) + "</RightCrop>"
- "<TopCrop>" + raw_convert<string>(crop.top) + "</TopCrop>"
- "<BottomCrop>" + raw_convert<string>(crop.bottom) + "</BottomCrop>"
- "<Scale>";
-
- if (ratio) {
- s += "<Ratio>" + ratio->id() + "</Ratio>";
- } else {
- s += "<Scale>" + string(scale ? "1" : "0") + "</Scale>";
- }
+static dcp::Size const FOUR_TO_THREE(1436, 1080);
+static dcp::Size const FLAT(1998, 1080);
+static dcp::Size const SCOPE(2048, 858);
- s += "</Scale>"
- "<ColourConversion>"
- "<InputGamma>2.4</InputGamma>"
- "<InputGammaLinearised>1</InputGammaLinearised>"
- "<Matrix i=\"0\" j=\"0\">0.4124564</Matrix>"
- "<Matrix i=\"0\" j=\"1\">0.3575761</Matrix>"
- "<Matrix i=\"0\" j=\"2\">0.1804375</Matrix>"
- "<Matrix i=\"1\" j=\"0\">0.2126729</Matrix>"
- "<Matrix i=\"1\" j=\"1\">0.7151522</Matrix>"
- "<Matrix i=\"1\" j=\"2\">0.072175</Matrix>"
- "<Matrix i=\"2\" j=\"0\">0.0193339</Matrix>"
- "<Matrix i=\"2\" j=\"1\">0.119192</Matrix>"
- "<Matrix i=\"2\" j=\"2\">0.9503041</Matrix>"
- "<OutputGamma>2.6</OutputGamma>"
- "</ColourConversion>"
- "<AudioGain>0</AudioGain>"
- "<AudioDelay>0</AudioDelay>"
- "<SubtitleXOffset>0</SubtitleXOffset>"
- "<SubtitleYOffset>0</SubtitleYOffset>"
- "<SubtitleXScale>0</SubtitleXScale>"
- "<SubtitleYScale>0</SubtitleYScale>"
- "</Content>";
-
- shared_ptr<cxml::Document> doc (new cxml::Document ());
- doc->read_string (s);
-
- list<string> notes;
- shared_ptr<FFmpegContent> vc (new FFmpegContent (doc, 10, notes));
-
- optional<VideoContentScale> 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));
+ }
}
+