Various fixes to seeking with audio.
authorCarl Hetherington <cth@carlh.net>
Wed, 19 Apr 2017 08:24:59 +0000 (09:24 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 19 Apr 2017 22:04:32 +0000 (23:04 +0100)
src/lib/audio_merger.cc
src/lib/ffmpeg_decoder.cc
src/lib/player.cc
src/lib/resampler.cc
src/lib/resampler.h
src/wx/film_viewer.cc

index 4bed4b3a5850539f8617f3ecb4a348889eacb2a8..ecfdfdc27ba54bc0b6cdd65f12a3f185c26297c1 100644 (file)
@@ -64,22 +64,31 @@ AudioMerger::pull (DCPTime time)
        BOOST_FOREACH (Buffer i, _buffers) {
                if (i.period().to <= time) {
                        /* Completely within the pull period */
+                       DCPOMATIC_ASSERT (i.audio->frames() > 0);
                        out.push_back (make_pair (i.audio, i.time));
                } else if (i.time < time) {
                        /* Overlaps the end of the pull period */
                        shared_ptr<AudioBuffers> audio (new AudioBuffers (i.audio->channels(), frames(DCPTime(time - i.time))));
                        audio->copy_from (i.audio.get(), audio->frames(), 0, 0);
+                       DCPOMATIC_ASSERT (audio->frames() > 0);
                        out.push_back (make_pair (audio, i.time));
                        i.audio->trim_start (audio->frames ());
                        i.time += DCPTime::from_frames(audio->frames(), _frame_rate);
+                       DCPOMATIC_ASSERT (i.audio->frames() > 0);
                        new_buffers.push_back (i);
                } else {
                        /* Not involved */
+                       DCPOMATIC_ASSERT (i.audio->frames() > 0);
                        new_buffers.push_back (i);
                }
        }
 
        _buffers = new_buffers;
+
+       for (list<pair<shared_ptr<AudioBuffers>, DCPTime> >::const_iterator i = out.begin(); i != out.end(); ++i) {
+               DCPOMATIC_ASSERT (i->first->frames() > 0);
+       }
+
        return out;
 }
 
