Fill audio in the Player.
authorCarl Hetherington <cth@carlh.net>
Sat, 13 May 2017 19:50:07 +0000 (20:50 +0100)
committerCarl Hetherington <cth@carlh.net>
Sat, 13 May 2017 19:50:07 +0000 (20:50 +0100)
src/lib/player.cc
src/lib/player.h
src/lib/playlist.cc
src/lib/playlist.h

index a186202db49e1d6f238809b04d0175f087dbd316..d9f03b7a416168813be30f10c82d1150b866fef2 100644 (file)
@@ -538,26 +538,50 @@ Player::pass ()
                }
        }
 
+       /* Fill towards the next thing that might happen (or the end of the playlist).  This is to fill gaps between content,
+          NOT to fill gaps within content (the latter is done in ::video())
+       */
        DCPTime fill_towards = earliest ? earliest_content : _playlist->length();
 
-       optional<DCPTime> fill_from;
-       if (_last_video_time) {
+       /* Work out where to fill video from */
+       optional<DCPTime> video_fill_from;
+       if (_last_video_time && !_playlist->video_content_at(_last_video_time.get())) {
                /* No seek; fill towards the next thing that might happen (or the end of the playlist) */
-               fill_from = _last_video_time;
+               video_fill_from = _last_video_time;
        } else if (_last_seek_time && !_playlist->video_content_at(_last_seek_time.get())) {
                /* Seek into an empty area; fill from the seek time */
-               fill_from = _last_seek_time;
+               video_fill_from = _last_seek_time;
        }
 
        bool filled = false;
-       if (fill_from && ((fill_towards - fill_from.get())) > one_video_frame()) {
-               emit_video (black_player_video_frame(), fill_from.get());
+
+       if (video_fill_from && ((fill_towards - video_fill_from.get())) > one_video_frame()) {
+               emit_video (black_player_video_frame(), video_fill_from.get());
                filled = true;
        } else if (_playlist->length() == DCPTime()) {
+               /* Special case of an empty Film; just give one black frame */
                emit_video (black_player_video_frame(), DCPTime());
                filled = true;
        }
 
+       optional<DCPTime> audio_fill_from;
+       if (_last_audio_time && !_playlist->audio_content_at(_last_audio_time.get())) {
+               /* No seek; fill from the last thing that happened */
+               audio_fill_from = _last_audio_time;
+       } else if (_last_seek_time && !_playlist->audio_content_at(_last_seek_time.get())) {
+               /* Seek into an empty area; fill from the seek time */
+               audio_fill_from = _last_seek_time;
+       }
+
+       if (audio_fill_from && audio_fill_from < fill_towards) {
+               DCPTimePeriod period (audio_fill_from.get(), fill_towards);
+               if (period.duration() > one_video_frame()) {
+                       period.to = period.from + one_video_frame();
+               }
+               fill_audio (period);
+               filled = true;
+       }
+
        if (!earliest && !filled) {
                return true;
        }
@@ -588,8 +612,7 @@ Player::pass ()
                        fill_audio (DCPTimePeriod (_last_audio_time.get(), i->second));
                }
 
-               Audio (i->first, i->second);
-               _last_audio_time = i->second + DCPTime::from_frames(i->first->frames(), _film->audio_frame_rate());
+               emit_audio (i->first, i->second);
        }
 
        return false;
@@ -970,6 +993,13 @@ Player::emit_video (shared_ptr<PlayerVideo> pv, DCPTime time)
        _active_subtitles.clear_before (time);
 }
 
+void
+Player::emit_audio (shared_ptr<AudioBuffers> data, DCPTime time)
+{
+       Audio (data, time);
+       _last_audio_time = time + DCPTime::from_frames (data->frames(), _film->audio_frame_rate ());
+}
+
 void
 Player::fill_audio (DCPTimePeriod period)
 {
@@ -981,7 +1011,7 @@ Player::fill_audio (DCPTimePeriod period)
                        if (samples) {
                                shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), samples));
                                silence->make_silent ();
-                               Audio (silence, t);
+                               emit_audio (silence, t);
                        }
                        t += block;
                }
index a66eb8bbb2ee6d4fc0ed45c30d4bfa5657ef2587..dc942bd83e8390a4cc655d29befd6a2c60f9552a 100644 (file)
@@ -117,6 +117,7 @@ private:
                ) const;
        boost::optional<PositionImage> subtitles_for_frame (DCPTime time) const;
        void emit_video (boost::shared_ptr<PlayerVideo> pv, DCPTime time);
+       void emit_audio (boost::shared_ptr<AudioBuffers> data, DCPTime time);
 
        boost::shared_ptr<const Film> _film;
        boost::shared_ptr<const Playlist> _playlist;
index 09b67e921bf42e2820937212fd1cfae32a3bdef7..d37f287837110a283b8ee56003d58011853fb1f3 100644 (file)
@@ -555,6 +555,18 @@ Playlist::video_content_at (DCPTime time) const
        return false;
 }
 
+bool
+Playlist::audio_content_at (DCPTime time) const
+{
+       BOOST_FOREACH (shared_ptr<Content> i, _content) {
+               if (i->audio && i->position() <= time && time < i->end()) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 pair<double, double>
 Playlist::speed_up_range (int dcp_video_frame_rate) const
 {
index 1ce5f247ab700c6e54badd70910d5400879d5ccd..25dcda202b214e0e9029ac5407cfaf6b4d0e43fb 100644 (file)
@@ -56,6 +56,7 @@ public:
 
        ContentList content () const;
        bool video_content_at (DCPTime time) const;
+       bool audio_content_at (DCPTime time) const;
 
        std::string video_identifier () const;