Fix skip-frame.
[dcpomatic.git] / src / lib / player.cc
index 7b1b08250b5edb3ec7f16ee61613a0af22bca03f..7d53b07bfe104ce90c113958023087c1cb72d27a 100644 (file)
@@ -95,6 +95,8 @@ Player::Player (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist
        set_video_container_size (_film->frame_size ());
 
        film_changed (Film::AUDIO_PROCESSOR);
+
+       seek (DCPTime (), true);
 }
 
 void
@@ -146,6 +148,14 @@ Player::setup_pieces ()
                }
        }
 
+       BOOST_FOREACH (shared_ptr<Piece> i, _pieces) {
+               if (i->content->audio) {
+                       BOOST_FOREACH (AudioStreamPtr j, i->content->audio->streams()) {
+                               _stream_states[j] = StreamState (i, i->content->position ());
+                       }
+               }
+       }
+
        _have_valid_pieces = true;
 }
 
@@ -535,9 +545,12 @@ Player::pass ()
                DCPTime t = _last_audio_time;
                while (t < length) {
                        DCPTime block = min (DCPTime::from_seconds (0.5), length - t);
-                       shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), block.frames_round(_film->audio_frame_rate())));
-                       silence->make_silent ();
-                       Audio (silence, t);
+                       Frame const samples = block.frames_round(_film->audio_frame_rate());
+                       if (samples) {
+                               shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), samples));
+                               silence->make_silent ();
+                               Audio (silence, t);
+                       }
                        t += block;
                }
 
@@ -548,24 +561,15 @@ Player::pass ()
 
        /* Emit any audio that is ready */
 
-       optional<DCPTime> earliest_audio;
-       BOOST_FOREACH (shared_ptr<Piece> i, _pieces) {
-               if (i->decoder->audio) {
-                       DCPTime t = i->content->position()
-                               + DCPTime (i->decoder->audio->position(), i->frc)
-                               + DCPTime::from_seconds (i->content->audio->delay() / 1000.0);
-
-                       if (t < DCPTime()) {
-                               t = DCPTime();
-                       }
-
-                       if (!earliest_audio || t < *earliest_audio) {
-                               earliest_audio = t;
-                       }
+       DCPTime pull_from = _playlist->length ();
+       for (map<AudioStreamPtr, StreamState>::const_iterator i = _stream_states.begin(); i != _stream_states.end(); ++i) {
+               if (!i->second.piece->done && i->second.last_push_end < pull_from) {
+                       pull_from = i->second.last_push_end;
                }
        }
 
-       pair<shared_ptr<AudioBuffers>, DCPTime> audio = _audio_merger.pull (earliest_audio.get_value_or(DCPTime()));
+//     cout << "PULL " << to_string(pull_from) << "\n";
+       pair<shared_ptr<AudioBuffers>, DCPTime> audio = _audio_merger.pull (pull_from);
        if (audio.first->frames() > 0) {
                DCPOMATIC_ASSERT (audio.second >= _last_audio_time);
                DCPTime t = _last_audio_time;
@@ -593,6 +597,11 @@ Player::video (weak_ptr<Piece> wp, ContentVideo video)
                return;
        }
 
+       FrameRateChange frc(piece->content->active_video_frame_rate(), _film->video_frame_rate());
+       if (frc.skip && (video.frame % 2) == 1) {
+               return;
+       }
+
        /* Time and period of the frame we will emit */
        DCPTime const time = content_video_to_dcp (piece, video.frame);
        DCPTimePeriod const period (time, time + DCPTime::from_frames (1, _film->video_frame_rate()));
@@ -750,7 +759,11 @@ Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_a
                content_audio.audio = _audio_processor->run (content_audio.audio, _film->audio_channels ());
        }
 
+//     cout << "PUSH " << content_audio.audio->frames() << " @ " << to_string(time) << "\n";
        _audio_merger.push (content_audio.audio, time);
+
+       DCPOMATIC_ASSERT (_stream_states.find (stream) != _stream_states.end ());
+       _stream_states[stream].last_push_end = time + DCPTime::from_frames (content_audio.audio->frames(), _film->audio_frame_rate());
 }
 
 void