Don't overlap simultaneous video content in the timeline. Fix keep-aligned for separ...
[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         FrameRateConversion frc = FrameRateConversion (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         
56         content->_video_frame_rate = 50;
57         best = film->playlist()->best_dcp_frame_rate ();
58         frc = FrameRateConversion (50, best);
59         BOOST_CHECK_EQUAL (best, 25);
60         BOOST_CHECK_EQUAL (frc.skip, true);
61         BOOST_CHECK_EQUAL (frc.repeat, 1);
62         BOOST_CHECK_EQUAL (frc.change_speed, false);
63
64         content->_video_frame_rate = 48;
65         best = film->playlist()->best_dcp_frame_rate ();
66         frc = FrameRateConversion (48, best);
67         BOOST_CHECK_EQUAL (best, 24);
68         BOOST_CHECK_EQUAL (frc.skip, true);
69         BOOST_CHECK_EQUAL (frc.repeat, 1);
70         BOOST_CHECK_EQUAL (frc.change_speed, false);
71
72         content->_video_frame_rate = 30;
73         best = film->playlist()->best_dcp_frame_rate ();
74         frc = FrameRateConversion (30, best);
75         BOOST_CHECK_EQUAL (best, 30);
76         BOOST_CHECK_EQUAL (frc.skip, false);
77         BOOST_CHECK_EQUAL (frc.repeat, 1);
78         BOOST_CHECK_EQUAL (frc.change_speed, false);
79
80         content->_video_frame_rate = 29.97;
81         best = film->playlist()->best_dcp_frame_rate ();
82         frc = FrameRateConversion (29.97, best);
83         BOOST_CHECK_EQUAL (best, 30);
84         BOOST_CHECK_EQUAL (frc.skip, false);
85         BOOST_CHECK_EQUAL (frc.repeat, 1);
86         BOOST_CHECK_EQUAL (frc.change_speed, true);
87         
88         content->_video_frame_rate = 25;
89         best = film->playlist()->best_dcp_frame_rate ();
90         frc = FrameRateConversion (25, best);
91         BOOST_CHECK_EQUAL (best, 25);
92         BOOST_CHECK_EQUAL (frc.skip, false);
93         BOOST_CHECK_EQUAL (frc.repeat, 1);
94         BOOST_CHECK_EQUAL (frc.change_speed, false);
95
96         content->_video_frame_rate = 24;
97         best = film->playlist()->best_dcp_frame_rate ();
98         frc = FrameRateConversion (24, best);
99         BOOST_CHECK_EQUAL (best, 24);
100         BOOST_CHECK_EQUAL (frc.skip, false);
101         BOOST_CHECK_EQUAL (frc.repeat, 1);
102         BOOST_CHECK_EQUAL (frc.change_speed, false);
103
104         content->_video_frame_rate = 14.5;
105         best = film->playlist()->best_dcp_frame_rate ();
106         frc = FrameRateConversion (14.5, best);
107         BOOST_CHECK_EQUAL (best, 30);
108         BOOST_CHECK_EQUAL (frc.skip, false);
109         BOOST_CHECK_EQUAL (frc.repeat, 2);
110         BOOST_CHECK_EQUAL (frc.change_speed, true);
111
112         content->_video_frame_rate = 12.6;
113         best = film->playlist()->best_dcp_frame_rate ();
114         frc = FrameRateConversion (12.6, best);
115         BOOST_CHECK_EQUAL (best, 25);
116         BOOST_CHECK_EQUAL (frc.skip, false);
117         BOOST_CHECK_EQUAL (frc.repeat, 2);
118         BOOST_CHECK_EQUAL (frc.change_speed, true);
119
120         content->_video_frame_rate = 12.4;
121         best = film->playlist()->best_dcp_frame_rate ();
122         frc = FrameRateConversion (12.4, 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
128         content->_video_frame_rate = 12;
129         best = film->playlist()->best_dcp_frame_rate ();
130         frc = FrameRateConversion (12, best);
131         BOOST_CHECK_EQUAL (best, 24);
132         BOOST_CHECK_EQUAL (frc.skip, false);
133         BOOST_CHECK_EQUAL (frc.repeat, 2);
134         BOOST_CHECK_EQUAL (frc.change_speed, false);
135
136         /* Now add some more rates and see if it will use them
137            in preference to skip/repeat.
138         */
139
140         afr.push_back (48);
141         afr.push_back (50);
142         afr.push_back (60);
143         Config::instance()->set_allowed_dcp_frame_rates (afr);
144
145         content->_video_frame_rate = 60;
146         best = film->playlist()->best_dcp_frame_rate ();
147         frc = FrameRateConversion (60, best);
148         BOOST_CHECK_EQUAL (best, 60);
149         BOOST_CHECK_EQUAL (frc.skip, false);
150         BOOST_CHECK_EQUAL (frc.repeat, 1);
151         BOOST_CHECK_EQUAL (frc.change_speed, false);
152         
153         content->_video_frame_rate = 50;
154         best = film->playlist()->best_dcp_frame_rate ();
155         frc = FrameRateConversion (50, best);
156         BOOST_CHECK_EQUAL (best, 50);
157         BOOST_CHECK_EQUAL (frc.skip, false);
158         BOOST_CHECK_EQUAL (frc.repeat, 1);
159         BOOST_CHECK_EQUAL (frc.change_speed, false);
160
161         content->_video_frame_rate = 48;
162         best = film->playlist()->best_dcp_frame_rate ();
163         frc = FrameRateConversion (48, best);
164         BOOST_CHECK_EQUAL (best, 48);
165         BOOST_CHECK_EQUAL (frc.skip, false);
166         BOOST_CHECK_EQUAL (frc.repeat, 1);
167         BOOST_CHECK_EQUAL (frc.change_speed, false);
168
169         /* Check some out-there conversions (not the best) */
170         
171         frc = FrameRateConversion (14.99, 24);
172         BOOST_CHECK_EQUAL (frc.skip, false);
173         BOOST_CHECK_EQUAL (frc.repeat, 2);
174         BOOST_CHECK_EQUAL (frc.change_speed, true);
175
176         /* Check some conversions with limited DCP targets */
177
178         afr.clear ();
179         afr.push_back (24);
180         Config::instance()->set_allowed_dcp_frame_rates (afr);
181
182         content->_video_frame_rate = 25;
183         best = film->playlist()->best_dcp_frame_rate ();
184         frc = FrameRateConversion (25, best);
185         BOOST_CHECK_EQUAL (best, 24);
186         BOOST_CHECK_EQUAL (frc.skip, false);
187         BOOST_CHECK_EQUAL (frc.repeat, 1);
188         BOOST_CHECK_EQUAL (frc.change_speed, true);
189 }
190
191 /* Test Playlist::best_dcp_frame_rate and FrameRateConversion
192    with two pieces of content.
193 */
194 BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_double)
195 {
196         shared_ptr<Film> film = new_test_film ("best_dcp_frame_rate_test_double");
197         /* Get any old content, it doesn't matter what */
198         shared_ptr<FFmpegContent> A (new FFmpegContent (film, "test/data/test.mp4"));
199         film->add_content (A);
200         shared_ptr<FFmpegContent> B (new FFmpegContent (film, "test/data/test.mp4"));
201         film->add_content (B);
202         wait_for_jobs ();
203
204         /* Run some tests with a limited range of allowed rates */
205         
206         std::list<int> afr;
207         afr.push_back (24);
208         afr.push_back (25);
209         afr.push_back (30);
210         Config::instance()->set_allowed_dcp_frame_rates (afr);
211
212         A->_video_frame_rate = 30;
213         B->_video_frame_rate = 24;
214         BOOST_CHECK_EQUAL (film->playlist()->best_dcp_frame_rate(), 25);
215 }
216
217
218 BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
219 {
220         shared_ptr<Film> film = new_test_film ("audio_sampling_rate_test");
221         /* Get any piece of content, it doesn't matter what */
222         shared_ptr<FFmpegContent> content (new FFmpegContent (film, "test/data/test.mp4"));
223         film->add_content (content);
224         wait_for_jobs ();
225         
226         std::list<int> afr;
227         afr.push_back (24);
228         afr.push_back (25);
229         afr.push_back (30);
230         Config::instance()->set_allowed_dcp_frame_rates (afr);
231
232         content->_video_frame_rate = 24;
233         film->set_video_frame_rate (24);
234         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
235         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 48000);
236
237         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
238         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 48000);
239
240         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 80000, 0)));
241         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 96000);
242
243         content->_video_frame_rate = 23.976;
244         film->set_video_frame_rate (24);
245         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
246         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 47952);
247
248         content->_video_frame_rate = 29.97;
249         film->set_video_frame_rate (30);
250         BOOST_CHECK_EQUAL (film->video_frame_rate (), 30);
251         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
252         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 47952);
253
254         content->_video_frame_rate = 25;
255         film->set_video_frame_rate (24);
256         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
257         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 50000);
258
259         content->_video_frame_rate = 25;
260         film->set_video_frame_rate (24);
261         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
262         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 50000);
263
264         /* Check some out-there conversions (not the best) */
265         
266         content->_video_frame_rate = 14.99;
267         film->set_video_frame_rate (25);
268         content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 16000, 0)));
269         /* The FrameRateConversion within output_audio_frame_rate should choose to double-up
270            the 14.99 fps video to 30 and then run it slow at 25.
271         */
272         BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), rint (48000 * 2 * 14.99 / 25));
273 }
274