2 Copyright (C) 2013-2020 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
22 #ifndef DCPOMATIC_PLAYER_H
23 #define DCPOMATIC_PLAYER_H
26 #include "active_text.h"
27 #include "atmos_metadata.h"
28 #include "audio_merger.h"
29 #include "audio_stream.h"
30 #include "content_atmos.h"
31 #include "content_audio.h"
32 #include "content_text.h"
33 #include "content_video.h"
35 #include "enum_indexed_vector.h"
38 #include "player_text.h"
39 #include "position_image.h"
41 #include <boost/atomic.hpp>
54 class ReferencedReelAsset;
60 static int const VIDEO_CONTAINER_SIZE;
61 static int const PLAYLIST;
62 static int const FILM_CONTAINER;
63 static int const FILM_VIDEO_FRAME_RATE;
64 static int const DCP_DECODE_REDUCTION;
65 static int const PLAYBACK_LENGTH;
66 static int const IGNORE_VIDEO;
67 static int const IGNORE_AUDIO;
68 static int const IGNORE_TEXT;
69 static int const ALWAYS_BURN_OPEN_SUBTITLES;
70 static int const PLAY_REFERENCED;
75 * @brief A class which can play a Playlist.
77 class Player : public std::enable_shared_from_this<Player>
80 Player (std::shared_ptr<const Film>, Image::Alignment subtitle_alignment);
81 Player (std::shared_ptr<const Film>, std::shared_ptr<const Playlist> playlist);
83 Player (Player const& Player) = delete;
84 Player& operator= (Player const& Player) = delete;
87 void seek (dcpomatic::DCPTime time, bool accurate);
89 std::vector<std::shared_ptr<dcpomatic::Font>> get_subtitle_fonts ();
91 dcp::Size video_container_size () const {
92 return _video_container_size;
95 void set_video_container_size (dcp::Size);
96 void set_ignore_video ();
97 void set_ignore_audio ();
98 void set_ignore_text ();
99 void set_always_burn_open_subtitles ();
101 void set_play_referenced ();
102 void set_dcp_decode_reduction (boost::optional<int> reduction);
104 boost::optional<dcpomatic::DCPTime> content_time_to_dcp (std::shared_ptr<const Content> content, dcpomatic::ContentTime t) const;
105 boost::optional<dcpomatic::ContentTime> dcp_to_content_time (std::shared_ptr<const Content> content, dcpomatic::DCPTime t) const;
107 void signal_change(ChangeType type, int property);
109 /** First parameter is PENDING, DONE or CANCELLED.
110 * Second parameter is the property.
111 * Third parameter is true if these signals are currently likely to be frequent.
113 boost::signals2::signal<void (ChangeType, int, bool)> Change;
115 /** Emitted when a video frame is ready. These emissions happen in the correct order. */
116 boost::signals2::signal<void (std::shared_ptr<PlayerVideo>, dcpomatic::DCPTime)> Video;
117 /** Emitted when audio data is ready. First parameter is the audio data, second its time,
118 * third the frame rate.
120 boost::signals2::signal<void (std::shared_ptr<AudioBuffers>, dcpomatic::DCPTime, int)> Audio;
121 /** Emitted when a text is ready. This signal may be emitted considerably
122 * after the corresponding Video.
124 boost::signals2::signal<void (PlayerText, TextType, boost::optional<DCPTextTrack>, dcpomatic::DCPTimePeriod)> Text;
125 boost::signals2::signal<void (std::shared_ptr<const dcp::AtmosFrame>, dcpomatic::DCPTime, AtmosMetadata)> Atmos;
128 friend class PlayerWrapper;
130 friend struct player_time_calculation_test1;
131 friend struct player_time_calculation_test2;
132 friend struct player_time_calculation_test3;
133 friend struct player_subframe_test;
134 friend struct empty_test1;
135 friend struct empty_test2;
136 friend struct check_reuse_old_data_test;
137 friend struct overlap_video_test1;
140 void setup_pieces ();
141 void film_change (ChangeType, Film::Property);
142 void playlist_change (ChangeType);
143 void playlist_content_change (ChangeType, int, bool);
144 Frame dcp_to_content_video (std::shared_ptr<const Piece> piece, dcpomatic::DCPTime t) const;
145 dcpomatic::DCPTime content_video_to_dcp (std::shared_ptr<const Piece> piece, Frame f) const;
146 Frame dcp_to_resampled_audio (std::shared_ptr<const Piece> piece, dcpomatic::DCPTime t) const;
147 dcpomatic::DCPTime resampled_audio_to_dcp (std::shared_ptr<const Piece> piece, Frame f) const;
148 dcpomatic::ContentTime dcp_to_content_time (std::shared_ptr<const Piece> piece, dcpomatic::DCPTime t) const;
149 dcpomatic::DCPTime content_time_to_dcp (std::shared_ptr<const Piece> piece, dcpomatic::ContentTime t) const;
150 std::shared_ptr<PlayerVideo> black_player_video_frame (Eyes eyes) const;
152 void video (std::weak_ptr<Piece>, ContentVideo);
153 void audio (std::weak_ptr<Piece>, AudioStreamPtr, ContentAudio);
154 void bitmap_text_start (std::weak_ptr<Piece>, std::weak_ptr<const TextContent>, ContentBitmapText);
155 void plain_text_start (std::weak_ptr<Piece>, std::weak_ptr<const TextContent>, ContentStringText);
156 void subtitle_stop (std::weak_ptr<Piece>, std::weak_ptr<const TextContent>, dcpomatic::ContentTime);
157 void atmos (std::weak_ptr<Piece>, ContentAtmos);
159 dcpomatic::DCPTime one_video_frame () const;
160 void fill_audio (dcpomatic::DCPTimePeriod period);
161 std::pair<std::shared_ptr<AudioBuffers>, dcpomatic::DCPTime> discard_audio (
162 std::shared_ptr<const AudioBuffers> audio, dcpomatic::DCPTime time, dcpomatic::DCPTime discard_to
164 boost::optional<PositionImage> open_subtitles_for_frame (dcpomatic::DCPTime time) const;
165 void emit_video (std::shared_ptr<PlayerVideo> pv, dcpomatic::DCPTime time);
166 void do_emit_video (std::shared_ptr<PlayerVideo> pv, dcpomatic::DCPTime time);
167 void emit_audio (std::shared_ptr<AudioBuffers> data, dcpomatic::DCPTime time);
168 std::shared_ptr<const Playlist> playlist () const;
170 /** Mutex to protect the most of the Player state. When it's used for the preview we have
171 seek() and pass() called from the Butler thread and lots of other stuff called
174 mutable boost::mutex _mutex;
176 std::weak_ptr<const Film> const _film;
177 /** Playlist, or 0 if we are using the one from the _film */
178 std::shared_ptr<const Playlist> const _playlist;
180 /** > 0 if we are suspended (i.e. pass() and seek() do nothing) */
181 boost::atomic<int> _suspended;
182 std::list<std::shared_ptr<Piece>> _pieces;
184 /** Size of the image we are rendering to; this may be the DCP frame size, or
185 * the size of preview in a window.
187 boost::atomic<dcp::Size> _video_container_size;
189 mutable boost::mutex _black_image_mutex;
190 std::shared_ptr<Image> _black_image;
192 /** true if the player should ignore all video; i.e. never produce any */
193 boost::atomic<bool> _ignore_video;
194 boost::atomic<bool> _ignore_audio;
195 /** true if the player should ignore all text; i.e. never produce any */
196 boost::atomic<bool> _ignore_text;
197 boost::atomic<bool> _always_burn_open_subtitles;
198 /** true if we should try to be fast rather than high quality */
199 boost::atomic<bool> _fast;
200 /** true if we should keep going in the face of `survivable' errors */
201 bool const _tolerant;
202 /** true if we should `play' (i.e output) referenced DCP data (e.g. for preview) */
203 boost::atomic<bool> _play_referenced;
205 /** Time of the next video that we will emit, or the time of the last accurate seek */
206 boost::optional<dcpomatic::DCPTime> _next_video_time;
207 /** Eyes of the next video that we will emit */
208 boost::optional<Eyes> _next_video_eyes;
209 /** Time of the next audio that we will emit, or the time of the last accurate seek */
210 boost::optional<dcpomatic::DCPTime> _next_audio_time;
212 boost::atomic<boost::optional<int>> _dcp_decode_reduction;
214 typedef std::map<std::weak_ptr<Piece>, std::shared_ptr<PlayerVideo>, std::owner_less<std::weak_ptr<Piece>>> LastVideoMap;
215 LastVideoMap _last_video;
217 AudioMerger _audio_merger;
218 std::unique_ptr<Shuffler> _shuffler;
219 std::list<std::pair<std::shared_ptr<PlayerVideo>, dcpomatic::DCPTime>> _delay;
226 StreamState (std::shared_ptr<Piece> p, dcpomatic::DCPTime l)
231 std::shared_ptr<Piece> piece;
232 dcpomatic::DCPTime last_push_end;
234 std::map<AudioStreamPtr, StreamState> _stream_states;
239 EnumIndexedVector<ActiveText, TextType> _active_texts;
240 std::shared_ptr<AudioProcessor> _audio_processor;
242 boost::atomic<dcpomatic::DCPTime> _playback_length;
244 /** Alignment for subtitle images that we create */
245 Image::Alignment const _subtitle_alignment = Image::Alignment::PADDED;
247 boost::signals2::scoped_connection _film_changed_connection;
248 boost::signals2::scoped_connection _playlist_change_connection;
249 boost::signals2::scoped_connection _playlist_content_change_connection;