Mark .exr as a valid image file.
[dcpomatic.git] / src / lib / audio_decoder.cc
index 4b77a8afbe0a1f56787f110c60c227cdd849b262..5df4047db49e00f579350ffc33efee2c228e4dce 100644 (file)
@@ -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,8 +98,16 @@ AudioDecoder::emit (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data,
                data = ro;
        }
 
-       Data (stream, ContentAudio (data, _positions[stream]));
-       _positions[stream] += data->frames();
+       _positions[stream] += Data(stream, ContentAudio (data, _positions[stream])).get_value_or(0);
+}
+
+/** @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
@@ -98,7 +115,7 @@ 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 +147,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]));
+       }
 }