2 Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
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.
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.
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/>.
21 /** @file test/frame_rate_test.cc
22 * @brief Tests for FrameRateChange and the computation of the best
23 * frame rate for the DCP.
27 #include <boost/test/unit_test.hpp>
29 #include "lib/config.h"
30 #include "lib/ffmpeg_content.h"
31 #include "lib/playlist.h"
32 #include "lib/ffmpeg_audio_stream.h"
33 #include "lib/frame_rate_change.h"
34 #include "lib/video_content.h"
35 #include "lib/audio_content.h"
38 using std::shared_ptr;
40 /* Test Playlist::best_dcp_frame_rate and FrameRateChange
41 with a single piece of content.
43 BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
45 shared_ptr<Film> film = new_test_film ("best_dcp_frame_rate_test_single");
46 /* Get any piece of content, it doesn't matter what */
47 shared_ptr<FFmpegContent> content (new FFmpegContent("test/data/test.mp4"));
48 film->examine_and_add_content (content);
49 BOOST_REQUIRE (!wait_for_jobs());
51 /* Run some tests with a limited range of allowed rates */
57 Config::instance()->set_allowed_dcp_frame_rates (afr);
59 content->_video_frame_rate = 60;
60 int best = film->best_video_frame_rate ();
61 FrameRateChange frc = FrameRateChange (60, best);
62 BOOST_CHECK_EQUAL (best, 30);
63 BOOST_CHECK_EQUAL (frc.skip, true);
64 BOOST_CHECK_EQUAL (frc.repeat, 1);
65 BOOST_CHECK_EQUAL (frc.change_speed, false);
66 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
68 content->_video_frame_rate = 50;
69 best = film->best_video_frame_rate ();
70 frc = FrameRateChange (50, best);
71 BOOST_CHECK_EQUAL (best, 25);
72 BOOST_CHECK_EQUAL (frc.skip, true);
73 BOOST_CHECK_EQUAL (frc.repeat, 1);
74 BOOST_CHECK_EQUAL (frc.change_speed, false);
75 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
77 content->_video_frame_rate = 48;
78 best = film->best_video_frame_rate ();
79 frc = FrameRateChange (48, best);
80 BOOST_CHECK_EQUAL (best, 24);
81 BOOST_CHECK_EQUAL (frc.skip, true);
82 BOOST_CHECK_EQUAL (frc.repeat, 1);
83 BOOST_CHECK_EQUAL (frc.change_speed, false);
84 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
86 content->_video_frame_rate = 30;
87 best = film->best_video_frame_rate ();
88 frc = FrameRateChange (30, best);
89 BOOST_CHECK_EQUAL (best, 30);
90 BOOST_CHECK_EQUAL (frc.skip, false);
91 BOOST_CHECK_EQUAL (frc.repeat, 1);
92 BOOST_CHECK_EQUAL (frc.change_speed, false);
93 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
95 content->_video_frame_rate = 29.97;
96 best = film->best_video_frame_rate ();
97 frc = FrameRateChange (29.97, best);
98 BOOST_CHECK_EQUAL (best, 30);
99 BOOST_CHECK_EQUAL (frc.skip, false);
100 BOOST_CHECK_EQUAL (frc.repeat, 1);
101 BOOST_CHECK_EQUAL (frc.change_speed, true);
102 BOOST_CHECK_CLOSE (frc.speed_up, 30 / 29.97, 0.1);
104 content->_video_frame_rate = 25;
105 best = film->best_video_frame_rate ();
106 frc = FrameRateChange (25, best);
107 BOOST_CHECK_EQUAL (best, 25);
108 BOOST_CHECK_EQUAL (frc.skip, false);
109 BOOST_CHECK_EQUAL (frc.repeat, 1);
110 BOOST_CHECK_EQUAL (frc.change_speed, false);
111 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
113 content->_video_frame_rate = 24;
114 best = film->best_video_frame_rate ();
115 frc = FrameRateChange (24, best);
116 BOOST_CHECK_EQUAL (best, 24);
117 BOOST_CHECK_EQUAL (frc.skip, false);
118 BOOST_CHECK_EQUAL (frc.repeat, 1);
119 BOOST_CHECK_EQUAL (frc.change_speed, false);
120 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
122 content->_video_frame_rate = 14.5;
123 best = film->best_video_frame_rate ();
124 frc = FrameRateChange (14.5, best);
125 BOOST_CHECK_EQUAL (best, 30);
126 BOOST_CHECK_EQUAL (frc.skip, false);
127 BOOST_CHECK_EQUAL (frc.repeat, 2);
128 BOOST_CHECK_EQUAL (frc.change_speed, true);
129 BOOST_CHECK_CLOSE (frc.speed_up, 15 / 14.5, 0.1);
131 content->_video_frame_rate = 12.6;
132 best = film->best_video_frame_rate ();
133 frc = FrameRateChange (12.6, best);
134 BOOST_CHECK_EQUAL (best, 25);
135 BOOST_CHECK_EQUAL (frc.skip, false);
136 BOOST_CHECK_EQUAL (frc.repeat, 2);
137 BOOST_CHECK_EQUAL (frc.change_speed, true);
138 BOOST_CHECK_CLOSE (frc.speed_up, 25 / 25.2, 0.1);
140 content->_video_frame_rate = 12.4;
141 best = film->best_video_frame_rate ();
142 frc = FrameRateChange (12.4, best);
143 BOOST_CHECK_EQUAL (best, 25);
144 BOOST_CHECK_EQUAL (frc.skip, false);
145 BOOST_CHECK_EQUAL (frc.repeat, 2);
146 BOOST_CHECK_EQUAL (frc.change_speed, true);
147 BOOST_CHECK_CLOSE (frc.speed_up, 25 / 24.8, 0.1);
149 content->_video_frame_rate = 12;
150 best = film->best_video_frame_rate ();
151 frc = FrameRateChange (12, best);
152 BOOST_CHECK_EQUAL (best, 24);
153 BOOST_CHECK_EQUAL (frc.skip, false);
154 BOOST_CHECK_EQUAL (frc.repeat, 2);
155 BOOST_CHECK_EQUAL (frc.change_speed, false);
156 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
158 /* Now add some more rates and see if it will use them
159 in preference to skip/repeat.
165 Config::instance()->set_allowed_dcp_frame_rates (afr);
167 content->_video_frame_rate = 60;
168 best = film->playlist()->best_video_frame_rate ();
169 frc = FrameRateChange (60, best);
170 BOOST_CHECK_EQUAL (best, 60);
171 BOOST_CHECK_EQUAL (frc.skip, false);
172 BOOST_CHECK_EQUAL (frc.repeat, 1);
173 BOOST_CHECK_EQUAL (frc.change_speed, false);
174 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
176 content->_video_frame_rate = 50;
177 best = film->playlist()->best_video_frame_rate ();
178 frc = FrameRateChange (50, best);
179 BOOST_CHECK_EQUAL (best, 50);
180 BOOST_CHECK_EQUAL (frc.skip, false);
181 BOOST_CHECK_EQUAL (frc.repeat, 1);
182 BOOST_CHECK_EQUAL (frc.change_speed, false);
183 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
185 content->_video_frame_rate = 48;
186 best = film->playlist()->best_video_frame_rate ();
187 frc = FrameRateChange (48, best);
188 BOOST_CHECK_EQUAL (best, 48);
189 BOOST_CHECK_EQUAL (frc.skip, false);
190 BOOST_CHECK_EQUAL (frc.repeat, 1);
191 BOOST_CHECK_EQUAL (frc.change_speed, false);
192 BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
194 /* Check some out-there conversions (not the best) */
196 frc = FrameRateChange (14.99, 24);
197 BOOST_CHECK_EQUAL (frc.skip, false);
198 BOOST_CHECK_EQUAL (frc.repeat, 2);
199 BOOST_CHECK_EQUAL (frc.change_speed, true);
200 BOOST_CHECK_CLOSE (frc.speed_up, 24 / (2 * 14.99), 0.1);
202 /* Check some conversions with limited DCP targets */
206 Config::instance()->set_allowed_dcp_frame_rates (afr);
208 content->_video_frame_rate = 25;
209 best = film->best_video_frame_rate ();
210 frc = FrameRateChange (25, best);
211 BOOST_CHECK_EQUAL (best, 24);
212 BOOST_CHECK_EQUAL (frc.skip, false);
213 BOOST_CHECK_EQUAL (frc.repeat, 1);
214 BOOST_CHECK_EQUAL (frc.change_speed, true);
215 BOOST_CHECK_CLOSE (frc.speed_up, 24.0 / 25, 0.1);
218 /* Test Playlist::best_dcp_frame_rate and FrameRateChange
219 with two pieces of content.
221 BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_double)
223 shared_ptr<Film> film = new_test_film ("best_dcp_frame_rate_test_double");
224 /* Get any old content, it doesn't matter what */
225 shared_ptr<FFmpegContent> A (new FFmpegContent("test/data/test.mp4"));
226 film->examine_and_add_content (A);
227 shared_ptr<FFmpegContent> B (new FFmpegContent("test/data/test.mp4"));
228 film->examine_and_add_content (B);
229 BOOST_REQUIRE (!wait_for_jobs());
231 /* Run some tests with a limited range of allowed rates */
237 Config::instance()->set_allowed_dcp_frame_rates (afr);
239 A->_video_frame_rate = 30;
240 B->_video_frame_rate = 24;
241 BOOST_CHECK_EQUAL (film->best_video_frame_rate(), 25);
243 A->_video_frame_rate = 24;
244 B->_video_frame_rate = 24;
245 BOOST_CHECK_EQUAL (film->best_video_frame_rate(), 24);
247 A->_video_frame_rate = 24;
248 B->_video_frame_rate = 48;
249 BOOST_CHECK_EQUAL (film->best_video_frame_rate(), 24);
252 BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
254 shared_ptr<Film> film = new_test_film ("audio_sampling_rate_test");
255 /* Get any piece of content, it doesn't matter what */
256 shared_ptr<FFmpegContent> content (new FFmpegContent("test/data/test.mp4"));
257 film->examine_and_add_content (content);
258 BOOST_REQUIRE (!wait_for_jobs());
264 Config::instance()->set_allowed_dcp_frame_rates (afr);
266 shared_ptr<FFmpegAudioStream> stream (new FFmpegAudioStream ("foo", 0, 0, 0, 0));
267 content->audio.reset (new AudioContent (content.get()));
268 content->audio->add_stream (stream);
269 content->_video_frame_rate = 24;
270 film->set_video_frame_rate (24);
271 stream->_frame_rate = 48000;
272 BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 48000);
274 stream->_frame_rate = 44100;
275 BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 48000);
277 stream->_frame_rate = 80000;
278 BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 48000);
280 content->_video_frame_rate = 23.976;
281 film->set_video_frame_rate (24);
282 stream->_frame_rate = 48000;
283 BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 47952);
285 content->_video_frame_rate = 29.97;
286 film->set_video_frame_rate (30);
287 BOOST_CHECK_EQUAL (film->video_frame_rate (), 30);
288 stream->_frame_rate = 48000;
289 BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 47952);
291 content->_video_frame_rate = 25;
292 film->set_video_frame_rate (24);
293 stream->_frame_rate = 48000;
294 BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 50000);
296 content->_video_frame_rate = 25;
297 film->set_video_frame_rate (24);
298 stream->_frame_rate = 44100;
299 BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), 50000);
301 /* Check some out-there conversions (not the best) */
303 content->_video_frame_rate = 14.99;
304 film->set_video_frame_rate (25);
305 stream->_frame_rate = 16000;
306 /* The FrameRateChange within resampled_frame_rate should choose to double-up
307 the 14.99 fps video to 30 and then run it slow at 25.
309 BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(film), lrint (48000 * 2 * 14.99 / 25));