Express trims using ContentTime so that they do not change
[dcpomatic.git] / test / time_calculation_test.cc
1 /*
2     Copyright (C) 2015 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 "lib/film.h"
21 #include "lib/ffmpeg_content.h"
22 #include "lib/player.h"
23 #include "test.h"
24 #include <boost/test/unit_test.hpp>
25
26 using std::string;
27 using std::list;
28 using boost::shared_ptr;
29
30 static string const xml = "<Content>"
31         "<Type>FFmpeg</Type>"
32         "<BurnSubtitles>0</BurnSubtitles>"
33         "<BitsPerPixel>8</BitsPerPixel>"
34         "<Path>/home/c.hetherington/DCP/clapperboard.mp4</Path>"
35         "<Digest>2760e03c7251480f7f02c01a907792673784335</Digest>"
36         "<Position>0</Position>"
37         "<TrimStart>0</TrimStart>"
38         "<TrimEnd>0</TrimEnd>"
39         "<VideoLength>1353600</VideoLength>"
40         "<VideoWidth>1280</VideoWidth>"
41         "<VideoHeight>720</VideoHeight>"
42         "<VideoFrameRate>25</VideoFrameRate>"
43         "<VideoFrameType>0</VideoFrameType>"
44         "<LeftCrop>0</LeftCrop>"
45         "<RightCrop>0</RightCrop>"
46         "<TopCrop>0</TopCrop>"
47         "<BottomCrop>0</BottomCrop>"
48         "<Scale>"
49         "<Ratio>178</Ratio>"
50         "</Scale>"
51         "<ColourConversion>"
52         "<InputTransferFunction>"
53         "<Type>ModifiedGamma</Type>"
54         "<Power>2.222222222222222</Power>"
55         "<Threshold>0.081</Threshold>"
56         "<A>0.099</A>"
57         "<B>4.5</B>"
58         "</InputTransferFunction>"
59         "<RedX>0.64</RedX>"
60         "<RedY>0.33</RedY>"
61         "<GreenX>0.3</GreenX>"
62         "<GreenY>0.6</GreenY>"
63         "<BlueX>0.15</BlueX>"
64         "<BlueY>0.06</BlueY>"
65         "<WhiteX>0.3127</WhiteX>"
66         "<WhiteY>0.329</WhiteY>"
67         "<OutputGamma>2.6</OutputGamma>"
68         "</ColourConversion>"
69         "<FadeIn>0</FadeIn>"
70         "<FadeOut>0</FadeOut>"
71         "<AudioGain>0</AudioGain>"
72         "<AudioDelay>0</AudioDelay>"
73         "<UseSubtitles>0</UseSubtitles>"
74         "<SubtitleXOffset>0</SubtitleXOffset>"
75         "<SubtitleYOffset>0</SubtitleYOffset>"
76         "<SubtitleXScale>1</SubtitleXScale>"
77         "<SubtitleYScale>1</SubtitleYScale>"
78         "<SubtitleLanguage></SubtitleLanguage>"
79         "<AudioStream>"
80         "<Selected>1</Selected>"
81         "<Name>und; 2 channels</Name>"
82         "<Id>2</Id>"
83         "<FrameRate>44100</FrameRate>"
84         "<Channels>2</Channels>"
85         "<FirstAudio>0</FirstAudio>"
86         "<Mapping>"
87         "<InputChannels>2</InputChannels>"
88         "<OutputChannels>12</OutputChannels>"
89         "<Gain Input=\"0\" Output=\"0\">1</Gain>"
90         "<Gain Input=\"0\" Output=\"1\">0</Gain>"
91         "<Gain Input=\"0\" Output=\"2\">0</Gain>"
92         "<Gain Input=\"0\" Output=\"3\">0</Gain>"
93         "<Gain Input=\"0\" Output=\"4\">0</Gain>"
94         "<Gain Input=\"0\" Output=\"5\">0</Gain>"
95         "<Gain Input=\"0\" Output=\"6\">0</Gain>"
96         "<Gain Input=\"0\" Output=\"7\">0</Gain>"
97         "<Gain Input=\"0\" Output=\"8\">0</Gain>"
98         "<Gain Input=\"0\" Output=\"9\">0</Gain>"
99         "<Gain Input=\"0\" Output=\"10\">0</Gain>"
100         "<Gain Input=\"0\" Output=\"11\">0</Gain>"
101         "<Gain Input=\"1\" Output=\"0\">0</Gain>"
102         "<Gain Input=\"1\" Output=\"1\">1</Gain>"
103         "<Gain Input=\"1\" Output=\"2\">0</Gain>"
104         "<Gain Input=\"1\" Output=\"3\">0</Gain>"
105         "<Gain Input=\"1\" Output=\"4\">0</Gain>"
106         "<Gain Input=\"1\" Output=\"5\">0</Gain>"
107         "<Gain Input=\"1\" Output=\"6\">0</Gain>"
108         "<Gain Input=\"1\" Output=\"7\">0</Gain>"
109         "<Gain Input=\"1\" Output=\"8\">0</Gain>"
110         "<Gain Input=\"1\" Output=\"9\">0</Gain>"
111         "<Gain Input=\"1\" Output=\"10\">0</Gain>"
112         "<Gain Input=\"1\" Output=\"11\">0</Gain>"
113         "</Mapping>"
114         "</AudioStream>"
115         "<FirstVideo>0</FirstVideo>"
116         "</Content>";
117
118 BOOST_AUTO_TEST_CASE (ffmpeg_time_calculation_test)
119 {
120         shared_ptr<Film> film = new_test_film ("ffmpeg_time_calculation_test");
121
122         shared_ptr<cxml::Document> doc (new cxml::Document);
123         doc->read_string (xml);
124
125         list<string> notes;
126         shared_ptr<FFmpegContent> content (new FFmpegContent (film, doc, film->state_version(), notes));
127
128         /* 25fps content, 25fps DCP */
129         film->set_video_frame_rate (25);
130         BOOST_CHECK_EQUAL (content->full_length(), DCPTime::from_seconds (content->video_length() / 25.0));
131         /* 25fps content, 24fps DCP; length should be increased */
132         film->set_video_frame_rate (24);
133         BOOST_CHECK_EQUAL (content->full_length(), DCPTime::from_seconds (content->video_length() / 24.0));
134         /* 25fps content, 30fps DCP; length should be decreased */
135         film->set_video_frame_rate (30);
136         BOOST_CHECK_EQUAL (content->full_length(), DCPTime::from_seconds (content->video_length() / 30.0));
137         /* 25fps content, 50fps DCP; length should be the same */
138         film->set_video_frame_rate (50);
139         BOOST_CHECK_EQUAL (content->full_length(), DCPTime::from_seconds (content->video_length() / 25.0));
140         /* 25fps content, 60fps DCP; length should be decreased */
141         film->set_video_frame_rate (60);
142         BOOST_CHECK_EQUAL (content->full_length(), DCPTime::from_seconds (content->video_length() * (50.0 / 60) / 25.0));
143 }
144
145 /** Test Player::dcp_to_content_video */
146 BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
147 {
148         shared_ptr<Film> film = new_test_film ("player_time_calculation_test1");
149
150         shared_ptr<cxml::Document> doc (new cxml::Document);
151         doc->read_string (xml);
152
153         list<string> notes;
154         shared_ptr<FFmpegContent> content (new FFmpegContent (film, doc, film->state_version(), notes));
155         film->set_sequence_video (false);
156         film->add_content (content);
157
158         shared_ptr<Player> player (new Player (film, film->playlist ()));
159
160         /* Position 0, no trim, content rate = DCP rate */
161         content->set_position (DCPTime ());
162         content->set_trim_start (ContentTime ());
163         content->set_video_frame_rate (24);
164         film->set_video_frame_rate (24);
165         player->setup_pieces ();
166         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
167         shared_ptr<Piece> piece = player->_pieces.front ();
168         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
169         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.5)), 12);
170         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 72);
171
172         /* Position 3s, no trim, content rate = DCP rate */
173         content->set_position (DCPTime::from_seconds (3));
174         content->set_trim_start (ContentTime ());
175         content->set_video_frame_rate (24);
176         film->set_video_frame_rate (24);
177         player->setup_pieces ();
178         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
179         piece = player->_pieces.front ();
180         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
181         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
182         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),   0);
183         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  36);
184         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 162);
185
186         /* Position 3s, 1.5s trim, content rate = DCP rate */
187         content->set_position (DCPTime::from_seconds (3));
188         content->set_trim_start (ContentTime::from_seconds (1.5));
189         content->set_video_frame_rate (24);
190         film->set_video_frame_rate (24);
191         player->setup_pieces ();
192         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
193         piece = player->_pieces.front ();
194         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
195         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
196         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),  36);
197         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  72);
198         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 198);
199
200         /* Position 0, no trim, content rate 24, DCP rate 25.
201            Now, for example, a DCPTime position of 3s means 3s at 25fps.  Since we run the video
202            fast (at 25fps) in this case, this means 75 frames of content video will be used.
203         */
204         content->set_position (DCPTime ());
205         content->set_trim_start (ContentTime ());
206         content->set_video_frame_rate (24);
207         film->set_video_frame_rate (25);
208         player->setup_pieces ();
209         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
210         piece = player->_pieces.front ();
211         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
212         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.6)), 15);
213         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 75);
214
215         /* Position 3s, no trim, content rate 24, DCP rate 25 */
216         content->set_position (DCPTime::from_seconds (3));
217         content->set_trim_start (ContentTime ());
218         content->set_video_frame_rate (24);
219         film->set_video_frame_rate (25);
220         player->setup_pieces ();
221         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
222         piece = player->_pieces.front ();
223         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
224         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.60)),   0);
225         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),   0);
226         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.60)),  40);
227         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 169);
228
229         /* Position 3s, 1.6s trim, content rate 24, DCP rate 25.  Here the trim is in ContentTime,
230            so it's 1.6s at 24fps.
231          */
232         content->set_position (DCPTime::from_seconds (3));
233         content->set_trim_start (ContentTime::from_seconds (1.6));
234         content->set_video_frame_rate (24);
235         film->set_video_frame_rate (25);
236         player->setup_pieces ();
237         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
238         piece = player->_pieces.front ();
239         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
240         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.60)),   0);
241         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),  38);
242         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.60)),  78);
243         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 207);
244
245         /* Position 0, no trim, content rate 24, DCP rate 48
246            Now, for example, a DCPTime position of 3s means 3s at 48fps.  Since we run the video
247            with repeated frames in this case, 3 * 24 frames of content video will
248            be used to make 3 * 48 frames of DCP video.  The results should be the same as the
249            content rate = DCP rate case.
250         */
251         content->set_position (DCPTime ());
252         content->set_trim_start (ContentTime ());
253         content->set_video_frame_rate (24);
254         film->set_video_frame_rate (48);
255         player->setup_pieces ();
256         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
257         piece = player->_pieces.front ();
258         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
259         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.5)), 12);
260         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 72);
261
262         /* Position 3s, no trim, content rate 24, DCP rate 48 */
263         content->set_position (DCPTime::from_seconds (3));
264         content->set_trim_start (ContentTime ());
265         content->set_video_frame_rate (24);
266         film->set_video_frame_rate (48);
267         player->setup_pieces ();
268         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
269         piece = player->_pieces.front ();
270         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
271         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
272         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),   0);
273         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  36);
274         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 162);
275
276         /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
277         content->set_position (DCPTime::from_seconds (3));
278         content->set_trim_start (ContentTime::from_seconds (1.5));
279         content->set_video_frame_rate (24);
280         film->set_video_frame_rate (48);
281         player->setup_pieces ();
282         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
283         piece = player->_pieces.front ();
284         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
285         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
286         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),  36);
287         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  72);
288         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 198);
289
290         /* Position 0, no trim, content rate 48, DCP rate 24
291            Now, for example, a DCPTime position of 3s means 3s at 24fps.  Since we run the video
292            with skipped frames in this case, 3 * 48 frames of content video will
293            be used to make 3 * 24 frames of DCP video.
294         */
295         content->set_position (DCPTime ());
296         content->set_trim_start (ContentTime ());
297         content->set_video_frame_rate (48);
298         film->set_video_frame_rate (24);
299         player->setup_pieces ();
300         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
301         piece = player->_pieces.front ();
302         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
303         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.5)), 24);
304         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 144);
305
306         /* Position 3s, no trim, content rate 24, DCP rate 48 */
307         content->set_position (DCPTime::from_seconds (3));
308         content->set_trim_start (ContentTime ());
309         content->set_video_frame_rate (48);
310         film->set_video_frame_rate (24);
311         player->setup_pieces ();
312         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
313         piece = player->_pieces.front ();
314         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
315         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
316         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),   0);
317         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  72);
318         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 324);
319
320         /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
321         content->set_position (DCPTime::from_seconds (3));
322         content->set_trim_start (ContentTime::from_seconds (1.5));
323         content->set_video_frame_rate (48);
324         film->set_video_frame_rate (24);
325         player->setup_pieces ();
326         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
327         piece = player->_pieces.front ();
328         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
329         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
330         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),  72);
331         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)), 144);
332         BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 396);
333 }
334
335 /** Test Player::content_video_to_dcp */
336 BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
337 {
338         shared_ptr<Film> film = new_test_film ("player_time_calculation_test2");
339
340         shared_ptr<cxml::Document> doc (new cxml::Document);
341         doc->read_string (xml);
342
343         list<string> notes;
344         shared_ptr<FFmpegContent> content (new FFmpegContent (film, doc, film->state_version(), notes));
345         film->set_sequence_video (false);
346         film->add_content (content);
347
348         shared_ptr<Player> player (new Player (film, film->playlist ()));
349
350         /* Position 0, no trim, content rate = DCP rate */
351         content->set_position (DCPTime ());
352         content->set_trim_start (ContentTime ());
353         content->set_video_frame_rate (24);
354         film->set_video_frame_rate (24);
355         player->setup_pieces ();
356         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
357         shared_ptr<Piece> piece = player->_pieces.front ();
358         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime ());
359         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 12), DCPTime::from_seconds (0.5));
360         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (3.0));
361
362         /* Position 3s, no trim, content rate = DCP rate */
363         content->set_position (DCPTime::from_seconds (3));
364         content->set_trim_start (ContentTime ());
365         content->set_video_frame_rate (24);
366         film->set_video_frame_rate (24);
367         player->setup_pieces ();
368         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
369         piece = player->_pieces.front ();
370         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (3.00));
371         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 36), DCPTime::from_seconds (4.50));
372         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 162), DCPTime::from_seconds (9.75));
373
374         /* Position 3s, 1.5s trim, content rate = DCP rate */
375         content->set_position (DCPTime::from_seconds (3));
376         content->set_trim_start (ContentTime::from_seconds (1.5));
377         content->set_video_frame_rate (24);
378         film->set_video_frame_rate (24);
379         player->setup_pieces ();
380         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
381         piece = player->_pieces.front ();
382         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (1.50));
383         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 36), DCPTime::from_seconds (3.00));
384         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (4.50));
385         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 198), DCPTime::from_seconds (9.75));
386
387         /* Position 0, no trim, content rate 24, DCP rate 25.
388            Now, for example, a DCPTime position of 3s means 3s at 25fps.  Since we run the video
389            fast (at 25fps) in this case, this means 75 frames of content video will be used.
390         */
391         content->set_position (DCPTime ());
392         content->set_trim_start (ContentTime ());
393         content->set_video_frame_rate (24);
394         film->set_video_frame_rate (25);
395         player->setup_pieces ();
396         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
397         piece = player->_pieces.front ();
398         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime ());
399         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 15), DCPTime::from_seconds (0.6));
400         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 75), DCPTime::from_seconds (3.0));
401
402         /* Position 3s, no trim, content rate 24, DCP rate 25 */
403         content->set_position (DCPTime::from_seconds (3));
404         content->set_trim_start (ContentTime ());
405         content->set_video_frame_rate (24);
406         film->set_video_frame_rate (25);
407         player->setup_pieces ();
408         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
409         piece = player->_pieces.front ();
410         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (3.00));
411         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 40), DCPTime::from_seconds (4.60));
412         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 169), DCPTime::from_seconds (9.76));
413
414         /* Position 3s, 1.6s trim, content rate 24, DCP rate 25, so the 1.6s trim is at 24fps */
415         content->set_position (DCPTime::from_seconds (3));
416         content->set_trim_start (ContentTime::from_seconds (1.6));
417         content->set_video_frame_rate (24);
418         film->set_video_frame_rate (25);
419         player->setup_pieces ();
420         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
421         piece = player->_pieces.front ();
422         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (1.464));
423         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 40), DCPTime::from_seconds (3.064));
424         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 80), DCPTime::from_seconds (4.664));
425         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 209), DCPTime::from_seconds (9.824));
426
427         /* Position 0, no trim, content rate 24, DCP rate 48
428            Now, for example, a DCPTime position of 3s means 3s at 48fps.  Since we run the video
429            with repeated frames in this case, 3 * 24 frames of content video will
430            be used to make 3 * 48 frames of DCP video.  The results should be the same as the
431            content rate = DCP rate case.
432         */
433         content->set_position (DCPTime ());
434         content->set_trim_start (ContentTime ());
435         content->set_video_frame_rate (24);
436         film->set_video_frame_rate (48);
437         player->setup_pieces ();
438         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
439         piece = player->_pieces.front ();
440         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime ());
441         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 12), DCPTime::from_seconds (0.5));
442         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (3.0));
443
444         /* Position 3s, no trim, content rate 24, DCP rate 48 */
445         content->set_position (DCPTime::from_seconds (3));
446         content->set_trim_start (ContentTime ());
447         content->set_video_frame_rate (24);
448         film->set_video_frame_rate (48);
449         player->setup_pieces ();
450         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
451         piece = player->_pieces.front ();
452         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (3.00));
453         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 36), DCPTime::from_seconds (4.50));
454         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 162), DCPTime::from_seconds (9.75));
455
456         /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
457         content->set_position (DCPTime::from_seconds (3));
458         content->set_trim_start (ContentTime::from_seconds (1.5));
459         content->set_video_frame_rate (24);
460         film->set_video_frame_rate (48);
461         player->setup_pieces ();
462         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
463         piece = player->_pieces.front ();
464         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (1.50));
465         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 36), DCPTime::from_seconds (3.00));
466         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (4.50));
467         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 198), DCPTime::from_seconds (9.75));
468
469         /* Position 0, no trim, content rate 48, DCP rate 24
470            Now, for example, a DCPTime position of 3s means 3s at 24fps.  Since we run the video
471            with skipped frames in this case, 3 * 48 frames of content video will
472            be used to make 3 * 24 frames of DCP video.
473         */
474         content->set_position (DCPTime ());
475         content->set_trim_start (ContentTime ());
476         content->set_video_frame_rate (48);
477         film->set_video_frame_rate (24);
478         player->setup_pieces ();
479         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
480         piece = player->_pieces.front ();
481         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime ());
482         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 24), DCPTime::from_seconds (0.5));
483         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 144), DCPTime::from_seconds (3.0));
484
485         /* Position 3s, no trim, content rate 24, DCP rate 48 */
486         content->set_position (DCPTime::from_seconds (3));
487         content->set_trim_start (ContentTime ());
488         content->set_video_frame_rate (48);
489         film->set_video_frame_rate (24);
490         player->setup_pieces ();
491         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
492         piece = player->_pieces.front ();
493         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (3.00));
494         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (4.50));
495         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 324), DCPTime::from_seconds (9.75));
496
497         /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
498         content->set_position (DCPTime::from_seconds (3));
499         content->set_trim_start (ContentTime::from_seconds (1.5));
500         content->set_video_frame_rate (48);
501         film->set_video_frame_rate (24);
502         player->setup_pieces ();
503         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
504         piece = player->_pieces.front ();
505         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (1.50));
506         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (3.00));
507         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 144), DCPTime::from_seconds (4.50));
508         BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 396), DCPTime::from_seconds (9.75));
509 }
510
511 /** Test Player::dcp_to_content_audio */
512 BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
513 {
514         shared_ptr<Film> film = new_test_film ("player_time_calculation_test3");
515
516         shared_ptr<cxml::Document> doc (new cxml::Document);
517         doc->read_string (xml);
518
519         list<string> notes;
520         shared_ptr<FFmpegContent> content (new FFmpegContent (film, doc, film->state_version(), notes));
521         AudioStreamPtr stream = content->audio_streams().front();
522         film->set_sequence_video (false);
523         film->add_content (content);
524
525         shared_ptr<Player> player (new Player (film, film->playlist ()));
526
527         /* Position 0, no trim, video/audio content rate = video/audio DCP rate */
528         content->set_position (DCPTime ());
529         content->set_trim_start (ContentTime ());
530         content->set_video_frame_rate (24);
531         film->set_video_frame_rate (24);
532         stream->_frame_rate = 48000;
533         player->setup_pieces ();
534         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
535         shared_ptr<Piece> piece = player->_pieces.front ();
536         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
537         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.5)),  24000);
538         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 144000);
539
540         /* Position 3s, no trim, video/audio content rate = video/audio DCP rate */
541         content->set_position (DCPTime::from_seconds (3));
542         content->set_trim_start (ContentTime ());
543         content->set_video_frame_rate (24);
544         film->set_video_frame_rate (24);
545         stream->_frame_rate = 48000;
546         player->setup_pieces ();
547         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
548         piece = player->_pieces.front ();
549         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
550         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
551         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
552         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)),  72000);
553         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 324000);
554
555         /* Position 3s, 1.5s trim, video/audio content rate = video/audio DCP rate */
556         content->set_position (DCPTime::from_seconds (3));
557         content->set_trim_start (ContentTime::from_seconds (1.5));
558         content->set_video_frame_rate (24);
559         film->set_video_frame_rate (24);
560         stream->_frame_rate = 48000;
561         player->setup_pieces ();
562         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
563         piece = player->_pieces.front ();
564         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
565         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),   0);
566         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  72000);
567         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)), 144000);
568         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 396000);
569
570         /* Position 0, no trim, content video rate 24, DCP video rate 25, both audio rates still 48k.
571            Now we are resampling the audio so that 48000 content samples become 46080 DCP samples
572            (sounding the same and still corresponding to 1 second) which are then played over 24/25s
573            so that they run fast.  Hence 1 second in the DCP uses (25/24) * 48000 content samples.
574         */
575         content->set_position (DCPTime ());
576         content->set_trim_start (ContentTime ());
577         content->set_video_frame_rate (24);
578         film->set_video_frame_rate (25);
579         stream->_frame_rate = 48000;
580         player->setup_pieces ();
581         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
582         piece = player->_pieces.front ();
583         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
584         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.6)),  30000);
585         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 150000);
586
587         /* Position 3s, no trim, content video rate 24, DCP rate 25, both audio rates still 48k. */
588         content->set_position (DCPTime::from_seconds (3));
589         content->set_trim_start (ContentTime ());
590         content->set_video_frame_rate (24);
591         film->set_video_frame_rate (25);
592         stream->_frame_rate = 48000;
593         player->setup_pieces ();
594         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
595         piece = player->_pieces.front ();
596         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
597         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.60)),      0);
598         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
599         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.60)),  80000);
600         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 337500);
601
602         /* Position 3s, 1.6s trim, content rate 24, DCP rate 25, both audio rates still 48k */
603         content->set_position (DCPTime::from_seconds (3));
604         content->set_trim_start (ContentTime::from_seconds (1.6));
605         content->set_video_frame_rate (24);
606         film->set_video_frame_rate (25);
607         stream->_frame_rate = 48000;
608         player->setup_pieces ();
609         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
610         piece = player->_pieces.front ();
611         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
612         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.60)),      0);
613         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  76800);
614         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.60)), 156800);
615         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 414300);
616
617         /* Position 0, no trim, content rate 24, DCP rate 48, both audio rates still 48k.
618            Now, for example, a DCPTime position of 3s means 3s at 48fps.  Since we run the video
619            with repeated frames in this case, audio samples will map straight through.
620            The results should be the same as the content rate = DCP rate case.
621         */
622         content->set_position (DCPTime ());
623         content->set_trim_start (ContentTime ());
624         content->set_video_frame_rate (24);
625         film->set_video_frame_rate (48);
626         stream->_frame_rate = 48000;
627         player->setup_pieces ();
628         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
629         piece = player->_pieces.front ();
630         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
631         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.5)),  24000);
632         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 144000);
633
634         /* Position 3s, no trim, content rate 24, DCP rate 48 */
635         content->set_position (DCPTime::from_seconds (3));
636         content->set_trim_start (ContentTime ());
637         content->set_video_frame_rate (24);
638         film->set_video_frame_rate (24);
639         stream->_frame_rate = 48000;
640         player->setup_pieces ();
641         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
642         piece = player->_pieces.front ();
643         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
644         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
645         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
646         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)),  72000);
647         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 324000);
648
649         /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
650         content->set_position (DCPTime::from_seconds (3));
651         content->set_trim_start (ContentTime::from_seconds (1.5));
652         content->set_video_frame_rate (24);
653         film->set_video_frame_rate (24);
654         stream->_frame_rate = 48000;
655         player->setup_pieces ();
656         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
657         piece = player->_pieces.front ();
658         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
659         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),   0);
660         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  72000);
661         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)), 144000);
662         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 396000);
663
664         /* Position 0, no trim, content rate 48, DCP rate 24
665            Now, for example, a DCPTime position of 3s means 3s at 24fps.  Since we run the video
666            with skipped frames in this case, audio samples should map straight through.
667         */
668         content->set_position (DCPTime ());
669         content->set_trim_start (ContentTime ());
670         content->set_video_frame_rate (24);
671         film->set_video_frame_rate (48);
672         stream->_frame_rate = 48000;
673         player->setup_pieces ();
674         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
675         piece = player->_pieces.front ();
676         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
677         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.5)),  24000);
678         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 144000);
679
680         /* Position 3s, no trim, content rate 24, DCP rate 48 */
681         content->set_position (DCPTime::from_seconds (3));
682         content->set_trim_start (ContentTime ());
683         content->set_video_frame_rate (24);
684         film->set_video_frame_rate (24);
685         stream->_frame_rate = 48000;
686         player->setup_pieces ();
687         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
688         piece = player->_pieces.front ();
689         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
690         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
691         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
692         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)),  72000);
693         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 324000);
694
695         /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
696         content->set_position (DCPTime::from_seconds (3));
697         content->set_trim_start (ContentTime::from_seconds (1.5));
698         content->set_video_frame_rate (24);
699         film->set_video_frame_rate (24);
700         stream->_frame_rate = 48000;
701         player->setup_pieces ();
702         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
703         piece = player->_pieces.front ();
704         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
705         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),   0);
706         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  72000);
707         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)), 144000);
708         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 396000);
709
710         /* Position 0, no trim, video content rate = video DCP rate, content audio rate = 44.1k
711            Now 44100 content samples correspond to 1s.
712         */
713         content->set_position (DCPTime ());
714         content->set_trim_start (ContentTime ());
715         content->set_video_frame_rate (24);
716         film->set_video_frame_rate (24);
717         stream->_frame_rate = 44100;
718         player->setup_pieces ();
719         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
720         piece = player->_pieces.front ();
721         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
722         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.5)),  22050);
723         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 132300);
724
725         /* Position 3s, no trim, video content rate = video DCP rate, content audio rate = 44.1k */
726         content->set_position (DCPTime::from_seconds (3));
727         content->set_trim_start (ContentTime ());
728         content->set_video_frame_rate (24);
729         film->set_video_frame_rate (24);
730         stream->_frame_rate = 44100;
731         player->setup_pieces ();
732         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
733         piece = player->_pieces.front ();
734         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
735         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
736         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
737         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)),  66150);
738         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 297675);
739
740         /* Position 3s, 1.5s trim, video content rate = video DCP rate, content audio rate = 44.1k */
741         content->set_position (DCPTime::from_seconds (3));
742         content->set_trim_start (ContentTime::from_seconds (1.5));
743         content->set_video_frame_rate (24);
744         film->set_video_frame_rate (24);
745         stream->_frame_rate = 44100;
746         player->setup_pieces ();
747         BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
748         piece = player->_pieces.front ();
749         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
750         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
751         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  66150);
752         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)), 132300);
753         BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 363825);
754 }