X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fplayer.h;h=6860807b3deb72c7d1cf5866a2bac44e232cb68f;hb=2e504b33eb9f38cac629ad31b7c107fb0cf5efda;hp=4d23d1951ab53b9256b4e471bc9080f93229ba07;hpb=a0f1a3d40f1c93d4432d1d4857c1620907259b2f;p=dcpomatic.git diff --git a/src/lib/player.h b/src/lib/player.h index 4d23d1951..6860807b3 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -1,7 +1,5 @@ -/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ - /* - Copyright (C) 2013 Carl Hetherington + Copyright (C) 2013-2014 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 @@ -25,65 +23,196 @@ #include #include #include -#include "video_source.h" -#include "audio_source.h" -#include "video_sink.h" -#include "audio_sink.h" #include "playlist.h" -#include "audio_buffers.h" +#include "content.h" +#include "film.h" +#include "rect.h" +#include "audio_merger.h" +#include "audio_content.h" +#include "decoded.h" class Job; class Film; class Playlist; class AudioContent; class Piece; +class Image; + +/** @class PlayerImage + * @brief 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, dcp::Size, dcp::Size, Scaler const *); + void set_subtitle (boost::shared_ptr, Position); + + boost::shared_ptr image (AVPixelFormat, bool); + +private: + boost::shared_ptr _in; + Crop _crop; + dcp::Size _inter_size; + dcp::Size _out_size; + Scaler const * _scaler; + boost::shared_ptr _subtitle_image; + Position _subtitle_position; +}; + +class PlayerStatistics +{ +public: + struct Video { + Video () + : black (0) + , repeat (0) + , good (0) + , skip (0) + {} + + int black; + int repeat; + int good; + int skip; + } video; + + struct Audio { + Audio () + : silence (0) + , good (0) + , skip (0) + {} + + DCPTime silence; + int64_t good; + int64_t skip; + } audio; + + void dump (boost::shared_ptr) const; +}; + /** @class Player * @brief A class which can `play' a Playlist; emitting its audio and video. */ - -class Player : public VideoSource, public AudioSource, public boost::enable_shared_from_this + +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 (); - void disable_subtitles (); bool pass (); - void seek (Time); - void seek_back (); - void seek_forward (); + void seek (DCPTime, bool); - Time position () const { - return _position; + DCPTime video_position () const { + return _video_position; } + void set_video_container_size (dcp::Size); + void set_approximate_size (); + + bool repeat_last_video (); + + PlayerStatistics const & statistics () const; + + /** 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, DCPTime)> Video; + + /** Emitted when some audio data is ready */ + boost::signals2::signal, DCPTime)> 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, bool, boost::shared_ptr, Time); - void process_audio (boost::weak_ptr, boost::shared_ptr, Time); void setup_pieces (); void playlist_changed (); - void content_changed (boost::weak_ptr, int); - void do_seek (Time, bool); + void content_changed (boost::weak_ptr, int, bool); + void do_seek (DCPTime, bool); + void flush (); + void emit_black (); + void emit_silence (DCPTime); + void film_changed (Film::Property); + void update_subtitle_from_image (); + void update_subtitle_from_text (); + void emit_video (boost::weak_ptr, boost::shared_ptr); + void emit_audio (boost::weak_ptr, boost::shared_ptr); + void step_video_position (boost::shared_ptr); boost::shared_ptr _film; boost::shared_ptr _playlist; bool _video; bool _audio; - bool _subtitles; /** 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; - /** Time of the earliest thing not yet to have been emitted */ - Time _position; - AudioBuffers _audio_buffers; - Time _next_audio; + /** The time after the last video that we emitted */ + DCPTime _video_position; + /** The time after the last audio that we emitted */ + DCPTime _audio_position; + + AudioMerger _audio_merger; + + dcp::Size _video_container_size; + boost::shared_ptr _black_frame; + + struct { + boost::weak_ptr piece; + boost::shared_ptr subtitle; + } _image_subtitle; + + struct { + boost::weak_ptr piece; + boost::shared_ptr subtitle; + } _text_subtitle; + + struct { + Position position; + boost::shared_ptr image; + DCPTime from; + DCPTime to; + } _out_subtitle; + +#ifdef DCPOMATIC_DEBUG + boost::shared_ptr _last_video; +#endif + + bool _last_emit_was_black; + + struct { + boost::weak_ptr weak_piece; + boost::shared_ptr video; + } _last_incoming_video; + + bool _just_did_inaccurate_seek; + bool _approximate_size; + + PlayerStatistics _statistics; + + boost::signals2::scoped_connection _playlist_changed_connection; + boost::signals2::scoped_connection _playlist_content_changed_connection; + boost::signals2::scoped_connection _film_changed_connection; }; #endif