C++11 tidying.
[dcpomatic.git] / src / lib / audio_decoder.cc
1 /*
2     Copyright (C) 2012-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_decoder.h"
23 #include "audio_buffers.h"
24 #include "audio_content.h"
25 #include "dcpomatic_log.h"
26 #include "log.h"
27 #include "resampler.h"
28 #include "compose.hpp"
29 #include <iostream>
30
31 #include "i18n.h"
32
33
34 using std::cout;
35 using std::map;
36 using std::pair;
37 using std::shared_ptr;
38 using std::make_shared;
39 using boost::optional;
40 using namespace dcpomatic;
41
42
43 AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, bool fast)
44         : DecoderPart (parent)
45         , _content (content)
46         , _fast (fast)
47 {
48         /* Set up _positions so that we have one for each stream */
49         for (auto i: content->streams ()) {
50                 _positions[i] = 0;
51         }
52 }
53
54
55 /** @param time_already_delayed true if the delay should not be added to time */
56 void
57 AudioDecoder::emit (shared_ptr<const Film> film, AudioStreamPtr stream, shared_ptr<const AudioBuffers> data, ContentTime time, bool time_already_delayed)
58 {
59         if (ignore ()) {
60                 return;
61         }
62
63         /* Amount of error we will tolerate on audio timestamps; see comment below.
64          * We'll use 1 24fps video frame at 48kHz as this seems to be roughly how
65          * ffplay does it.
66          */
67         static Frame const slack_frames = 48000 / 24;
68
69         int const resampled_rate = _content->resampled_frame_rate(film);
70         if (!time_already_delayed) {
71                 time += ContentTime::from_seconds (_content->delay() / 1000.0);
72         }
73
74         auto reset = false;
75         if (_positions[stream] == 0) {
76                 /* This is the first data we have received since initialisation or seek.  Set
77                    the position based on the ContentTime that was given.  After this first time
78                    we just count samples unless the timestamp is more than slack_frames away
79                    from where we think it should be.  This is because ContentTimes seem to be
80                    slightly unreliable from FFmpegDecoder (i.e. not sample accurate), but we still
81                    need to obey them sometimes otherwise we get sync problems such as #1833.
82                 */
83                 if (_content->delay() > 0) {
84                         /* Insert silence to give the delay */
85                         silence (_content->delay ());
86                 }
87                 reset = true;
88         } else if (std::abs(_positions[stream] - time.frames_round(resampled_rate)) > slack_frames) {
89                 reset = true;
90                 LOG_GENERAL (
91                         "Reset audio position: was %1, new data at %2, slack: %3 frames",
92                         _positions[stream],
93                         time.frames_round(resampled_rate),
94                         std::abs(_positions[stream] - time.frames_round(resampled_rate))
95                         );
96         }
97
98         if (reset) {
99                 _positions[stream] = time.frames_round (resampled_rate);
100         }
101
102         shared_ptr<Resampler> resampler;
103         auto i = _resamplers.find(stream);
104         if (i != _resamplers.end()) {
105                 resampler = i->second;
106         } else {
107                 if (stream->frame_rate() != resampled_rate) {
108                         LOG_GENERAL (
109                                 "Creating new resampler from %1 to %2 with %3 channels",
110                                 stream->frame_rate(),
111                                 resampled_rate,
112                                 stream->channels()
113                                 );
114
115                         resampler = make_shared<Resampler>(stream->frame_rate(), resampled_rate, stream->channels());
116                         if (_fast) {
117                                 resampler->set_fast ();
118                         }
119                         _resamplers[stream] = resampler;
120                 }
121         }
122
123         if (resampler) {
124                 auto ro = resampler->run (data);
125                 if (ro->frames() == 0) {
126                         return;
127                 }
128                 data = ro;
129         }
130
131         Data(stream, ContentAudio (data, _positions[stream]));
132         _positions[stream] += data->frames();
133 }
134
135
136 /** @return Time just after the last thing that was emitted from a given stream */
137 ContentTime
138 AudioDecoder::stream_position (shared_ptr<const Film> film, AudioStreamPtr stream) const
139 {
140         auto i = _positions.find (stream);
141         DCPOMATIC_ASSERT (i != _positions.end ());
142         return ContentTime::from_frames (i->second, _content->resampled_frame_rate(film));
143 }
144
145
146 boost::optional<ContentTime>
147 AudioDecoder::position (shared_ptr<const Film> film) const
148 {
149         optional<ContentTime> p;
150         for (auto i: _positions) {
151                 auto const ct = stream_position (film, i.first);
152                 if (!p || ct < *p) {
153                         p = ct;
154                 }
155         }
156
157         return p;
158 }
159
160
161 void
162 AudioDecoder::seek ()
163 {
164         for (auto i: _resamplers) {
165                 i.second->flush ();
166                 i.second->reset ();
167         }
168
169         for (auto& i: _positions) {
170                 i.second = 0;
171         }
172 }
173
174
175 void
176 AudioDecoder::flush ()
177 {
178         for (auto const& i: _resamplers) {
179                 auto ro = i.second->flush ();
180                 if (ro->frames() > 0) {
181                         Data (i.first, ContentAudio (ro, _positions[i.first]));
182                         _positions[i.first] += ro->frames();
183                 }
184         }
185
186         if (_content->delay() < 0) {
187                 /* Finish off with the gap caused by the delay */
188                 silence (-_content->delay ());
189         }
190 }
191
192
193 void
194 AudioDecoder::silence (int milliseconds)
195 {
196         for (auto i: _content->streams()) {
197                 int const samples = ContentTime::from_seconds(milliseconds / 1000.0).frames_round(i->frame_rate());
198                 auto silence = make_shared<AudioBuffers>(i->channels(), samples);
199                 silence->make_silent ();
200                 Data (i, ContentAudio (silence, _positions[i]));
201         }
202 }