Verify a whole bunch of DCPs made by unit tests.
[dcpomatic.git] / test / ffmpeg_encoder_test.cc
1 /*
2     Copyright (C) 2017-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 #include "lib/ffmpeg_encoder.h"
22 #include "lib/film.h"
23 #include "lib/ffmpeg_content.h"
24 #include "lib/image_content.h"
25 #include "lib/video_content.h"
26 #include "lib/audio_content.h"
27 #include "lib/string_text_file_content.h"
28 #include "lib/ratio.h"
29 #include "lib/transcode_job.h"
30 #include "lib/dcp_content.h"
31 #include "lib/text_content.h"
32 #include "lib/compose.hpp"
33 #include "lib/content_factory.h"
34 #include "test.h"
35 #include <boost/test/unit_test.hpp>
36
37 using std::string;
38 using std::shared_ptr;
39 using std::make_shared;
40 using boost::optional;
41 using namespace dcpomatic;
42
43 static void
44 ffmpeg_content_test (int number, boost::filesystem::path content, ExportFormat format)
45 {
46         Cleanup cl;
47
48         string name = "ffmpeg_encoder_";
49         string extension;
50         switch (format) {
51         case ExportFormat::H264_AAC:
52                 name += "h264";
53                 extension = "mp4";
54                 break;
55         case ExportFormat::PRORES:
56                 name += "prores";
57                 extension = "mov";
58                 break;
59         case ExportFormat::H264_PCM:
60         case ExportFormat::SUBTITLES_DCP:
61                 BOOST_REQUIRE (false);
62         }
63
64         name = String::compose("%1_test%2", name, number);
65
66         auto c = make_shared<FFmpegContent>(content);
67         shared_ptr<Film> film = new_test_film2 (name, {c}, &cl);
68         film->set_name (name);
69         film->set_audio_channels (6);
70
71         film->write_metadata ();
72         auto job = make_shared<TranscodeJob>(film);
73         auto file = boost::filesystem::path("build") / "test" / String::compose("%1.%2", name, extension);
74         cl.add (file);
75         FFmpegEncoder encoder (film, job, file, format, false, false, false, 23);
76         encoder.go ();
77
78         cl.run ();
79 }
80
81 /** Red / green / blue MP4 -> Prores */
82 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test1)
83 {
84         ffmpeg_content_test (1, "test/data/test.mp4", ExportFormat::PRORES);
85 }
86
87 /** Dolby Aurora trailer VOB -> Prores */
88 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test2)
89 {
90         ffmpeg_content_test (2, TestPaths::private_data() / "dolby_aurora.vob", ExportFormat::PRORES);
91 }
92
93 /** Sintel trailer -> Prores */
94 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test3)
95 {
96         ffmpeg_content_test (3, TestPaths::private_data() / "Sintel_Trailer1.480p.DivX_Plus_HD.mkv", ExportFormat::PRORES);
97 }
98
99 /** Big Buck Bunny trailer -> Prores */
100 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test4)
101 {
102         ffmpeg_content_test (4, TestPaths::private_data() / "big_buck_bunny_trailer_480p.mov", ExportFormat::PRORES);
103 }
104
105 /** Still image -> Prores */
106 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test5)
107 {
108         auto film = new_test_film ("ffmpeg_encoder_prores_test5");
109         film->set_name ("ffmpeg_encoder_prores_test5");
110         shared_ptr<ImageContent> c (new ImageContent(TestPaths::private_data() / "bbc405.png"));
111         film->set_container (Ratio::from_id ("185"));
112         film->set_audio_channels (6);
113
114         film->examine_and_add_content (c);
115         BOOST_REQUIRE (!wait_for_jobs ());
116
117         c->video->set_length (240);
118
119         film->write_metadata ();
120         shared_ptr<Job> job (new TranscodeJob (film));
121         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test5.mov", ExportFormat::PRORES, false, false, false, 23);
122         encoder.go ();
123 }
124
125 /** Subs -> Prores */
126 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test6)
127 {
128         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_prores_test6");
129         film->set_name ("ffmpeg_encoder_prores_test6");
130         film->set_container (Ratio::from_id ("185"));
131         film->set_audio_channels (6);
132
133         shared_ptr<StringTextFileContent> s (new StringTextFileContent("test/data/subrip2.srt"));
134         film->examine_and_add_content (s);
135         BOOST_REQUIRE (!wait_for_jobs ());
136         s->only_text()->set_colour (dcp::Colour (255, 255, 0));
137         s->only_text()->set_effect (dcp::Effect::SHADOW);
138         s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
139         film->write_metadata();
140
141         shared_ptr<Job> job (new TranscodeJob (film));
142         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test6.mov", ExportFormat::PRORES, false, false, false, 23);
143         encoder.go ();
144 }
145
146 /** Video + subs -> Prores */
147 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test7)
148 {
149         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_prores_test7");
150         film->set_name ("ffmpeg_encoder_prores_test7");
151         film->set_container (Ratio::from_id ("185"));
152         film->set_audio_channels (6);
153
154         shared_ptr<FFmpegContent> c (new FFmpegContent("test/data/test.mp4"));
155         film->examine_and_add_content (c);
156         BOOST_REQUIRE (!wait_for_jobs ());
157
158         shared_ptr<StringTextFileContent> s (new StringTextFileContent("test/data/subrip.srt"));
159         film->examine_and_add_content (s);
160         BOOST_REQUIRE (!wait_for_jobs ());
161         s->only_text()->set_colour (dcp::Colour (255, 255, 0));
162         s->only_text()->set_effect (dcp::Effect::SHADOW);
163         s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
164
165         shared_ptr<Job> job (new TranscodeJob (film));
166         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test7.mov", ExportFormat::PRORES, false, false, false, 23);
167         encoder.go ();
168 }
169
170 /** Red / green / blue MP4 -> H264 */
171 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test1)
172 {
173         ffmpeg_content_test(1, "test/data/test.mp4", ExportFormat::H264_AAC);
174 }
175
176 /** Just subtitles -> H264 */
177 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test2)
178 {
179         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_h264_test2");
180         film->set_name ("ffmpeg_encoder_h264_test2");
181         film->set_container (Ratio::from_id ("185"));
182         film->set_audio_channels (6);
183
184         shared_ptr<StringTextFileContent> s (new StringTextFileContent("test/data/subrip2.srt"));
185         film->examine_and_add_content (s);
186         BOOST_REQUIRE (!wait_for_jobs ());
187         s->only_text()->set_colour (dcp::Colour (255, 255, 0));
188         s->only_text()->set_effect (dcp::Effect::SHADOW);
189         s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
190         film->write_metadata();
191
192         shared_ptr<Job> job (new TranscodeJob (film));
193         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test2.mp4", ExportFormat::H264_AAC, false, false, false, 23);
194         encoder.go ();
195 }
196
197 /** Video + subs -> H264 */
198 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test3)
199 {
200         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_h264_test3");
201         film->set_name ("ffmpeg_encoder_h264_test3");
202         film->set_container (Ratio::from_id ("185"));
203         film->set_audio_channels (6);
204
205         shared_ptr<FFmpegContent> c (new FFmpegContent("test/data/test.mp4"));
206         film->examine_and_add_content (c);
207         BOOST_REQUIRE (!wait_for_jobs ());
208
209         shared_ptr<StringTextFileContent> s (new StringTextFileContent("test/data/subrip.srt"));
210         film->examine_and_add_content (s);
211         BOOST_REQUIRE (!wait_for_jobs ());
212         s->only_text()->set_colour (dcp::Colour (255, 255, 0));
213         s->only_text()->set_effect (dcp::Effect::SHADOW);
214         s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
215         film->write_metadata();
216
217         shared_ptr<Job> job (new TranscodeJob (film));
218         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test3.mp4", ExportFormat::H264_AAC, false, false, false, 23);
219         encoder.go ();
220 }
221
222 /** Scope-in-flat DCP -> H264 */
223 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test4)
224 {
225         shared_ptr<Film> film = new_test_film2("ffmpeg_encoder_h264_test4");
226         film->examine_and_add_content(shared_ptr<DCPContent>(new DCPContent("test/data/scope_dcp")));
227         BOOST_REQUIRE(!wait_for_jobs());
228
229         film->set_container(Ratio::from_id("185"));
230
231         shared_ptr<Job> job(new TranscodeJob(film));
232         FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test4.mp4", ExportFormat::H264_AAC, false, false, false, 23);
233         encoder.go();
234 }
235
236 /** Test mixdown from 5.1 to stereo */
237 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test5)
238 {
239         shared_ptr<Film> film = new_test_film ("ffmpeg_transcoder_h264_test5");
240         film->set_name ("ffmpeg_transcoder_h264_test5");
241         film->set_container (Ratio::from_id ("185"));
242         film->set_audio_channels (6);
243
244         shared_ptr<FFmpegContent> L (new FFmpegContent("test/data/L.wav"));
245         film->examine_and_add_content (L);
246         shared_ptr<FFmpegContent> R (new FFmpegContent("test/data/R.wav"));
247         film->examine_and_add_content (R);
248         shared_ptr<FFmpegContent> C (new FFmpegContent("test/data/C.wav"));
249         film->examine_and_add_content (C);
250         shared_ptr<FFmpegContent> Ls (new FFmpegContent("test/data/Ls.wav"));
251         film->examine_and_add_content (Ls);
252         shared_ptr<FFmpegContent> Rs (new FFmpegContent("test/data/Rs.wav"));
253         film->examine_and_add_content (Rs);
254         shared_ptr<FFmpegContent> Lfe (new FFmpegContent("test/data/Lfe.wav"));
255         film->examine_and_add_content (Lfe);
256         BOOST_REQUIRE (!wait_for_jobs ());
257
258         AudioMapping map (1, MAX_DCP_AUDIO_CHANNELS);
259
260         L->set_position (film, DCPTime::from_seconds(0));
261         map.make_zero ();
262         map.set (0, 0, 1);
263         L->audio->set_mapping (map);
264         R->set_position (film, DCPTime::from_seconds(1));
265         map.make_zero ();
266         map.set (0, 1, 1);
267         R->audio->set_mapping (map);
268         C->set_position (film, DCPTime::from_seconds(2));
269         map.make_zero ();
270         map.set (0, 2, 1);
271         C->audio->set_mapping (map);
272         Lfe->set_position (film, DCPTime::from_seconds(3));
273         map.make_zero ();
274         map.set (0, 3, 1);
275         Lfe->audio->set_mapping (map);
276         Ls->set_position (film, DCPTime::from_seconds(4));
277         map.make_zero ();
278         map.set (0, 4, 1);
279         Ls->audio->set_mapping (map);
280         Rs->set_position (film, DCPTime::from_seconds(5));
281         map.make_zero ();
282         map.set (0, 5, 1);
283         Rs->audio->set_mapping (map);
284
285         shared_ptr<Job> job (new TranscodeJob (film));
286         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test5.mp4", ExportFormat::H264_AAC, true, false, false, 23);
287         encoder.go ();
288
289         check_ffmpeg ("build/test/ffmpeg_encoder_h264_test5.mp4", "test/data/ffmpeg_encoder_h264_test5.mp4", 1);
290 }
291
292 /** Test export of a VF */
293 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test6)
294 {
295         shared_ptr<Film> film = new_test_film2 ("ffmpeg_encoder_h264_test6_ov");
296         film->examine_and_add_content (shared_ptr<ImageContent>(new ImageContent(TestPaths::private_data() / "bbc405.png")));
297         BOOST_REQUIRE (!wait_for_jobs());
298         film->make_dcp ();
299         BOOST_REQUIRE (!wait_for_jobs());
300
301         shared_ptr<Film> film2 = new_test_film2 ("ffmpeg_encoder_h264_test6_vf");
302         shared_ptr<DCPContent> ov (new DCPContent("build/test/ffmpeg_encoder_h264_test6_ov/" + film->dcp_name(false)));
303         film2->examine_and_add_content (ov);
304         BOOST_REQUIRE (!wait_for_jobs());
305         ov->set_reference_video (true);
306         shared_ptr<Content> subs = content_factory("test/data/subrip.srt").front();
307         film2->examine_and_add_content (subs);
308         BOOST_REQUIRE (!wait_for_jobs());
309         for (auto i: subs->text) {
310                 i->set_use (true);
311         }
312
313         shared_ptr<Job> job (new TranscodeJob (film2));
314         FFmpegEncoder encoder (film2, job, "build/test/ffmpeg_encoder_h264_test6_vf.mp4", ExportFormat::H264_AAC, true, false, false, 23);
315         encoder.go ();
316 }
317
318 /** Test export of a 3D DCP in a 2D project */
319 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test7)
320 {
321         shared_ptr<Film> film = new_test_film2 ("ffmpeg_encoder_h264_test7_data");
322         shared_ptr<Content> L (shared_ptr<ImageContent>(new ImageContent(TestPaths::private_data() / "bbc405.png")));
323         film->examine_and_add_content (L);
324         shared_ptr<Content> R (shared_ptr<ImageContent>(new ImageContent(TestPaths::private_data() / "bbc405.png")));
325         film->examine_and_add_content (R);
326         BOOST_REQUIRE (!wait_for_jobs());
327         L->video->set_frame_type (VideoFrameType::THREE_D_LEFT);
328         L->set_position (film, DCPTime());
329         R->video->set_frame_type (VideoFrameType::THREE_D_RIGHT);
330         R->set_position (film, DCPTime());
331         film->set_three_d (true);
332         film->make_dcp ();
333         BOOST_REQUIRE (!wait_for_jobs());
334
335         shared_ptr<Film> film2 = new_test_film2 ("ffmpeg_encoder_h264_test7_export");
336         shared_ptr<Content> dcp (new DCPContent(film->dir(film->dcp_name())));
337         film2->examine_and_add_content (dcp);
338         BOOST_REQUIRE (!wait_for_jobs());
339
340         shared_ptr<Job> job (new TranscodeJob (film2));
341         FFmpegEncoder encoder (film2, job, "build/test/ffmpeg_encoder_h264_test7.mp4", ExportFormat::H264_AAC, true, false, false, 23);
342         encoder.go ();
343 }
344
345
346 /** Stereo project with mixdown-to-stereo set */
347 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test8)
348 {
349         shared_ptr<Film> film = new_test_film2("ffmpeg_encoder_h264_test4");
350         film->examine_and_add_content(shared_ptr<DCPContent>(new DCPContent("test/data/scope_dcp")));
351         BOOST_REQUIRE(!wait_for_jobs());
352         film->set_audio_channels (2);
353
354         shared_ptr<Job> job(new TranscodeJob(film));
355         FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test8.mp4", ExportFormat::H264_AAC, true, false, false, 23);
356         encoder.go();
357 }
358
359
360 /** 7.1/HI/VI (i.e. 12-channel) project */
361 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test9)
362 {
363         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_prores_test9");
364         film->set_name ("ffmpeg_encoder_prores_test9");
365         shared_ptr<ImageContent> c (new ImageContent(TestPaths::private_data() / "bbc405.png"));
366         film->set_container (Ratio::from_id ("185"));
367         film->set_audio_channels (12);
368
369         film->examine_and_add_content (c);
370         BOOST_REQUIRE (!wait_for_jobs ());
371
372         c->video->set_length (240);
373
374         film->write_metadata ();
375         shared_ptr<Job> job (new TranscodeJob (film));
376         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test9.mov", ExportFormat::H264_AAC, false, false, false, 23);
377         encoder.go ();
378 }