0e5fd0259d8549ad3a9a6b1c97775f35df9d1052
[dcpomatic.git] / src / lib / piece.cc
1 /*
2     Copyright (C) 2013-2021 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
22 #include "audio_content.h"
23 #include "content.h"
24 #include "dcp_content.h"
25 #include "dcpomatic_log.h"
26 #include "decoder.h"
27 #include "film.h"
28 #include "piece.h"
29 #include "player_video.h"
30 #include "video_content.h"
31
32
33 using std::dynamic_pointer_cast;
34 using std::make_shared;
35 using std::shared_ptr;
36 using namespace dcpomatic;
37
38
39 Piece::Piece (shared_ptr<Content> c, shared_ptr<Decoder> d, FrameRateChange f)
40         : content (c)
41         , decoder (d)
42         , frc (f)
43 {
44         if (content->audio) {
45                 for (auto j: content->audio->streams()) {
46                         _stream_last_push_end[j] = content->position();
47                 }
48         }
49 }
50
51
52
53 void
54 Piece::update_pull_to (DCPTime& pull_to) const
55 {
56         if (done) {
57                 return;
58         }
59
60         for (auto const& i: _stream_last_push_end) {
61                 pull_to = std::min(pull_to, i.second);
62         }
63 }
64
65
66 void
67 Piece::set_last_push_end (AudioStreamPtr stream, DCPTime end)
68 {
69         DCPOMATIC_ASSERT (_stream_last_push_end.find(stream) != _stream_last_push_end.end());
70         _stream_last_push_end[stream] = end;
71 }
72
73
74 DCPTime
75 Piece::content_video_to_dcp (Frame f) const
76 {
77         /* See comment in resampled_audio_to_dcp */
78         auto const d = DCPTime::from_frames(f * frc.factor(), frc.dcp) - DCPTime(content->trim_start(), frc);
79         return d + content->position();
80 }
81
82
83 DCPTime
84 Piece::resampled_audio_to_dcp (Frame f, shared_ptr<const Film> film) const
85 {
86         /* It might seem more logical here to convert s to a ContentTime (using the FrameRateChange)
87            then convert that ContentTime to frames at the content's rate.  However this fails for
88            situations like content at 29.9978733fps, DCP at 30fps.  The accuracy of the Time type is not
89            enough to distinguish between the two with low values of time (e.g. 3200 in Time units).
90
91            Instead we convert the DCPTime using the DCP video rate then account for any skip/repeat.
92         */
93         return DCPTime::from_frames(f, film->audio_frame_rate())
94                 - DCPTime(content->trim_start(), frc)
95                 + content->position();
96 }
97
98
99 ContentTime
100 Piece::dcp_to_content_time (DCPTime t, shared_ptr<const Film> film) const
101 {
102         auto s = t - content->position ();
103         s = min (content->length_after_trim(film), s);
104         return max (ContentTime(), ContentTime(s, frc) + content->trim_start());
105 }
106
107
108 DCPTime
109 Piece::content_time_to_dcp (ContentTime t) const
110 {
111         return max (DCPTime(), DCPTime(t - content->trim_start(), frc) + content->position());
112 }
113
114
115 bool
116 Piece::use_video () const
117 {
118         return content->video && content->video->use();
119 }
120
121
122 VideoFrameType
123 Piece::video_frame_type () const
124 {
125         DCPOMATIC_ASSERT (content->video);
126         return content->video->frame_type ();
127 }
128
129
130 dcpomatic::DCPTime
131 Piece::position () const
132 {
133         return content->position ();
134 }
135
136
137 dcpomatic::DCPTime
138 Piece::end (shared_ptr<const Film> film) const
139 {
140         return content->end (film);
141 }
142
143
144 shared_ptr<PlayerVideo>
145 Piece::player_video (ContentVideo video, shared_ptr<const Film> film, dcp::Size container_size) const
146 {
147         return std::make_shared<PlayerVideo>(
148                 video.image,
149                 content->video->crop (),
150                 content->video->fade (film, video.frame),
151                 scale_for_display(content->video->scaled_size(film->frame_size()), container_size, film->frame_size()),
152                 container_size,
153                 video.eyes,
154                 video.part,
155                 content->video->colour_conversion(),
156                 content->video->range(),
157                 content,
158                 video.frame,
159                 false
160                 );
161 }
162
163
164 int
165 Piece::resampled_audio_frame_rate (shared_ptr<const Film> film) const
166 {
167         DCPOMATIC_ASSERT (content->audio);
168         return content->audio->resampled_frame_rate (film);
169 }
170
171
172 double
173 Piece::audio_gain () const
174 {
175         DCPOMATIC_ASSERT (content->audio);
176         return content->audio->gain();
177 }
178
179
180 shared_ptr<Decoder>
181 Piece::decoder_for (shared_ptr<Content> content_) const
182 {
183         if (content_ == content) {
184                 return decoder;
185         }
186
187         return {};
188 }
189
190
191 DCPTime
192 Piece::decoder_position () const
193 {
194         return content_time_to_dcp(std::max(decoder->position(), content->trim_start()));
195 }
196
197
198 void
199 Piece::pass ()
200 {
201         LOG_DEBUG_PLAYER ("Calling pass() on %1", content->path(0));
202         done = decoder->pass();
203 }
204
205
206 bool
207 Piece::reference_dcp_audio () const
208 {
209         auto dcp = dynamic_pointer_cast<DCPContent>(content);
210         return dcp && dcp->reference_audio();
211 }