- std::list<PositionImage> process_content_text_subtitles (std::list<boost::shared_ptr<ContentTextSubtitle> >) const;
- void update_subtitle_from_text ();
- VideoFrame dcp_to_content_video (boost::shared_ptr<const Piece> piece, DCPTime t) const;
- AudioFrame dcp_to_content_audio (boost::shared_ptr<const Piece> piece, DCPTime t) const;
- ContentTime dcp_to_content_subtitle (boost::shared_ptr<const Piece> piece, DCPTime t) const;
- boost::shared_ptr<PlayerVideoFrame> black_player_video_frame () const;
-
- /** @return Pieces of content type C that overlap a specified time range in the DCP */
- template<class C>
- std::list<boost::shared_ptr<Piece> >
- overlaps (DCPTime from, DCPTime to)
+ boost::optional<PositionImage> open_subtitles_for_frame (dcpomatic::DCPTime time) const;
+ void emit_video (std::shared_ptr<PlayerVideo> pv, dcpomatic::DCPTime time);
+ void do_emit_video (std::shared_ptr<PlayerVideo> pv, dcpomatic::DCPTime time);
+ void emit_audio (std::shared_ptr<AudioBuffers> data, dcpomatic::DCPTime time);
+ std::shared_ptr<const Playlist> playlist () const;
+
+ /** Mutex to protect the whole Player state. When it's used for the preview we have
+ seek() and pass() called from the Butler thread and lots of other stuff called
+ from the GUI thread.
+ */
+ mutable boost::mutex _mutex;
+
+ std::shared_ptr<const Film> _film;
+ /** Playlist, or 0 if we are using the one from the _film */
+ std::shared_ptr<const Playlist> _playlist;
+
+ /** > 0 if we are suspended (i.e. pass() and seek() do nothing) */
+ boost::atomic<int> _suspended;
+ std::list<std::shared_ptr<Piece> > _pieces;
+
+ /** Size of the image we are rendering to; this may be the DCP frame size, or
+ * the size of preview in a window.
+ */
+ dcp::Size _video_container_size;
+ std::shared_ptr<Image> _black_image;
+
+ /** true if the player should ignore all video; i.e. never produce any */
+ bool _ignore_video = false;
+ bool _ignore_audio = false;
+ /** true if the player should ignore all text; i.e. never produce any */
+ bool _ignore_text = false;
+ bool _always_burn_open_subtitles = false;
+ /** true if we should try to be fast rather than high quality */
+ bool _fast = false;
+ /** true if we should keep going in the face of `survivable' errors */
+ bool _tolerant = false;
+ /** true if we should `play' (i.e output) referenced DCP data (e.g. for preview) */
+ bool _play_referenced = false;
+
+ /** Time just after the last video frame we emitted, or the time of the last accurate seek */
+ boost::optional<dcpomatic::DCPTime> _last_video_time;
+ boost::optional<Eyes> _last_video_eyes;
+ /** Time just after the last audio frame we emitted, or the time of the last accurate seek */
+ boost::optional<dcpomatic::DCPTime> _last_audio_time;
+
+ boost::optional<int> _dcp_decode_reduction;
+
+ typedef std::map<std::weak_ptr<Piece>, std::shared_ptr<PlayerVideo>, std::owner_less<std::weak_ptr<Piece>>> LastVideoMap;
+ LastVideoMap _last_video;
+
+ AudioMerger _audio_merger;
+ Shuffler* _shuffler = nullptr;
+ std::list<std::pair<std::shared_ptr<PlayerVideo>, dcpomatic::DCPTime> > _delay;
+
+ class StreamState