Fix incorrect reel lengths in some cases; account for emitted data being rejected...
[dcpomatic.git] / src / lib / audio_decoder.cc
1 /*
2     Copyright (C) 2012-2017 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 "log.h"
25 #include "resampler.h"
26 #include "compose.hpp"
27 #include <boost/foreach.hpp>
28 #include <iostream>
29
30 #include "i18n.h"
31
32 #define LOG_GENERAL(...) _log->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL);
33
34 using std::cout;
35 using std::map;
36 using std::pair;
37 using boost::shared_ptr;
38 using boost::optional;
39
40 AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, shared_ptr<Log> log)
41         : DecoderPart (parent, log)
42         , _content (content)
43 {
44         /* Set up _positions so that we have one for each stream */
45         BOOST_FOREACH (AudioStreamPtr i, content->streams ()) {
46                 _positions[i] = 0;
47         }
48 }
49
50 void
51 AudioDecoder::emit (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data, ContentTime time)
52 {
53         if (ignore ()) {
54                 return;
55         }
56
57         if (_positions[stream] == 0) {
58                 /* This is the first data we have received since initialisation or seek.  Set
59                    the position based on the ContentTime that was given.  After this first time
60                    we just count samples, as it seems that ContentTimes are unreliable from
61                    FFmpegDecoder (not quite continuous; perhaps due to some rounding error).
62                 */
63                 if (_content->delay() > 0) {
64                         /* Insert silence to give the delay */
65                         silence (_content->delay ());
66                 }
67                 time += ContentTime::from_seconds (_content->delay() / 1000.0);
68                 _positions[stream] = time.frames_round (stream->frame_rate ());
69         }
70
71         shared_ptr<Resampler> resampler;
72         map<AudioStreamPtr, shared_ptr<Resampler> >::iterator i = _resamplers.find(stream);
73         if (i != _resamplers.end ()) {
74                 resampler = i->second;
75         } else {
76                 if (stream->frame_rate() != _content->resampled_frame_rate()) {
77                         LOG_GENERAL (
78                                 "Creating new resampler from %1 to %2 with %3 channels",
79                                 stream->frame_rate(),
80                                 _content->resampled_frame_rate(),
81                                 stream->channels()
82                                 );
83
84                         resampler.reset (new Resampler (stream->frame_rate(), _content->resampled_frame_rate(), stream->channels()));
85                         _resamplers[stream] = resampler;
86                 }
87         }
88
89         if (resampler) {
90                 shared_ptr<const AudioBuffers> ro = resampler->run (data);
91                 if (ro->frames() == 0) {
92                         return;
93                 }
94                 data = ro;
95         }
96
97         _positions[stream] += Data(stream, ContentAudio (data, _positions[stream])).get_value_or(0);
98 }
99
100 /** @return Time just after the last thing that was emitted from a given stream */
101 ContentTime
102 AudioDecoder::stream_position (AudioStreamPtr stream) const
103 {
104         map<AudioStreamPtr, Frame>::const_iterator i = _positions.find (stream);
105         DCPOMATIC_ASSERT (i != _positions.end ());
106         return ContentTime::from_frames (i->second, _content->resampled_frame_rate());
107 }
108
109 ContentTime
110 AudioDecoder::position () const
111 {
112         optional<ContentTime> p;
113         for (map<AudioStreamPtr, Frame>::const_iterator i = _positions.begin(); i != _positions.end(); ++i) {
114                 ContentTime const ct = stream_position (i->first);
115                 if (!p || ct < *p) {
116                         p = ct;
117                 }
118         }
119
120         return p.get_value_or(ContentTime());
121 }
122
123 void
124 AudioDecoder::seek ()
125 {
126         for (map<AudioStreamPtr, shared_ptr<Resampler> >::iterator i = _resamplers.begin(); i != _resamplers.end(); ++i) {
127                 i->second->flush ();
128                 i->second->reset ();
129         }
130
131         for (map<AudioStreamPtr, Frame>::iterator i = _positions.begin(); i != _positions.end(); ++i) {
132                 i->second = 0;
133         }
134 }
135
136 void
137 AudioDecoder::flush ()
138 {
139         for (map<AudioStreamPtr, shared_ptr<Resampler> >::iterator i = _resamplers.begin(); i != _resamplers.end(); ++i) {
140                 shared_ptr<const AudioBuffers> ro = i->second->flush ();
141                 if (ro->frames() > 0) {
142                         Data (i->first, ContentAudio (ro, _positions[i->first]));
143                         _positions[i->first] += ro->frames();
144                 }
145         }
146
147         if (_content->delay() < 0) {
148                 /* Finish off with the gap caused by the delay */
149                 silence (-_content->delay ());
150         }
151 }
152
153 void
154 AudioDecoder::silence (int milliseconds)
155 {
156         BOOST_FOREACH (AudioStreamPtr i, _content->streams ()) {
157                 int const samples = ContentTime::from_seconds(milliseconds / 1000.0).frames_round(i->frame_rate());
158                 shared_ptr<AudioBuffers> silence (new AudioBuffers (i->channels(), samples));
159                 silence->make_silent ();
160                 Data (i, ContentAudio (silence, _positions[i]));
161         }
162 }