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