/* Copyright (C) 2013 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef DCPOMATIC_PLAYER_H #define DCPOMATIC_PLAYER_H #include #include #include #include "playlist.h" #include "content.h" #include "film.h" #include "rect.h" #include "audio_merger.h" #include "audio_content.h" class Job; class Film; class Playlist; class AudioContent; class Piece; class Image; class Resampler; /** @class Player * @brief A class which can `play' a Playlist; emitting its audio and video. */ struct IncomingVideo { public: boost::weak_ptr weak_piece; boost::shared_ptr image; Eyes eyes; bool same; VideoContent::Frame frame; Time extra; }; /** A wrapper for an Image which contains some pending operations; these may * not be necessary if the receiver of the PlayerImage throws it away. */ class PlayerImage { public: PlayerImage (boost::shared_ptr, Crop, libdcp::Size, libdcp::Size, Scaler const *); void set_subtitle (boost::shared_ptr, Position); boost::shared_ptr image (); private: boost::shared_ptr _in; Crop _crop; libdcp::Size _inter_size; libdcp::Size _out_size; Scaler const * _scaler; boost::shared_ptr _subtitle_image; Position _subtitle_position; }; class Player : public boost::enable_shared_from_this, public boost::noncopyable { public: Player (boost::shared_ptr, boost::shared_ptr); void disable_video (); void disable_audio (); bool pass (); void seek (Time, bool); Time video_position () const { return _video_position; } void set_video_container_size (libdcp::Size); bool repeat_last_video (); /** Emitted when a video frame is ready. * First parameter is the video image. * Second parameter is the eye(s) that should see this image. * Third parameter is the colour conversion that should be used for this image. * Fourth parameter is true if the image is the same as the last one that was emitted. * Fifth parameter is the time. */ boost::signals2::signal, Eyes, ColourConversion, bool, Time)> Video; /** Emitted when some audio data is ready */ boost::signals2::signal, Time)> Audio; /** Emitted when something has changed such that if we went back and emitted * the last frame again it would look different. This is not emitted after * a seek. * * The parameter is true if these signals are currently likely to be frequent. */ boost::signals2::signal Changed; private: friend class PlayerWrapper; friend class Piece; void process_video (boost::weak_ptr, boost::shared_ptr, Eyes, bool, VideoContent::Frame, Time); void process_audio (boost::weak_ptr, boost::shared_ptr, AudioContent::Frame); void process_subtitle (boost::weak_ptr, boost::shared_ptr, dcpomatic::Rect, Time, Time); void setup_pieces (); void playlist_changed (); void content_changed (boost::weak_ptr, int, bool); void do_seek (Time, bool); void flush (); void emit_black (); void emit_silence (OutputAudioFrame); boost::shared_ptr resampler (boost::shared_ptr, bool); void film_changed (Film::Property); void update_subtitle (); boost::shared_ptr _film; boost::shared_ptr _playlist; bool _video; bool _audio; /** Our pieces are ready to go; if this is false the pieces must be (re-)created before they are used */ bool _have_valid_pieces; std::list > _pieces; /** The time after the last video that we emitted */ Time _video_position; /** The time after the last audio that we emitted */ Time _audio_position; AudioMerger _audio_merger; libdcp::Size _video_container_size; boost::shared_ptr _black_frame; std::map, boost::shared_ptr > _resamplers; struct { boost::weak_ptr piece; boost::shared_ptr image; dcpomatic::Rect rect; Time from; Time to; } _in_subtitle; struct { boost::shared_ptr image; Position position; Time from; Time to; } _out_subtitle; #ifdef DCPOMATIC_DEBUG boost::shared_ptr _last_video; #endif bool _last_emit_was_black; IncomingVideo _last_incoming_video; boost::signals2::scoped_connection _playlist_changed_connection; boost::signals2::scoped_connection _playlist_content_changed_connection; boost::signals2::scoped_connection _film_changed_connection; }; #endif