Cleanup: test tidying.
[dcpomatic.git] / test / frame_rate_test.cc
1 /*
2     Copyright (C) 2012-2016 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/frame_rate_test.cc
23  *  @brief Tests for FrameRateChange and the computation of the best
24  *  frame rate for the DCP.
25  *  @ingroup feature
26  */
27
28
29 #include "lib/audio_content.h"
30 #include "lib/config.h"
31 #include "lib/ffmpeg_audio_stream.h"
32 #include "lib/ffmpeg_content.h"
33 #include "lib/film.h"
34 #include "lib/frame_rate_change.h"
35 #include "lib/playlist.h"
36 #include "lib/video_content.h"
37 #include "test.h"
38 #include <boost/test/unit_test.hpp>
39
40
41
42 /* Test Playlist::best_dcp_frame_rate and FrameRateChange
43    with a single piece of content.
44 */
45 BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
46 {
47         auto film = new_test_film("best_dcp_frame_rate_test_single");
48         /* Get any piece of content, it doesn't matter what */
49         auto content = std::make_shared<FFmpegContent>("test/data/test.mp4");
50         film->examine_and_add_content (content);
51         BOOST_REQUIRE (!wait_for_jobs());
52
53         /* Run some tests with a limited range of allowed rates */
54
55         std::list<int> afr;
56         afr.push_back (24);
57         afr.push_back (25);
58         afr.push_back (30);
59         Config::instance()->set_allowed_dcp_frame_rates (afr);
60
61         content->_video_frame_rate = 60;
62         int best = film->best_video_frame_rate ();
63         auto frc = FrameRateChange(60, best);
64         BOOST_CHECK_EQUAL (best, 30);
65         BOOST_CHECK_EQUAL (frc.skip, true);
66         BOOST_CHECK_EQUAL (frc.repeat, 1);
67         BOOST_CHECK_EQUAL (frc.change_speed, false);
68         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
69
70         content->_video_frame_rate = 50;
71         best = film->best_video_frame_rate ();
72         frc = FrameRateChange (50, best);
73         BOOST_CHECK_EQUAL (best, 25);
74         BOOST_CHECK_EQUAL (frc.skip, true);
75         BOOST_CHECK_EQUAL (frc.repeat, 1);
76         BOOST_CHECK_EQUAL (frc.change_speed, false);
77         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
78
79         content->_video_frame_rate = 48;
80         best = film->best_video_frame_rate ();
81         frc = FrameRateChange (48, best);
82         BOOST_CHECK_EQUAL (best, 24);
83         BOOST_CHECK_EQUAL (frc.skip, true);
84         BOOST_CHECK_EQUAL (frc.repeat, 1);
85         BOOST_CHECK_EQUAL (frc.change_speed, false);
86         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
87
88         content->_video_frame_rate = 30;
89         best = film->best_video_frame_rate ();
90         frc = FrameRateChange (30, best);
91         BOOST_CHECK_EQUAL (best, 30);
92         BOOST_CHECK_EQUAL (frc.skip, false);
93         BOOST_CHECK_EQUAL (frc.repeat, 1);
94         BOOST_CHECK_EQUAL (frc.change_speed, false);
95         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
96
97         content->_video_frame_rate = 29.97;
98         best = film->best_video_frame_rate ();
99         frc = FrameRateChange (29.97, best);
100         BOOST_CHECK_EQUAL (best, 30);
101         BOOST_CHECK_EQUAL (frc.skip, false);
102         BOOST_CHECK_EQUAL (frc.repeat, 1);
103         BOOST_CHECK_EQUAL (frc.change_speed, true);
104         BOOST_CHECK_CLOSE (frc.speed_up, 30 / 29.97, 0.1);
105
106         content->_video_frame_rate = 25;
107         best = film->best_video_frame_rate ();
108         frc = FrameRateChange (25, best);
109         BOOST_CHECK_EQUAL (best, 25);
110         BOOST_CHECK_EQUAL (frc.skip, false);
111         BOOST_CHECK_EQUAL (frc.repeat, 1);
112         BOOST_CHECK_EQUAL (frc.change_speed, false);
113         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
114
115         content->_video_frame_rate = 24;
116         best = film->best_video_frame_rate ();
117         frc = FrameRateChange (24, best);
118         BOOST_CHECK_EQUAL (best, 24);
119         BOOST_CHECK_EQUAL (frc.skip, false);
120         BOOST_CHECK_EQUAL (frc.repeat, 1);
121         BOOST_CHECK_EQUAL (frc.change_speed, false);
122         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
123
124         content->_video_frame_rate = 14.5;
125         best = film->best_video_frame_rate ();
126         frc = FrameRateChange (14.5, best);
127         BOOST_CHECK_EQUAL (best, 30);
128         BOOST_CHECK_EQUAL (frc.skip, false);
129         BOOST_CHECK_EQUAL (frc.repeat, 2);
130         BOOST_CHECK_EQUAL (frc.change_speed, true);
131         BOOST_CHECK_CLOSE (frc.speed_up, 15 / 14.5, 0.1);
132
133         content->_video_frame_rate = 12.6;
134         best = film->best_video_frame_rate ();
135         frc = FrameRateChange (12.6, best);
136         BOOST_CHECK_EQUAL (best, 25);
137         BOOST_CHECK_EQUAL (frc.skip, false);
138         BOOST_CHECK_EQUAL (frc.repeat, 2);
139         BOOST_CHECK_EQUAL (frc.change_speed, true);
140         BOOST_CHECK_CLOSE (frc.speed_up, 25 / 25.2, 0.1);
141
142         content->_video_frame_rate = 12.4;
143         best = film->best_video_frame_rate ();
144         frc = FrameRateChange (12.4, best);
145         BOOST_CHECK_EQUAL (best, 25);
146         BOOST_CHECK_EQUAL (frc.skip, false);
147         BOOST_CHECK_EQUAL (frc.repeat, 2);
148         BOOST_CHECK_EQUAL (frc.change_speed, true);
149         BOOST_CHECK_CLOSE (frc.speed_up, 25 / 24.8, 0.1);
150
151         content->_video_frame_rate = 12;
152         best = film->best_video_frame_rate ();
153         frc = FrameRateChange (12, best);
154         BOOST_CHECK_EQUAL (best, 24);
155         BOOST_CHECK_EQUAL (frc.skip, false);
156         BOOST_CHECK_EQUAL (frc.repeat, 2);
157         BOOST_CHECK_EQUAL (frc.change_speed, false);
158         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
159
160         /* Now add some more rates and see if it will use them
161            in preference to skip/repeat.
162         */
163
164         afr.push_back (48);
165         afr.push_back (50);
166         afr.push_back (60);
167         Config::instance()->set_allowed_dcp_frame_rates (afr);
168
169         content->_video_frame_rate = 60;
170         best = film->playlist()->best_video_frame_rate ();
171         frc = FrameRateChange (60, best);
172         BOOST_CHECK_EQUAL (best, 60);
173         BOOST_CHECK_EQUAL (frc.skip, false);
174         BOOST_CHECK_EQUAL (frc.repeat, 1);
175         BOOST_CHECK_EQUAL (frc.change_speed, false);
176         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
177
178         content->_video_frame_rate = 50;
179         best = film->playlist()->best_video_frame_rate ();
180         frc = FrameRateChange (50, best);
181         BOOST_CHECK_EQUAL (best, 50);
182         BOOST_CHECK_EQUAL (frc.skip, false);
183         BOOST_CHECK_EQUAL (frc.repeat, 1);
184         BOOST_CHECK_EQUAL (frc.change_speed, false);
185         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
186
187         content->_video_frame_rate = 48;
188         best = film->playlist()->best_video_frame_rate ();
189         frc = FrameRateChange (48, best);
190         BOOST_CHECK_EQUAL (best, 48);
191         BOOST_CHECK_EQUAL (frc.skip, false);
192         BOOST_CHECK_EQUAL (frc.repeat, 1);
193         BOOST_CHECK_EQUAL (frc.change_speed, false);
194         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
195
196         /* Check some out-there conversions (not the best) */
197
198         frc = FrameRateChange (14.99, 24);
199         BOOST_CHECK_EQUAL (frc.skip, false);
200         BOOST_CHECK_EQUAL (frc.repeat, 2);
201         BOOST_CHECK_EQUAL (frc.change_speed, true);
202         BOOST_CHECK_CLOSE (frc.speed_up, 24 / (2 * 14.99), 0.1);
203
204         /* Check some conversions with limited DCP targets */
205
206         afr.clear ();
207         afr.push_back (24);
208         Config::instance()->set_allowed_dcp_frame_rates (afr);
209
210         content->_video_frame_rate = 25;
211         best = film->best_video_frame_rate ();
212         frc = FrameRateChange (25, best);
213         BOOST_CHECK_EQUAL (best, 24);
214         BOOST_CHECK_EQUAL (frc.skip, false);
215         BOOST_CHECK_EQUAL (frc.repeat, 1);
216         BOOST_CHECK_EQUAL (frc.change_speed, true);
217         BOOST_CHECK_CLOSE (frc.speed_up, 24.0 / 25, 0.1);
218 }
219
220 /* Test Playlist::best_dcp_frame_rate and FrameRateChange
221    with two pieces of content.
222 */
223 BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_double)
224 {
225         auto film = new_test_film("best_dcp_frame_rate_test_double");
226         /* Get any old content, it doesn't matter what */
227         auto A = std::make_shared<FFmpegContent>("test/data/test.mp4");
228         film->examine_and_add_content (A);
229         auto B = std::make_shared<FFmpegContent>("test/data/test.mp4");
230         film->examine_and_add_content (B);
231         BOOST_REQUIRE (!wait_for_jobs());
232
233         /* Run some tests with a limited range of allowed rates */
234
235         std::list<int> afr;
236         afr.push_back (24);
237         afr.push_back (25);
238         afr.push_back (30);
239         Config::instance()->set_allowed_dcp_frame_rates (afr);
240
241         A->_video_frame_rate = 30;
242         B->_video_frame_rate = 24;
243         BOOST_CHECK_EQUAL (film->best_video_frame_rate(), 25);
244
245         A->_video_frame_rate = 24;
246         B->_video_frame_rate = 24;
247         BOOST_CHECK_EQUAL (film->best_video_frame_rate(), 24);
248
249         A->_video_frame_rate = 24;
250         B->_video_frame_rate = 48;
251         BOOST_CHECK_EQUAL (film->best_video_frame_rate(), 24);
252 }
253
254 BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
255 {
256         auto film = new_test_film("audio_sampling_rate_test");
257         /* Get any piece of content, it doesn't matter what */
258         auto content = std::make_shared<FFmpegContent>("test/data/test.mp4");
259         film->examine_and_add_content (content);
260         BOOST_REQUIRE (!wait_for_jobs());
261
262         std::list<int> afr;
263         afr.push_back (24);
264         afr.push_back (25);
265         afr.push_back (30);
266         Config::instance()->set_allowed_dcp_frame_rates (afr);
267
268         auto stream = std::make_shared<FFmpegAudioStream>("foo", 0, 0, 0, 0, 0);
269         content->audio.reset (new AudioContent (content.get()));
270         content->audio->add_stream (stream);
271         content->_video_frame_rate = 24;
272         film->set_video_frame_rate (24);
273         stream->_frame_rate = 48000;
274         BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 48000);
275
276         stream->_frame_rate = 44100;
277         BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 48000);
278
279         stream->_frame_rate = 80000;
280         BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 48000);
281
282         content->_video_frame_rate = 23.976;
283         film->set_video_frame_rate (24);
284         stream->_frame_rate = 48000;
285         BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 47952);
286
287         content->_video_frame_rate = 29.97;
288         film->set_video_frame_rate (30);
289         BOOST_CHECK_EQUAL (film->video_frame_rate (), 30);
290         stream->_frame_rate = 48000;
291         BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 47952);
292
293         content->_video_frame_rate = 25;
294         film->set_video_frame_rate (24);
295         stream->_frame_rate = 48000;
296         BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 50000);
297
298         content->_video_frame_rate = 25;
299         film->set_video_frame_rate (24);
300         stream->_frame_rate = 44100;
301         BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 50000);
302
303         /* Check some out-there conversions (not the best) */
304
305         content->_video_frame_rate = 14.99;
306         film->set_video_frame_rate (25);
307         stream->_frame_rate = 16000;
308         /* The FrameRateChange within resampled_frame_rate should choose to double-up
309            the 14.99 fps video to 30 and then run it slow at 25.
310         */
311         BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), lrint (48000 * 2 * 14.99 / 25));
312 }