X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fplayer.cc;h=f4e181daf302ad1163476ab9cd2c35e13ffd309b;hb=a3241f40b061480a0907699a5857075388216643;hp=ee044e4e12e59c54a12ab3ceddc01b4c5e0a2502;hpb=9cbe46f9aa1d12b01ed0f9ffb3967bf6000e6e5c;p=dcpomatic.git diff --git a/src/lib/player.cc b/src/lib/player.cc index ee044e4e1..f4e181daf 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -22,10 +22,8 @@ #include "film.h" #include "ffmpeg_decoder.h" #include "ffmpeg_content.h" -#include "still_image_decoder.h" -#include "still_image_content.h" -#include "moving_image_decoder.h" -#include "moving_image_content.h" +#include "image_decoder.h" +#include "image_content.h" #include "sndfile_decoder.h" #include "sndfile_content.h" #include "subtitle_content.h" @@ -48,8 +46,6 @@ using boost::shared_ptr; using boost::weak_ptr; using boost::dynamic_pointer_cast; -//#define DEBUG_PLAYER 1 - class Piece { public: @@ -57,6 +53,8 @@ public: : content (c) , video_position (c->position ()) , audio_position (c->position ()) + , repeat_to_do (0) + , repeat_done (0) {} Piece (shared_ptr c, shared_ptr d) @@ -65,29 +63,52 @@ public: , video_position (c->position ()) , audio_position (c->position ()) {} + + /** Set this piece to repeat a video frame a given number of times */ + void set_repeat (IncomingVideo video, int num) + { + repeat_video = video; + repeat_to_do = num; + repeat_done = 0; + } + + void reset_repeat () + { + repeat_video.image.reset (); + repeat_to_do = 0; + repeat_done = 0; + } + + bool repeating () const + { + return repeat_done != repeat_to_do; + } + + void repeat (Player* player) + { + player->process_video ( + repeat_video.weak_piece, + repeat_video.image, + repeat_video.eyes, + repeat_done > 0, + repeat_video.frame, + (repeat_done + 1) * (TIME_HZ / player->_film->video_frame_rate ()) + ); + + ++repeat_done; + } shared_ptr content; shared_ptr decoder; + /** Time of the last video we emitted relative to the start of the DCP */ Time video_position; + /** Time of the last audio we emitted relative to the start of the DCP */ Time audio_position; -}; -#ifdef DEBUG_PLAYER -std::ostream& operator<<(std::ostream& s, Piece const & p) -{ - if (dynamic_pointer_cast (p.content)) { - s << "\tffmpeg "; - } else if (dynamic_pointer_cast (p.content)) { - s << "\tstill image"; - } else if (dynamic_pointer_cast (p.content)) { - s << "\tsndfile "; - } - - s << " at " << p.content->position() << " until " << p.content->end(); - - return s; -} -#endif + IncomingVideo repeat_video; + int repeat_to_do; + int repeat_done; +}; Player::Player (shared_ptr f, shared_ptr p) : _film (f) @@ -103,7 +124,7 @@ Player::Player (shared_ptr f, shared_ptr p) _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this)); _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3)); _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1)); - set_video_container_size (_film->container()->size (_film->full_frame ())); + set_video_container_size (fit_ratio_within (_film->container()->ratio (), _film->full_frame ())); } void @@ -126,10 +147,6 @@ Player::pass () _have_valid_pieces = true; } -#ifdef DEBUG_PLAYER - cout << "= PASS\n"; -#endif - Time earliest_t = TIME_MAX; shared_ptr earliest; enum { @@ -142,7 +159,10 @@ Player::pass () continue; } - if (_video && dynamic_pointer_cast ((*i)->decoder)) { + shared_ptr vd = dynamic_pointer_cast ((*i)->decoder); + shared_ptr ad = dynamic_pointer_cast ((*i)->decoder); + + if (_video && vd) { if ((*i)->video_position < earliest_t) { earliest_t = (*i)->video_position; earliest = *i; @@ -150,7 +170,7 @@ Player::pass () } } - if (_audio && dynamic_pointer_cast ((*i)->decoder)) { + if (_audio && ad && ad->has_audio ()) { if ((*i)->audio_position < earliest_t) { earliest_t = (*i)->audio_position; earliest = *i; @@ -160,10 +180,6 @@ Player::pass () } if (!earliest) { -#ifdef DEBUG_PLAYER - cout << "no earliest piece.\n"; -#endif - flush (); return true; } @@ -171,28 +187,20 @@ Player::pass () switch (type) { case VIDEO: if (earliest_t > _video_position) { -#ifdef DEBUG_PLAYER - cout << "no video here; emitting black frame (earliest=" << earliest_t << ", video_position=" << _video_position << ").\n"; -#endif emit_black (); } else { -#ifdef DEBUG_PLAYER - cout << "Pass video " << *earliest << "\n"; -#endif - earliest->decoder->pass (); + if (earliest->repeating ()) { + earliest->repeat (this); + } else { + earliest->decoder->pass (); + } } break; case AUDIO: if (earliest_t > _audio_position) { -#ifdef DEBUG_PLAYER - cout << "no audio here (none until " << earliest_t << "); emitting silence.\n"; -#endif emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position)); } else { -#ifdef DEBUG_PLAYER - cout << "Pass audio " << *earliest << "\n"; -#endif earliest->decoder->pass (); if (earliest->decoder->done()) { @@ -209,28 +217,41 @@ Player::pass () } break; } - - Time audio_done_up_to = TIME_MAX; - for (list >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) { - if (dynamic_pointer_cast ((*i)->decoder)) { - audio_done_up_to = min (audio_done_up_to, (*i)->audio_position); - } - } - TimedAudioBuffers