Merge.
[dcpomatic.git] / test / frame_rate_test.cc
1 /*
2     Copyright (C) 2012 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 #include <boost/test/unit_test.hpp>
21 #include "lib/film.h"
22 #include "lib/config.h"
23 #include "lib/ffmpeg_content.h"
24 #include "lib/playlist.h"
25 #include "test.h"
26
27 using boost::shared_ptr;
28
29 /* Test Playlist::best_dcp_frame_rate and FrameRateConversion
30    with a single piece of content.
31 */
32 BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
33 {
34         shared_ptr<Film> film = new_test_film ("best_dcp_frame_rate_test_single");
35         /* Get any piece of content, it doesn't matter what */
36         shared_ptr<FFmpegContent> content (new FFmpegContent (film, "test/data/test.mp4"));
37         film->add_content (content);
38         wait_for_jobs ();
39         
40         /* Run some tests with a limited range of allowed rates */
41         
42         std::list<int> afr;
43         afr.push_back (24);
44         afr.push_back (25);
45         afr.push_back (30);
46         Config::instance()->set_allowed_dcp_frame_rates (afr);
47
48         content->_video_frame_rate = 60;
49         int best = film->playlist()->best_dcp_frame_rate ();
50         FrameRateChange frc = FrameRateChange (60, best);
51         BOOST_CHECK_EQUAL (best, 30);
52         BOOST_CHECK_EQUAL (frc.skip, true);
53         BOOST_CHECK_EQUAL (frc.repeat, 1);
54         BOOST_CHECK_EQUAL (frc.change_speed, false);
55         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
56         
57         content->_video_frame_rate = 50;
58         best = film->playlist()->best_dcp_frame_rate ();
59         frc = FrameRateChange (50, best);
60         BOOST_CHECK_EQUAL (best, 25);
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 = 48;
67         best = film->playlist()->best_dcp_frame_rate ();
68         frc = FrameRateChange (48, best);
69         BOOST_CHECK_EQUAL (best, 24);
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 = 30;
76         best = film->playlist()->best_dcp_frame_rate ();
77         frc = FrameRateChange (30, best);
78         BOOST_CHECK_EQUAL (best, 30);
79         BOOST_CHECK_EQUAL (frc.skip, false);
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 = 29.97;
85         best = film->playlist()->best_dcp_frame_rate ();
86         frc = FrameRateChange (29.97, 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, true);
91         BOOST_CHECK_CLOSE (frc.speed_up, 30 / 29.97, 0.1);
92         
93         content->_video_frame_rate = 25;
94         best = film->playlist()->best_dcp_frame_rate ();
95         frc = FrameRateChange (25, best);
96         BOOST_CHECK_EQUAL (best, 25);
97         BOOST_CHECK_EQUAL (frc.skip, false);
98         BOOST_CHECK_EQUAL (frc.repeat, 1);
99         BOOST_CHECK_EQUAL (frc.change_speed, false);
100         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
101
102         content->_video_frame_rate = 24;
103         best = film->playlist()->best_dcp_frame_rate ();
104         frc = FrameRateChange (24, best);
105         BOOST_CHECK_EQUAL (best, 24);
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 = 14.5;
112         best = film->playlist()->best_dcp_frame_rate ();
113         frc = FrameRateChange (14.5, best);
114         BOOST_CHECK_EQUAL (best, 30);
115         BOOST_CHECK_EQUAL (frc.skip, false);
116         BOOST_CHECK_EQUAL (frc.repeat, 2);
117         BOOST_CHECK_EQUAL (frc.change_speed, true);
118         BOOST_CHECK_CLOSE (frc.speed_up, 15 / 14.5, 0.1);
119
120         content->_video_frame_rate = 12.6;
121         best = film->playlist()->best_dcp_frame_rate ();
122         frc = FrameRateChange (12.6, best);
123         BOOST_CHECK_EQUAL (best, 25);
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, 25 / 25.2, 0.1);
128
129         content->_video_frame_rate = 12.4;
130         best = film->playlist()->best_dcp_frame_rate ();
131         frc = FrameRateChange (12.4, 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 / 24.8, 0.1);
137
138         content->_video_frame_rate = 12;
139         best = film->playlist()->best_dcp_frame_rate ();
140         frc = FrameRateChange (12, best);
141         BOOST_CHECK_EQUAL (best, 24);
142         BOOST_CHECK_EQUAL (frc.skip, false);
143         BOOST_CHECK_EQUAL (frc.repeat, 2);
144         BOOST_CHECK_EQUAL (frc.change_speed, false);
145         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
146
147         /* Now add some more rates and see if it will use them
148            in preference to skip/repeat.
149         */
150
151         afr.push_back (48);
152         afr.push_back (50);
153         afr.push_back (60);
154         Config::instance()->set_allowed_dcp_frame_rates (afr);
155
156         content->_video_frame_rate = 60;
157         best = film->playlist()->best_dcp_frame_rate ();
158         frc = FrameRateChange (60, best);
159         BOOST_CHECK_EQUAL (best, 60);
160         BOOST_CHECK_EQUAL (frc.skip, false);
161         BOOST_CHECK_EQUAL (frc.repeat, 1);
162         BOOST_CHECK_EQUAL (frc.change_speed, false);
163         BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
164         
165         content->_video_frame_rate = 50;
166         best = film->playlist()->best_dcp_frame_rate ();
167         frc = FrameRateChange (50, best);
168         BOOST_CHECK_EQUAL (best, 50);
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 = 48;
175         best = film->playlist()->best_dcp_frame_rate ();
176         frc = FrameRateChange (48, best);
177         BOOST_CHECK_EQUAL (best, 48);
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         /* Check some out-there conversions (not the best) */
184         
185         frc = FrameRateChange (14.99, 24);
186         BOOST_CHECK_EQUAL (frc.skip, false);
187         BOOST_CHECK_EQUAL (frc.repeat, 2);
188         BOOST_CHECK_EQUAL (frc.change_speed, true);
189         BOOST_CHECK_CLOSE (frc.speed_up, 24 / (2 * 14.99), 0.1);
190
191         /* Check some conversions with limited DCP targets */
192
193         afr.clear ();
194         afr.push_back (24);
195         Config::instance()->set_allowed_dcp_frame_rates (afr);
196
197         content->_video_frame_rate = 25;
198         best = film->playlist()->best_dcp_frame_rate ();
199         frc = FrameRateChange (25, best);
200         BOOST_CHECK_EQUAL (best, 24);
201         BOOST_CHECK_EQUAL (frc.skip, false);
202         BOOST_CHECK_EQUAL (frc.repeat, 1);
203         BOOST_CHECK_EQUAL (frc.change_speed, true);
204         BOOST_CHECK_CLOSE (frc.speed_up, 24.0 / 25, 0.1);
205 }
206
207 /* Test Playlist::best_dcp_frame_rate and FrameRateChange
208    with two pieces of content.
209 */
210 BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_double)
211 {
212         shared_ptr<Film> film = new_test_film ("best_dcp_frame_rate_test_double");
213         /* Get any old content, it doesn't matter what */
214         shared_ptr<FFmpegContent> A (new FFmpegContent (film, "test/data/test.mp4"));
215         film->add_content (A);
216         shared_ptr<FFmpegContent> B (new FFmpegContent (film, "test/data/test.mp4"));
217         film->add_content (B);
218         wait_for_jobs ();
219
220         /* Run some tests with a limited range of allowed rates */
221         
222         std::list<int> afr;
223         afr.push_back (24);
224         afr.push_back (25);
225         afr.push_back (30);
226         Config::instance()->set_allowed_dcp_frame_rates (afr);
227
228         A->_video_frame_rate = 30;
229         B->_video_frame_rate = 24;
230         BOOST_CHECK_EQUAL (film->playlist()->best_dcp_frame_rate(), 25);
231 }
232
233
234 BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
235 {
236         shared_ptr<Film> film = new_test_film ("audio_sampling_rate_test");
237         /* Get any piece of content, it doesn't matter what */
238         shared_ptr<FFmpegContent> content (new FFmpegContent (film, "test/data/test.mp4"));
239         film->add_content (content);
240         wait_for_jobs ();
241         
242         std::list<int> afr;
243         afr.push_back (24);
244         afr.push_back (25);
245         afr.push_back (30);
246         Config::instance()->set_allowed_dcp_frame_rates (afr);
247
248         content->_video_frame_rate = 24;
249         film->set_video_frame_rate (24);
250         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
251         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 48000);
252
253         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
254         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 48000);
255
256         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 80000, 0)));
257         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 96000);
258
259         content->_video_frame_rate = 23.976;
260         film->set_video_frame_rate (24);
261         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
262         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 47952);
263
264         content->_video_frame_rate = 29.97;
265         film->set_video_frame_rate (30);
266         BOOST_CHECK_EQUAL (film->video_frame_rate (), 30);
267         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
268         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 47952);
269
270         content->_video_frame_rate = 25;
271         film->set_video_frame_rate (24);
272         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
273         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 50000);
274
275         content->_video_frame_rate = 25;
276         film->set_video_frame_rate (24);
277         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
278         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 50000);
279
280         /* Check some out-there conversions (not the best) */
281         
282         content->_video_frame_rate = 14.99;
283         film->set_video_frame_rate (25);
284         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 16000, 0)));
285         /* The FrameRateChange within output_audio_frame_rate should choose to double-up
286            the 14.99 fps video to 30 and then run it slow at 25.
287         */
288         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), rint (48000 * 2 * 14.99 / 25));
289 }
290