@@ -88,6 +97,7 @@ void
 AudioMerger::push (boost::shared_ptr<const AudioBuffers> audio, DCPTime time)
 {
        DCPOMATIC_ASSERT (time >= _last_pull);
+       DCPOMATIC_ASSERT (audio->frames() > 0);
 
        DCPTimePeriod period (time, time + DCPTime::from_frames (audio->frames(), _frame_rate));
 
@@ -129,6 +139,7 @@ AudioMerger::push (boost::shared_ptr<const AudioBuffers> audio, DCPTime time)
 
                if (before == _buffers.end() && after == _buffers.end()) {
                        /* New buffer */
+                       DCPOMATIC_ASSERT (part->frames() > 0);
                        _buffers.push_back (Buffer (part, time, _frame_rate));
                } else if (before != _buffers.end() && after == _buffers.end()) {
                        /* We have an existing buffer before this one; append new data to it */
index 604864a148ffa88fa9875381948a3309b49c5595..4635cd5a38ce5de57679ea1cd27cb94d17084044 100644 (file)
@@ -339,7 +339,9 @@ FFmpegDecoder::seek (ContentTime time, bool accurate)
                avcodec_flush_buffers (video_codec_context());
        }
 
-       /* XXX: should be flushing audio buffers? */
+       BOOST_FOREACH (shared_ptr<FFmpegAudioStream> i, ffmpeg_content()->ffmpeg_audio_streams()) {
+               avcodec_flush_buffers (i->stream(_format_context)->codec);
+       }
 
        if (subtitle_codec_context ()) {
                avcodec_flush_buffers (subtitle_codec_context ());
index 44e2d16526ffddf58425f4c965dc4ee501937857..2a5452e1e300a6503d35b622c1844d463e4abd5d 100644 (file)
@@ -699,6 +699,10 @@ Player::audio_flush (shared_ptr<Piece> piece, AudioStreamPtr stream)
        }
 
        pair<shared_ptr<const AudioBuffers>, Frame> ro = r->flush ();
+       if (ro.first->frames() == 0) {
+               return;
+       }
+
        ContentAudio content_audio;
        content_audio.audio = ro.first;
        content_audio.frame = ro.second;
@@ -713,6 +717,8 @@ Player::audio_flush (shared_ptr<Piece> piece, AudioStreamPtr stream)
 void
 Player::audio_transform (shared_ptr<AudioContent> content, AudioStreamPtr stream, ContentAudio content_audio, DCPTime time)
 {
+       DCPOMATIC_ASSERT (content_audio.audio->frames() > 0);
+
        /* Gain */
 
        if (content->gain() != 0) {
@@ -758,6 +764,8 @@ Player::audio_transform (shared_ptr<AudioContent> content, AudioStreamPtr stream
 void
 Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_audio)
 {
+       DCPOMATIC_ASSERT (content_audio.audio->frames() > 0);
+
        shared_ptr<Piece> piece = wp.lock ();
        if (!piece) {
                return;
@@ -770,6 +778,9 @@ Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_a
        if (stream->frame_rate() != content->resampled_frame_rate()) {
                shared_ptr<Resampler> r = resampler (content, stream, true);
                pair<shared_ptr<const AudioBuffers>, Frame> ro = r->run (content_audio.audio, content_audio.frame);
+               if (ro.first->frames() == 0) {
+                       return;
+               }
                content_audio.audio = ro.first;
                content_audio.frame = ro.second;
        }
@@ -797,6 +808,7 @@ Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_a
                return;
        } else if (end > piece->content->end()) {
                Frame const remaining_frames = DCPTime(piece->content->end() - time).frames_round(_film->audio_frame_rate());
+               DCPOMATIC_ASSERT (remaining_frames > 0);
                shared_ptr<AudioBuffers> cut (new AudioBuffers (content_audio.audio->channels(), remaining_frames));
                cut->copy_from (content_audio.audio.get(), remaining_frames, 0, 0);
                content_audio.audio = cut;
@@ -887,10 +899,15 @@ Player::seek (DCPTime time, bool accurate)
                _audio_processor->flush ();
        }
 
+       for (ResamplerMap::iterator i = _resamplers.begin(); i != _resamplers.end(); ++i) {
+               i->second->flush ();
+               i->second->reset ();
+       }
+
        BOOST_FOREACH (shared_ptr<Piece> i, _pieces) {
+               i->done = false;
                if (i->content->position() <= time && time < i->content->end()) {
                        i->decoder->seek (dcp_to_content_time (i, time), accurate);
-                       i->done = false;
                }
        }
 
index 1a0c6073dcb6cc8278b74007d60b74f226069ba6..4498dccb557533296fc3dd4cb1593a9764848d5d 100644 (file)
@@ -200,3 +200,9 @@ Resampler::flush ()
        delete[] buffer;
        return make_pair (out, _next_out.get ());
 }
+
+void
+Resampler::reset ()
+{
+       src_reset (_src);
+}
index 9d620b96282ecba02139414fa5612a5d070d7d3e..9e9304fb421c7d46ca529702c635a09c67133ed1 100644 (file)
@@ -33,6 +33,7 @@ public:
 
        std::pair<boost::shared_ptr<const AudioBuffers>, Frame> run (boost::shared_ptr<const AudioBuffers>, Frame);
        std::pair<boost::shared_ptr<const AudioBuffers>, Frame> flush ();
+       void reset ();
        void set_fast ();
 
 private:
index 942a0fedcd27717faf146d2599e625ab412948fb..40efdce61d8110012aa0ed52255832b811a14def 100644 (file)
@@ -666,9 +666,15 @@ FilmViewer::seek (DCPTime t, bool accurate)
                return;
        }
 
+       bool const was_running = stop ();
+
        _butler->seek (t, accurate);
        _last_seek_accurate = accurate;
        get ();
+
+       if (was_running) {
+               start ();
+       }
 }
 
 void