4fe91ebca3679f37616dd8d407e01cedb7949a5a
[dcpomatic.git] / test / threed_test.cc
1 /*
2     Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21
22 /** @file  test/threed_test.cc
23  *  @brief Create some 3D DCPs (without comparing the results to anything).
24  *  @ingroup completedcp
25  */
26
27
28 #include "lib/config.h"
29 #include "lib/content_factory.h"
30 #include "lib/cross.h"
31 #include "lib/dcp_content_type.h"
32 #include "lib/ffmpeg_content.h"
33 #include "lib/film.h"
34 #include "lib/job.h"
35 #include "lib/job_manager.h"
36 #include "lib/make_dcp.h"
37 #include "lib/ratio.h"
38 #include "lib/video_content.h"
39 #include "test.h"
40 #include <boost/test/unit_test.hpp>
41 #include <iostream>
42
43
44 using std::cout;
45 using std::make_shared;
46 using std::shared_ptr;
47
48
49 /** Basic sanity check of THREE_D_LEFT_RIGHT */
50 BOOST_AUTO_TEST_CASE (threed_test1)
51 {
52         auto film = new_test_film ("threed_test1");
53         film->set_name ("test_film1");
54         auto c = make_shared<FFmpegContent>("test/data/test.mp4");
55         film->examine_and_add_content (c);
56         BOOST_REQUIRE (!wait_for_jobs());
57
58         c->video->set_frame_type (VideoFrameType::THREE_D_LEFT_RIGHT);
59
60         film->set_container (Ratio::from_id ("185"));
61         film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
62         film->set_three_d (true);
63         make_and_verify_dcp (film);
64 }
65
66
67 /** Basic sanity check of THREE_D_ALTERNATE; at the moment this is just to make sure
68  *  that such a transcode completes without error.
69  */
70 BOOST_AUTO_TEST_CASE (threed_test2)
71 {
72         auto film = new_test_film ("threed_test2");
73         film->set_name ("test_film2");
74         auto c = make_shared<FFmpegContent>("test/data/test.mp4");
75         film->examine_and_add_content (c);
76         BOOST_REQUIRE (!wait_for_jobs());
77
78         c->video->set_frame_type (VideoFrameType::THREE_D_ALTERNATE);
79
80         film->set_container (Ratio::from_id ("185"));
81         film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
82         film->set_three_d (true);
83         make_and_verify_dcp (film);
84 }
85
86
87 /** Basic sanity check of THREE_D_LEFT and THREE_D_RIGHT; at the moment this is just to make sure
88  *  that such a transcode completes without error.
89  */
90 BOOST_AUTO_TEST_CASE (threed_test3)
91 {
92         shared_ptr<Film> film = new_test_film2 ("threed_test3");
93         auto L = make_shared<FFmpegContent>("test/data/test.mp4");
94         film->examine_and_add_content (L);
95         auto R = make_shared<FFmpegContent>("test/data/test.mp4");
96         film->examine_and_add_content (R);
97         BOOST_REQUIRE (!wait_for_jobs());
98
99         L->video->set_frame_type (VideoFrameType::THREE_D_LEFT);
100         R->video->set_frame_type (VideoFrameType::THREE_D_RIGHT);
101
102         film->set_three_d (true);
103         make_and_verify_dcp (film);
104 }
105
106
107 BOOST_AUTO_TEST_CASE (threed_test4)
108 {
109         ConfigRestorer cr;
110
111         /* Try to stop out-of-memory crashes on my laptop */
112         Config::instance()->set_master_encoding_threads (boost::thread::hardware_concurrency() / 4);
113
114         auto film = new_test_film2 ("threed_test4");
115         auto L = make_shared<FFmpegContent>(TestPaths::private_data() / "LEFT_TEST_DCP3D4K.mov");
116         film->examine_and_add_content (L);
117         auto R = make_shared<FFmpegContent>(TestPaths::private_data() / "RIGHT_TEST_DCP3D4K.mov");
118         film->examine_and_add_content (R);
119         BOOST_REQUIRE (!wait_for_jobs());
120
121         L->video->set_frame_type (VideoFrameType::THREE_D_LEFT);
122         R->video->set_frame_type (VideoFrameType::THREE_D_RIGHT);
123         /* There doesn't seem much point in encoding the whole input, especially as we're only
124          * checking for errors during the encode and not the result.  Also decoding these files
125          * (4K HQ Prores) is very slow.
126          */
127         L->set_trim_end (dcpomatic::ContentTime::from_seconds(22));
128         R->set_trim_end (dcpomatic::ContentTime::from_seconds(22));
129
130         film->set_three_d (true);
131         make_and_verify_dcp (film, {dcp::VerificationNote::Code::INVALID_PICTURE_ASSET_RESOLUTION_FOR_3D});
132 }
133
134
135 BOOST_AUTO_TEST_CASE (threed_test5)
136 {
137         auto film = new_test_film2 ("threed_test5");
138         auto L = make_shared<FFmpegContent>(TestPaths::private_data() / "boon_telly.mkv");
139         film->examine_and_add_content (L);
140         auto R = make_shared<FFmpegContent>(TestPaths::private_data() / "boon_telly.mkv");
141         film->examine_and_add_content (R);
142         BOOST_REQUIRE (!wait_for_jobs());
143
144         L->video->set_frame_type (VideoFrameType::THREE_D_LEFT);
145         R->video->set_frame_type (VideoFrameType::THREE_D_RIGHT);
146         /* There doesn't seem much point in encoding the whole input, especially as we're only
147          * checking for errors during the encode and not the result.
148          */
149         L->set_trim_end (dcpomatic::ContentTime::from_seconds(3 * 60 + 20));
150         R->set_trim_end (dcpomatic::ContentTime::from_seconds(3 * 60 + 20));
151
152         film->set_three_d (true);
153         make_and_verify_dcp (film, {dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_RATE_FOR_2K});
154 }
155
156
157 BOOST_AUTO_TEST_CASE (threed_test6)
158 {
159         auto film = new_test_film2 ("threed_test6");
160         auto L = make_shared<FFmpegContent>("test/data/3dL.mp4");
161         film->examine_and_add_content (L);
162         auto R = make_shared<FFmpegContent>("test/data/3dR.mp4");
163         film->examine_and_add_content (R);
164         BOOST_REQUIRE (!wait_for_jobs());
165
166         L->video->set_frame_type (VideoFrameType::THREE_D_LEFT);
167         R->video->set_frame_type (VideoFrameType::THREE_D_RIGHT);
168
169         film->set_three_d (true);
170         make_and_verify_dcp (film);
171         check_dcp ("test/data/threed_test6", film->dir(film->dcp_name()));
172 }
173
174
175 /** Check 2D content set as being 3D; this should give an informative error */
176 BOOST_AUTO_TEST_CASE (threed_test7)
177 {
178         using boost::filesystem::path;
179
180         auto film = new_test_film2 ("threed_test7");
181         path const content_path = "test/data/flat_red.png";
182         auto c = content_factory(content_path).front();
183         film->examine_and_add_content (c);
184         BOOST_REQUIRE (!wait_for_jobs());
185
186         c->video->set_frame_type (VideoFrameType::THREE_D);
187         c->video->set_length (24);
188
189         film->set_three_d (true);
190         make_dcp (film, TranscodeJob::ChangedBehaviour::IGNORE);
191         film->write_metadata ();
192
193         auto jm = JobManager::instance ();
194         while (jm->work_to_do ()) {
195                 while (signal_manager->ui_idle()) {}
196                 dcpomatic_sleep_seconds (1);
197         }
198
199         while (signal_manager->ui_idle ()) {}
200
201         BOOST_REQUIRE (jm->errors());
202         shared_ptr<Job> failed;
203         for (auto i: jm->_jobs) {
204                 if (i->finished_in_error()) {
205                         BOOST_REQUIRE (!failed);
206                         failed = i;
207                 }
208         }
209         BOOST_REQUIRE (failed);
210         BOOST_CHECK_EQUAL (failed->error_summary(), String::compose("The content file %1 is set as 3D but does not appear to contain 3D images.  Please set it to 2D.  You can still make a 3D DCP from this content by ticking the 3D option in the DCP video tab.", content_path.string()));
211
212         while (signal_manager->ui_idle ()) {}
213
214         JobManager::drop ();
215 }
216
217
218 /** Trigger a -114 error by trying to make a 3D DCP out of two files with slightly
219  *  different lengths.
220  */
221 BOOST_AUTO_TEST_CASE (threed_test_separate_files_slightly_different_lengths)
222 {
223         shared_ptr<Film> film = new_test_film2 ("threed_test3");
224         auto L = make_shared<FFmpegContent>("test/data/test.mp4");
225         film->examine_and_add_content (L);
226         auto R = make_shared<FFmpegContent>("test/data/test.mp4");
227         film->examine_and_add_content (R);
228         BOOST_REQUIRE (!wait_for_jobs());
229
230         L->video->set_frame_type (VideoFrameType::THREE_D_LEFT);
231         R->video->set_frame_type (VideoFrameType::THREE_D_RIGHT);
232         R->set_trim_end (dcpomatic::ContentTime::from_frames(1, 24));
233
234         film->set_three_d (true);
235         make_and_verify_dcp (film);
236 }
237
238
239 /** Trigger a -114 error by trying to make a 3D DCP out of two files with very
240  *  different lengths.
241  */
242 BOOST_AUTO_TEST_CASE (threed_test_separate_files_very_different_lengths)
243 {
244         shared_ptr<Film> film = new_test_film2 ("threed_test3");
245         auto L = make_shared<FFmpegContent>("test/data/test.mp4");
246         film->examine_and_add_content (L);
247         auto R = make_shared<FFmpegContent>("test/data/test.mp4");
248         film->examine_and_add_content (R);
249         BOOST_REQUIRE (!wait_for_jobs());
250
251         L->video->set_frame_type (VideoFrameType::THREE_D_LEFT);
252         R->video->set_frame_type (VideoFrameType::THREE_D_RIGHT);
253         R->set_trim_end (dcpomatic::ContentTime::from_seconds(1.5));
254
255         film->set_three_d (true);
256         make_and_verify_dcp (film);
257 }