A previous commit took care to make Decoder::position() not be updated
[dcpomatic.git] / src / lib / audio_decoder.cc
index 4b77a8afbe0a1f56787f110c60c227cdd849b262..4bd6535d81a2888f98af09016652e0642dc1e674 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -37,9 +37,10 @@ using std::pair;
 using boost::shared_ptr;
 using boost::optional;
 
-AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, shared_ptr<Log> log)
+AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, shared_ptr<Log> log, bool fast)
        : DecoderPart (parent, log)
        , _content (content)
+       , _fast (fast)
 {
        /* Set up _positions so that we have one for each stream */
        BOOST_FOREACH (AudioStreamPtr i, content->streams ()) {
@@ -60,6 +61,11 @@ AudioDecoder::emit (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data,
                   we just count samples, as it seems that ContentTimes are unreliable from
                   FFmpegDecoder (not quite continuous; perhaps due to some rounding error).
                */
+               if (_content->delay() > 0) {
+                       /* Insert silence to give the delay */
+                       silence (_content->delay ());
+               }
+               time += ContentTime::from_seconds (_content->delay() / 1000.0);
                _positions[stream] = time.frames_round (stream->frame_rate ());
        }
 
@@ -77,6 +83,9 @@ AudioDecoder::emit (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data,
                                );
 
                        resampler.reset (new Resampler (stream->frame_rate(), _content->resampled_frame_rate(), stream->channels()));
+                       if (_fast) {
+                               resampler->set_fast ();
+                       }
                        _resamplers[stream] = resampler;
                }
        }
@@ -89,16 +98,25 @@ AudioDecoder::emit (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data,
                data = ro;
        }
 
-       Data (stream, ContentAudio (data, _positions[stream]));
+       Data(stream, ContentAudio (data, _positions[stream]));
        _positions[stream] += data->frames();
 }
 
+/** @return Time just after the last thing that was emitted from a given stream */
+ContentTime
+AudioDecoder::stream_position (AudioStreamPtr stream) const
+{
+       map<AudioStreamPtr, Frame>::const_iterator i = _positions.find (stream);
+       DCPOMATIC_ASSERT (i != _positions.end ());
+       return ContentTime::from_frames (i->second, _content->resampled_frame_rate());
+}
+
 ContentTime
 AudioDecoder::position () const
 {
        optional<ContentTime> p;
        for (map<AudioStreamPtr, Frame>::const_iterator i = _positions.begin(); i != _positions.end(); ++i) {
-               ContentTime const ct = ContentTime::from_frames (i->second, _content->resampled_frame_rate());
+               ContentTime const ct = stream_position (i->first);
                if (!p || ct < *p) {
                        p = ct;
                }
@@ -130,4 +148,20 @@ AudioDecoder::flush ()
                        _positions[i->first] += ro->frames();
                }
        }
+
+       if (_content->delay() < 0) {
+               /* Finish off with the gap caused by the delay */
+               silence (-_content->delay ());
+       }
+}
+
+void
+AudioDecoder::silence (int milliseconds)
+{
+       BOOST_FOREACH (AudioStreamPtr i, _content->streams ()) {
+               int const samples = ContentTime::from_seconds(milliseconds / 1000.0).frames_round(i->frame_rate());
+               shared_ptr<AudioBuffers> silence (new AudioBuffers (i->channels(), samples));
+               silence->make_silent ();
+               Data (i, ContentAudio (silence, _positions[i]));
+       }
 }