summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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));
+ }
}
+