Tweak naming and add more tests.
[dcpomatic.git] / test / ffmpeg_encoder_test.cc
1 /*
2     Copyright (C) 2017-2018 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/video_content.h"
25 #include "lib/audio_content.h"
26 #include "lib/text_subtitle_content.h"
27 #include "lib/ratio.h"
28 #include "lib/transcode_job.h"
29 #include "lib/dcp_content.h"
30 #include "lib/subtitle_content.h"
31 #include "test.h"
32 #include <boost/test/unit_test.hpp>
33
34 using boost::shared_ptr;
35
36 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_basic_test_mov)
37 {
38         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_basic_test_mov");
39         film->set_name ("ffmpeg_encoder_basic_test_mov");
40         shared_ptr<FFmpegContent> c (new FFmpegContent (film, "test/data/test.mp4"));
41         film->set_container (Ratio::from_id ("185"));
42         film->set_audio_channels (6);
43
44         film->examine_and_add_content (c);
45         BOOST_REQUIRE (!wait_for_jobs ());
46
47         shared_ptr<Job> job (new TranscodeJob (film));
48         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_basic_test.mov", FFmpegEncoder::FORMAT_PRORES, false);
49         encoder.go ();
50 }
51
52 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_basic_test2_mov)
53 {
54         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_basic_test2_mov");
55         film->set_name ("ffmpeg_encoder_basic_test2_mov");
56         shared_ptr<FFmpegContent> c (new FFmpegContent (film, private_data / "dolby_aurora.vob"));
57         film->set_container (Ratio::from_id ("185"));
58         film->set_audio_channels (6);
59
60         film->examine_and_add_content (c);
61         BOOST_REQUIRE (!wait_for_jobs ());
62
63         shared_ptr<Job> job (new TranscodeJob (film));
64         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_basic_test2.mov", FFmpegEncoder::FORMAT_PRORES, false);
65         encoder.go ();
66 }
67
68 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_basic_test_mp4)
69 {
70         shared_ptr<Film> film = new_test_film ("ffmpeg_transcoder_basic_test_mp4");
71         film->set_name ("ffmpeg_transcoder_basic_test");
72         shared_ptr<FFmpegContent> c (new FFmpegContent (film, "test/data/test.mp4"));
73         film->set_container (Ratio::from_id ("185"));
74         film->set_audio_channels (6);
75
76         film->examine_and_add_content (c);
77         BOOST_REQUIRE (!wait_for_jobs ());
78
79         shared_ptr<Job> job (new TranscodeJob (film));
80         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_basic_test.mp4", FFmpegEncoder::FORMAT_H264, false);
81         encoder.go ();
82 }
83
84 /** Simplest possible export subtitle case: just the subtitles */
85 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_test_subs_h264_1)
86 {
87         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_test_subs_h264_1");
88         film->set_name ("ffmpeg_encoder_test_subs_h264_1");
89         film->set_container (Ratio::from_id ("185"));
90         film->set_audio_channels (6);
91
92         shared_ptr<TextSubtitleContent> s (new TextSubtitleContent (film, "test/data/subrip2.srt"));
93         film->examine_and_add_content (s);
94         BOOST_REQUIRE (!wait_for_jobs ());
95         s->subtitle->set_colour (dcp::Colour (255, 255, 0));
96         s->subtitle->set_effect (dcp::SHADOW);
97         s->subtitle->set_effect_colour (dcp::Colour (0, 255, 255));
98         film->write_metadata();
99
100         shared_ptr<Job> job (new TranscodeJob (film));
101         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_test_subs_h264_1.mp4", FFmpegEncoder::FORMAT_H264, false);
102         encoder.go ();
103 }
104
105 /** Slightly more complicated example with longer subs and a video to overlay */
106 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_test_subs_h264_2)
107 {
108         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_test_subs_h264_2");
109         film->set_name ("ffmpeg_encoder_test_subs_h264_2");
110         film->set_container (Ratio::from_id ("185"));
111         film->set_audio_channels (6);
112
113         shared_ptr<FFmpegContent> c (new FFmpegContent (film, "test/data/test.mp4"));
114         film->examine_and_add_content (c);
115         BOOST_REQUIRE (!wait_for_jobs ());
116
117         shared_ptr<TextSubtitleContent> s (new TextSubtitleContent (film, "test/data/subrip.srt"));
118         film->examine_and_add_content (s);
119         BOOST_REQUIRE (!wait_for_jobs ());
120         s->subtitle->set_colour (dcp::Colour (255, 255, 0));
121         s->subtitle->set_effect (dcp::SHADOW);
122         s->subtitle->set_effect_colour (dcp::Colour (0, 255, 255));
123         film->write_metadata();
124
125         shared_ptr<Job> job (new TranscodeJob (film));
126         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_test_subs_h264_2.mp4", FFmpegEncoder::FORMAT_H264, false);
127         encoder.go ();
128 }
129
130 /** Simplest possible export subtitle case: just the subtitles */
131 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_test_subs_prores_1)
132 {
133         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_test_subs_prores_1");
134         film->set_name ("ffmpeg_encoder_test_subs_prores_1");
135         film->set_container (Ratio::from_id ("185"));
136         film->set_audio_channels (6);
137
138         shared_ptr<TextSubtitleContent> s (new TextSubtitleContent (film, "test/data/subrip2.srt"));
139         film->examine_and_add_content (s);
140         BOOST_REQUIRE (!wait_for_jobs ());
141         s->subtitle->set_colour (dcp::Colour (255, 255, 0));
142         s->subtitle->set_effect (dcp::SHADOW);
143         s->subtitle->set_effect_colour (dcp::Colour (0, 255, 255));
144         film->write_metadata();
145
146         shared_ptr<Job> job (new TranscodeJob (film));
147         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_test_subs_prores_1.mov", FFmpegEncoder::FORMAT_PRORES, false);
148         encoder.go ();
149 }
150
151 /** Slightly more complicated example with longer subs and a video to overlay */
152 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_test_subs_prores_2)
153 {
154         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_test_subs_prores_2");
155         film->set_name ("ffmpeg_encoder_test_subs_prores_2");
156         film->set_container (Ratio::from_id ("185"));
157         film->set_audio_channels (6);
158
159         shared_ptr<FFmpegContent> c (new FFmpegContent (film, "test/data/test.mp4"));
160         film->examine_and_add_content (c);
161         BOOST_REQUIRE (!wait_for_jobs ());
162
163         shared_ptr<TextSubtitleContent> s (new TextSubtitleContent (film, "test/data/subrip.srt"));
164         film->examine_and_add_content (s);
165         BOOST_REQUIRE (!wait_for_jobs ());
166         s->subtitle->set_colour (dcp::Colour (255, 255, 0));
167         s->subtitle->set_effect (dcp::SHADOW);
168         s->subtitle->set_effect_colour (dcp::Colour (0, 255, 255));
169
170         shared_ptr<Job> job (new TranscodeJob (film));
171         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_test_subs_prores_2.mov", FFmpegEncoder::FORMAT_PRORES, false);
172         encoder.go ();
173 }
174
175 /** Test a bug with export of scope-in-flat DCP content */
176 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_bug_test_scope)
177 {
178         shared_ptr<Film> film = new_test_film2("ffmpeg_encoder_bug_test_scope");
179         film->examine_and_add_content(shared_ptr<DCPContent>(new DCPContent(film, "test/data/scope_dcp")));
180         BOOST_REQUIRE(!wait_for_jobs());
181
182         film->set_container(Ratio::from_id("185"));
183
184         shared_ptr<Job> job(new TranscodeJob(film));
185         FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_bug_test_scope.mp4", FFmpegEncoder::FORMAT_H264, false);
186         encoder.go();
187 }
188
189 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_basic_test_mixdown)
190 {
191         shared_ptr<Film> film = new_test_film ("ffmpeg_transcoder_basic_test_mixdown");
192         film->set_name ("ffmpeg_transcoder_basic_test");
193         film->set_container (Ratio::from_id ("185"));
194         film->set_audio_channels (6);
195
196         shared_ptr<FFmpegContent> L (new FFmpegContent (film, "test/data/L.wav"));
197         film->examine_and_add_content (L);
198         shared_ptr<FFmpegContent> R (new FFmpegContent (film, "test/data/R.wav"));
199         film->examine_and_add_content (R);
200         shared_ptr<FFmpegContent> C (new FFmpegContent (film, "test/data/C.wav"));
201         film->examine_and_add_content (C);
202         shared_ptr<FFmpegContent> Ls (new FFmpegContent (film, "test/data/Ls.wav"));
203         film->examine_and_add_content (Ls);
204         shared_ptr<FFmpegContent> Rs (new FFmpegContent (film, "test/data/Rs.wav"));
205         film->examine_and_add_content (Rs);
206         shared_ptr<FFmpegContent> Lfe (new FFmpegContent (film, "test/data/Lfe.wav"));
207         film->examine_and_add_content (Lfe);
208         BOOST_REQUIRE (!wait_for_jobs ());
209
210         AudioMapping map (1, MAX_DCP_AUDIO_CHANNELS);
211
212         L->set_position (DCPTime::from_seconds (0));
213         map.make_zero ();
214         map.set (0, 0, 1);
215         L->audio->set_mapping (map);
216         R->set_position (DCPTime::from_seconds (1));
217         map.make_zero ();
218         map.set (0, 1, 1);
219         R->audio->set_mapping (map);
220         C->set_position (DCPTime::from_seconds (2));
221         map.make_zero ();
222         map.set (0, 2, 1);
223         C->audio->set_mapping (map);
224         Lfe->set_position (DCPTime::from_seconds (3));
225         map.make_zero ();
226         map.set (0, 3, 1);
227         Lfe->audio->set_mapping (map);
228         Ls->set_position (DCPTime::from_seconds (4));
229         map.make_zero ();
230         map.set (0, 4, 1);
231         Ls->audio->set_mapping (map);
232         Rs->set_position (DCPTime::from_seconds (5));
233         map.make_zero ();
234         map.set (0, 5, 1);
235         Rs->audio->set_mapping (map);
236
237         shared_ptr<Job> job (new TranscodeJob (film));
238         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_basic_test_mixdown.mp4", FFmpegEncoder::FORMAT_H264, true);
239         encoder.go ();
240
241         check_ffmpeg ("build/test/ffmpeg_encoder_basic_test_mixdown.mp4", "test/data/ffmpeg_encoder_basic_test_mixdown.mp4", 1);
242 }
243
244 /** Test going from an image source to a MOV which has at times had big colour problems */
245 BOOST_AUTO_TEST_CASE (ffmpeg_encoder_image_test_mov)
246 {
247         shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_image_test_mov");
248         film->set_name ("ffmpeg_encoder_image_test");
249         shared_ptr<FFmpegContent> c (new FFmpegContent (film, private_data / "bbc405.png"));
250         film->set_container (Ratio::from_id ("185"));
251         film->set_audio_channels (6);
252
253         film->examine_and_add_content (c);
254         BOOST_REQUIRE (!wait_for_jobs ());
255
256         c->video->set_length (240);
257
258         shared_ptr<Job> job (new TranscodeJob (film));
259         FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_image_test.mov", FFmpegEncoder::FORMAT_PRORES, false);
260         encoder.go ();
261 }