81d1f4cced413c19aba5113d3e299fc26b08ff5c
[dcpomatic.git] / test / player_test.cc
1 /*
2     Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
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.
10
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.
15
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/>.
18
19 */
20
21 /** @file  test/player_test.cc
22  *  @brief Various tests of Player.
23  */
24
25 #include <iostream>
26 #include <boost/test/unit_test.hpp>
27 #include "lib/film.h"
28 #include "lib/ffmpeg_content.h"
29 #include "lib/dcp_content_type.h"
30 #include "lib/ratio.h"
31 #include "lib/audio_buffers.h"
32 #include "lib/player.h"
33 #include "lib/video_content.h"
34 #include "lib/image_content.h"
35 #include "test.h"
36
37 using std::cout;
38 using std::list;
39 using boost::shared_ptr;
40 using boost::bind;
41
42 static bool
43 valid (Content const *)
44 {
45         return true;
46 }
47
48 /** Player::overlaps */
49 BOOST_AUTO_TEST_CASE (player_overlaps_test)
50 {
51         shared_ptr<Film> film = new_test_film ("player_overlaps_test");
52         film->set_container (Ratio::from_id ("185"));
53
54         /* This content is 3s long */
55         shared_ptr<FFmpegContent> A (new FFmpegContent (film, "test/data/test.mp4"));
56         shared_ptr<FFmpegContent> B (new FFmpegContent (film, "test/data/test.mp4"));
57         shared_ptr<FFmpegContent> C (new FFmpegContent (film, "test/data/test.mp4"));
58
59         film->examine_and_add_content (A);
60         film->examine_and_add_content (B);
61         film->examine_and_add_content (C);
62         wait_for_jobs ();
63
64         BOOST_CHECK_EQUAL (A->full_length().get(), 288000);
65
66         A->set_position (DCPTime::from_seconds (0));
67         B->set_position (DCPTime::from_seconds (10));
68         C->set_position (DCPTime::from_seconds (20));
69
70         shared_ptr<Player> player (new Player (film, film->playlist ()));
71
72         list<shared_ptr<Piece> > o = player->overlaps (DCPTime::from_seconds (0), DCPTime::from_seconds (5), &valid);
73         BOOST_CHECK_EQUAL (o.size(), 1U);
74         BOOST_CHECK_EQUAL (o.front()->content, A);
75
76         o = player->overlaps (DCPTime::from_seconds (5), DCPTime::from_seconds (8), &valid);
77         BOOST_CHECK_EQUAL (o.size(), 0U);
78
79         o = player->overlaps (DCPTime::from_seconds (8), DCPTime::from_seconds (12), &valid);
80         BOOST_CHECK_EQUAL (o.size(), 1U);
81         BOOST_CHECK_EQUAL (o.front()->content, B);
82
83         o = player->overlaps (DCPTime::from_seconds (2), DCPTime::from_seconds (12), &valid);
84         BOOST_CHECK_EQUAL (o.size(), 2U);
85         BOOST_CHECK_EQUAL (o.front()->content, A);
86         BOOST_CHECK_EQUAL (o.back()->content, B);
87
88         o = player->overlaps (DCPTime::from_seconds (8), DCPTime::from_seconds (11), &valid);
89         BOOST_CHECK_EQUAL (o.size(), 1U);
90         BOOST_CHECK_EQUAL (o.front()->content, B);
91 }
92
93 static shared_ptr<AudioBuffers> accumulated;
94
95 static void
96 accumulate (shared_ptr<AudioBuffers> audio, DCPTime t)
97 {
98         cout << "got " << audio->frames() << " @ " << to_string(t) << "\n";
99         BOOST_REQUIRE (accumulated);
100         accumulated->append (audio);
101 }
102
103 /** Check that the Player correctly generates silence when used with a silent FFmpegContent */
104 BOOST_AUTO_TEST_CASE (player_silence_padding_test)
105 {
106         shared_ptr<Film> film = new_test_film ("player_silence_padding_test");
107         film->set_name ("player_silence_padding_test");
108         shared_ptr<FFmpegContent> c (new FFmpegContent (film, "test/data/test.mp4"));
109         film->set_container (Ratio::from_id ("185"));
110         film->set_audio_channels (6);
111
112         film->examine_and_add_content (c);
113         wait_for_jobs ();
114
115         accumulated.reset (new AudioBuffers (film->audio_channels(), 0));
116
117         shared_ptr<Player> player (new Player (film, film->playlist ()));
118         player->Audio.connect (bind (&accumulate, _1, _2));
119         while (!player->pass ()) {}
120         BOOST_REQUIRE (accumulated->frames() >= 48000);
121         BOOST_CHECK_EQUAL (accumulated->channels(), film->audio_channels ());
122
123         for (int i = 0; i < 48000; ++i) {
124                 for (int c = 0; c < accumulated->channels(); ++c) {
125                         BOOST_CHECK_EQUAL (accumulated->data()[c][i], 0);
126                 }
127         }
128 }
129
130 /* Test insertion of black frames between separate bits of video content */
131 BOOST_AUTO_TEST_CASE (player_black_fill_test)
132 {
133         shared_ptr<Film> film = new_test_film ("black_fill_test");
134         film->set_dcp_content_type (DCPContentType::from_isdcf_name ("FTR"));
135         film->set_name ("black_fill_test");
136         film->set_container (Ratio::from_id ("185"));
137         film->set_sequence (false);
138         shared_ptr<ImageContent> contentA (new ImageContent (film, "test/data/simple_testcard_640x480.png"));
139         shared_ptr<ImageContent> contentB (new ImageContent (film, "test/data/simple_testcard_640x480.png"));
140
141         film->examine_and_add_content (contentA);
142         film->examine_and_add_content (contentB);
143         wait_for_jobs ();
144
145         contentA->video->set_scale (VideoContentScale (Ratio::from_id ("185")));
146         contentA->video->set_length (3);
147         contentA->set_position (DCPTime::from_frames (2, film->video_frame_rate ()));
148         contentB->video->set_scale (VideoContentScale (Ratio::from_id ("185")));
149         contentB->video->set_length (1);
150         contentB->set_position (DCPTime::from_frames (7, film->video_frame_rate ()));
151
152         film->make_dcp ();
153
154         wait_for_jobs ();
155
156         boost::filesystem::path ref;
157         ref = "test";
158         ref /= "data";
159         ref /= "black_fill_test";
160
161         boost::filesystem::path check;
162         check = "build";
163         check /= "test";
164         check /= "black_fill_test";
165         check /= film->dcp_name();
166
167         check_dcp (ref.string(), check.string());
168 }