X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fplayer.cc;h=ce51097334be3e6a48107033e8446568d2dc0c4f;hb=797c7543dc7fe5a9f9ddaf4c2035f9b9a7188758;hp=d13ae5f3cb8588fbb6b96dab72ed9f54c22745d4;hpb=a1b0ed4ac0753b420ce8ab8467165e220bdb4b05;p=dcpomatic.git diff --git a/src/lib/player.cc b/src/lib/player.cc index d13ae5f3c..ce5109733 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) @@ -123,13 +144,8 @@ Player::pass () { if (!_have_valid_pieces) { setup_pieces (); - _have_valid_pieces = true; } -#ifdef DEBUG_PLAYER - cout << "= PASS\n"; -#endif - Time earliest_t = TIME_MAX; shared_ptr earliest; enum { @@ -142,7 +158,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 +169,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 +179,6 @@ Player::pass () } if (!earliest) { -#ifdef DEBUG_PLAYER - cout << "no earliest piece.\n"; -#endif - flush (); return true; } @@ -171,28 +186,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()) { @@ -211,28 +218,40 @@ Player::pass () } if (_audio) { - Time audio_done_up_to = TIME_MAX; + boost::optional