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