Add Piece::resampled_audio_frame_rate().
[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 "film.h"
25 #include "piece.h"
26 #include "player_video.h"
27 #include "video_content.h"
28
29
30 using std::shared_ptr;
31 using std::make_shared;
32 using namespace dcpomatic;
33
34
35 Piece::Piece (shared_ptr<Content> c, shared_ptr<Decoder> d, FrameRateChange f)
36         : content (c)
37         , decoder (d)
38         , frc (f)
39 {
40         if (content->audio) {
41                 for (auto j: content->audio->streams()) {
42                         _stream_last_push_end[j] = content->position();
43                 }
44         }
45 }
46
47
48
49 void
50 Piece::update_pull_to (DCPTime& pull_to) const
51 {
52         if (done) {
53                 return;
54         }
55
56         for (auto const& i: _stream_last_push_end) {
57                 pull_to = std::min(pull_to, i.second);
58         }
59 }
60
61
62 void
63 Piece::set_last_push_end (AudioStreamPtr stream, DCPTime end)
64 {
65         DCPOMATIC_ASSERT (_stream_last_push_end.find(stream) != _stream_last_push_end.end());
66         _stream_last_push_end[stream] = end;
67 }
68
69
70 DCPTime
71 Piece::content_video_to_dcp (Frame f) const
72 {
73         /* See comment in resampled_audio_to_dcp */
74         auto const d = DCPTime::from_frames(f * frc.factor(), frc.dcp) - DCPTime(content->trim_start(), frc);
75         return d + content->position();
76 }
77
78
79 DCPTime
80 Piece::resampled_audio_to_dcp (Frame f, shared_ptr<const Film> film) const
81 {
82         /* It might seem more logical here to convert s to a ContentTime (using the FrameRateChange)
83            then convert that ContentTime to frames at the content's rate.  However this fails for
84            situations like content at 29.9978733fps, DCP at 30fps.  The accuracy of the Time type is not
85            enough to distinguish between the two with low values of time (e.g. 3200 in Time units).
86
87            Instead we convert the DCPTime using the DCP video rate then account for any skip/repeat.
88         */
89         return DCPTime::from_frames(f, film->audio_frame_rate())
90                 - DCPTime(content->trim_start(), frc)
91                 + content->position();
92 }
93
94
95 ContentTime
96 Piece::dcp_to_content_time (DCPTime t, shared_ptr<const Film> film) const
97 {
98         auto s = t - content->position ();
99         s = min (content->length_after_trim(film), s);
100         return max (ContentTime(), ContentTime(s, frc) + content->trim_start());
101 }
102
103
104 DCPTime
105 Piece::content_time_to_dcp (ContentTime t) const
106 {
107         return max (DCPTime(), DCPTime(t - content->trim_start(), frc) + content->position());
108 }
109
110
111 bool
112 Piece::use_video () const
113 {
114         return content->video && content->video->use();
115 }
116
117
118 dcpomatic::DCPTime
119 Piece::position () const
120 {
121         return content->position ();
122 }
123
124
125 dcpomatic::DCPTime
126 Piece::end (shared_ptr<const Film> film) const
127 {
128         return content->end (film);
129 }
130
131
132 shared_ptr<PlayerVideo>
133 Piece::player_video (ContentVideo video, shared_ptr<const Film> film, dcp::Size container_size) const
134 {
135         return std::make_shared<PlayerVideo>(
136                 video.image,
137                 content->video->crop (),
138                 content->video->fade (film, video.frame),
139                 scale_for_display(content->video->scaled_size(film->frame_size()), container_size, film->frame_size()),
140                 container_size,
141                 video.eyes,
142                 video.part,
143                 content->video->colour_conversion(),
144                 content->video->range(),
145                 content,
146                 video.frame,
147                 false
148                 );
149 }
150
151
152 int
153 Piece::resampled_audio_frame_rate (shared_ptr<const Film> film) const
154 {
155         DCPOMATIC_ASSERT (content->audio);
156         return content->audio->resampled_frame_rate (film);
157 }
158