Fix _audio_position after seek.
[dcpomatic.git] / src / lib / player.cc
index c9f9acd942179561184fb2c32bd70e2ee65a24b9..eb7b177ecd21aacc86bc5c96d89e404a8333f7e1 100644 (file)
@@ -108,13 +108,37 @@ Player::pass ()
 
        for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
 
-               shared_ptr<Decoded> dec = (*i)->decoder->peek ();
+               DCPTime const offset = (*i)->content->position() - (*i)->content->trim_start();
+               
+               bool done = false;
+               shared_ptr<Decoded> dec;
+               while (!done) {
+                       dec = (*i)->decoder->peek ();
+                       if (!dec) {
+                               /* Decoder has nothing else to give us */
+                               break;
+                       }
+
+                       dec->set_dcp_times (_film->video_frame_rate(), _film->audio_frame_rate(), (*i)->frc, offset);
+                       DCPTime const t = dec->dcp_time - offset;
+                       if (t >= ((*i)->content->full_length() - (*i)->content->trim_end ())) {
+                               /* In the end-trimmed part; decoder has nothing else to give us */
+                               dec.reset ();
+                               done = true;
+                       } else if (t >= (*i)->content->trim_start ()) {
+                               /* Within the un-trimmed part; everything's ok */
+                               done = true;
+                       } else {
+                               /* Within the start-trimmed part; get something else */
+                               (*i)->decoder->consume ();
+                       }
+               }
 
-               if (dec) {
-                       dec->set_dcp_times ((*i)->frc.speed_up, (*i)->content->position() - (*i)->content->trim_start());
+               if (!dec) {
+                       continue;
                }
 
-               if (dec && dec->dcp_time < earliest_time) {
+               if (dec->dcp_time < earliest_time) {
                        earliest_piece = *i;
                        earliest_decoded = dec;
                        earliest_time = dec->dcp_time;
@@ -173,11 +197,13 @@ Player::pass ()
                        if (i == _pieces.end() || !_last_incoming_video.video || !_have_valid_pieces) {
                                /* We're outside all video content */
                                emit_black ();
+                               _statistics.video.black++;
                        } else {
                                /* We're inside some video; repeat the frame */
                                _last_incoming_video.video->dcp_time = _video_position;
                                emit_video (_last_incoming_video.weak_piece, _last_incoming_video.video);
                                step_video_position (_last_incoming_video.video);
+                               _statistics.video.repeat++;
                        }
 
                        consume = false;
@@ -186,8 +212,10 @@ Player::pass ()
                        /* We're ok */
                        emit_video (earliest_piece, dv);
                        step_video_position (dv);
+                       _statistics.video.good++;
                } else {
                        /* Too far behind: skip */
+                       _statistics.video.skip++;
                }
 
                _just_did_inaccurate_seek = false;
@@ -198,11 +226,14 @@ Player::pass ()
                        /* Too far ahead */
                        emit_silence (da->dcp_time - _audio_position);
                        consume = false;
+                       _statistics.audio.silence += (da->dcp_time - _audio_position);
                } else if (abs (da->dcp_time - _audio_position) < margin) {
                        /* We're ok */
                        emit_audio (earliest_piece, da);
+                       _statistics.audio.good += da->data->frames();
                } else {
                        /* Too far behind: skip */
+                       _statistics.audio.skip += da->data->frames();
                }
                
        } else if (ds && _video) {
@@ -305,10 +336,6 @@ Player::emit_audio (weak_ptr<Piece> weak_piece, shared_ptr<DecodedAudio> audio)
                audio->data = gain;
        }
 
-       if (content->trimmed (audio->dcp_time - content->position ())) {
-               return;
-       }
-
        /* Remap channels */
        shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->data->frames()));
        dcp_mapped->make_silent ();
@@ -380,7 +407,7 @@ Player::seek (DCPTime t, bool accurate)
                s = min ((*i)->content->length_after_trim(), s);
 
                /* Convert this to the content time */
-               ContentTime ct = (s * (*i)->frc.speed_up) + (*i)->content->trim_start ();
+               ContentTime ct = (s + (*i)->content->trim_start()) * (*i)->frc.speed_up;
 
                /* And seek the decoder */
                (*i)->decoder->seek (ct, accurate);
@@ -470,7 +497,8 @@ Player::setup_pieces ()
                        }
                }
 
-               decoder->seek ((*i)->trim_start (), true);
+               ContentTime st = (*i)->trim_start() * frc->speed_up;
+               decoder->seek (st, true);
                
                _pieces.push_back (shared_ptr<Piece> (new Piece (*i, decoder, frc.get ())));
        }
@@ -694,3 +722,15 @@ PlayerImage::image (AVPixelFormat format, bool aligned)
        return out;
 }
 
+void
+PlayerStatistics::dump (shared_ptr<Log> log) const
+{
+       log->log (String::compose ("Video: %1 good %2 skipped %3 black %4 repeat", video.good, video.skip, video.black, video.repeat));
+       log->log (String::compose ("Audio: %1 good %2 skipped %3 silence", audio.good, audio.skip, audio.silence));
+}
+
+PlayerStatistics const &
+Player::statistics () const
+{
+       return _statistics;
+}