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