Change how video timing is done.
[dcpomatic.git] / src / lib / player.cc
1 /*
2     Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
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.
10
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.
15
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/>.
18
19 */
20
21
22 #include "atmos_decoder.h"
23 #include "audio_buffers.h"
24 #include "audio_content.h"
25 #include "audio_decoder.h"
26 #include "audio_processor.h"
27 #include "compose.hpp"
28 #include "config.h"
29 #include "content_audio.h"
30 #include "content_video.h"
31 #include "dcp_content.h"
32 #include "dcp_decoder.h"
33 #include "dcpomatic_log.h"
34 #include "decoder.h"
35 #include "decoder_factory.h"
36 #include "ffmpeg_content.h"
37 #include "film.h"
38 #include "frame_rate_change.h"
39 #include "image.h"
40 #include "image_decoder.h"
41 #include "job.h"
42 #include "log.h"
43 #include "maths_util.h"
44 #include "piece.h"
45 #include "player.h"
46 #include "player_video.h"
47 #include "playlist.h"
48 #include "ratio.h"
49 #include "raw_image_proxy.h"
50 #include "render_text.h"
51 #include "shuffler.h"
52 #include "text_content.h"
53 #include "text_decoder.h"
54 #include "timer.h"
55 #include "video_decoder.h"
56 #include <dcp/reel.h>
57 #include <dcp/reel_closed_caption_asset.h>
58 #include <dcp/reel_picture_asset.h>
59 #include <dcp/reel_sound_asset.h>
60 #include <dcp/reel_subtitle_asset.h>
61 #include <algorithm>
62 #include <iostream>
63 #include <stdint.h>
64
65 #include "i18n.h"
66
67
68 using std::copy;
69 using std::cout;
70 using std::dynamic_pointer_cast;
71 using std::list;
72 using std::make_pair;
73 using std::make_shared;
74 using std::max;
75 using std::min;
76 using std::pair;
77 using std::shared_ptr;
78 using std::vector;
79 using std::weak_ptr;
80 using boost::optional;
81 using boost::scoped_ptr;
82 #if BOOST_VERSION >= 106100
83 using namespace boost::placeholders;
84 #endif
85 using namespace dcpomatic;
86
87
88 int const PlayerProperty::VIDEO_CONTAINER_SIZE = 700;
89 int const PlayerProperty::PLAYLIST = 701;
90 int const PlayerProperty::FILM_CONTAINER = 702;
91 int const PlayerProperty::FILM_VIDEO_FRAME_RATE = 703;
92 int const PlayerProperty::DCP_DECODE_REDUCTION = 704;
93 int const PlayerProperty::PLAYBACK_LENGTH = 705;
94 int const PlayerProperty::IGNORE_VIDEO = 706;
95 int const PlayerProperty::IGNORE_AUDIO = 707;
96 int const PlayerProperty::IGNORE_TEXT = 708;
97 int const PlayerProperty::ALWAYS_BURN_OPEN_SUBTITLES = 709;
98 int const PlayerProperty::PLAY_REFERENCED = 710;
99
100
101 Player::Player (shared_ptr<const Film> film, Image::Alignment subtitle_alignment)
102         : _film (film)
103         , _suspended (0)
104         , _ignore_video(false)
105         , _ignore_audio(false)
106         , _ignore_text(false)
107         , _always_burn_open_subtitles(false)
108         , _fast(false)
109         , _tolerant (film->tolerant())
110         , _play_referenced(false)
111         , _audio_merger(film->audio_frame_rate())
112         , _subtitle_alignment (subtitle_alignment)
113 {
114         construct ();
115 }
116
117
118 Player::Player (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist_)
119         : _film (film)
120         , _playlist (playlist_)
121         , _suspended (0)
122         , _ignore_video(false)
123         , _ignore_audio(false)
124         , _ignore_text(false)
125         , _always_burn_open_subtitles(false)
126         , _fast(false)
127         , _tolerant (film->tolerant())
128         , _play_referenced(false)
129         , _audio_merger(film->audio_frame_rate())
130 {
131         construct ();
132 }
133
134
135 void
136 Player::construct ()
137 {
138         auto film = _film.lock();
139         DCPOMATIC_ASSERT(film);
140
141         connect();
142         set_video_container_size(film->frame_size());
143
144         film_change (ChangeType::DONE, Film::Property::AUDIO_PROCESSOR);
145
146         setup_pieces ();
147         seek (DCPTime (), true);
148 }
149
150
151 void
152 Player::connect()
153 {
154         auto film = _film.lock();
155         DCPOMATIC_ASSERT(film);
156
157         _film_changed_connection = film->Change.connect(bind(&Player::film_change, this, _1, _2));
158         /* The butler must hear about this first, so since we are proxying this through to the butler we must
159            be first.
160         */
161         _playlist_change_connection = playlist()->Change.connect (bind (&Player::playlist_change, this, _1), boost::signals2::at_front);
162         _playlist_content_change_connection = playlist()->ContentChange.connect (bind(&Player::playlist_content_change, this, _1, _3, _4));
163 }
164
165
166 Player::Player(Player&& other)
167         : _film(other._film)
168         , _playlist(std::move(other._playlist))
169         , _suspended(other._suspended.load())
170         , _pieces(std::move(other._pieces))
171         , _video_container_size(other._video_container_size.load())
172         , _black_image(std::move(other._black_image))
173         , _ignore_video(other._ignore_video.load())
174         , _ignore_audio(other._ignore_audio.load())
175         , _ignore_text(other._ignore_text.load())
176         , _always_burn_open_subtitles(other._always_burn_open_subtitles.load())
177         , _fast(other._fast.load())
178         , _tolerant(other._tolerant)
179         , _play_referenced(other._play_referenced.load())
180         , _next_video_time(other._next_video_time)
181         , _next_audio_time(other._next_audio_time)
182         , _dcp_decode_reduction(other._dcp_decode_reduction.load())
183         , _last_video(std::move(other._last_video))
184         , _audio_merger(std::move(other._audio_merger))
185         , _shuffler(std::move(other._shuffler))
186         , _delay(std::move(other._delay))
187         , _stream_states(std::move(other._stream_states))
188         , _black(std::move(other._black))
189         , _silent(std::move(other._silent))
190         , _active_texts(std::move(other._active_texts))
191         , _audio_processor(std::move(other._audio_processor))
192         , _playback_length(other._playback_length.load())
193         , _subtitle_alignment(other._subtitle_alignment)
194 {
195         connect();
196 }
197
198
199 Player&
200 Player::operator=(Player&& other)
201 {
202         if (this == &other) {
203                 return *this;
204         }
205
206         _film = std::move(other._film);
207         _playlist = std::move(other._playlist);
208         _suspended = other._suspended.load();
209         _pieces = std::move(other._pieces);
210         _video_container_size = other._video_container_size.load();
211         _black_image = std::move(other._black_image);
212         _ignore_video = other._ignore_video.load();
213         _ignore_audio = other._ignore_audio.load();
214         _ignore_text = other._ignore_text.load();
215         _always_burn_open_subtitles = other._always_burn_open_subtitles.load();
216         _fast = other._fast.load();
217         _tolerant = other._tolerant;
218         _play_referenced = other._play_referenced.load();
219         _next_video_time = other._next_video_time;
220         _next_audio_time = other._next_audio_time;
221         _dcp_decode_reduction = other._dcp_decode_reduction.load();
222         _last_video = std::move(other._last_video);
223         _audio_merger = std::move(other._audio_merger);
224         _shuffler = std::move(other._shuffler);
225         _delay = std::move(other._delay);
226         _stream_states = std::move(other._stream_states);
227         _black = std::move(other._black);
228         _silent = std::move(other._silent);
229         _active_texts = std::move(other._active_texts);
230         _audio_processor = std::move(other._audio_processor);
231         _playback_length = other._playback_length.load();
232         _subtitle_alignment = other._subtitle_alignment;
233
234         connect();
235
236         return *this;
237 }
238
239
240 bool
241 have_video (shared_ptr<const Content> content)
242 {
243         return static_cast<bool>(content->video) && content->video->use() && content->can_be_played();
244 }
245
246
247 bool
248 have_audio (shared_ptr<const Content> content)
249 {
250         return static_cast<bool>(content->audio) && content->can_be_played();
251 }
252
253
254 void
255 Player::setup_pieces ()
256 {
257         boost::mutex::scoped_lock lm (_mutex);
258
259         auto old_pieces = _pieces;
260         _pieces.clear ();
261
262         auto film = _film.lock();
263         if (!film) {
264                 return;
265         }
266
267         _playback_length = _playlist ? _playlist->length(film) : film->length();
268
269         auto playlist_content = playlist()->content();
270         bool const have_threed = std::any_of(
271                 playlist_content.begin(),
272                 playlist_content.end(),
273                 [](shared_ptr<const Content> c) {
274                         return c->video && (c->video->frame_type() == VideoFrameType::THREE_D_LEFT || c->video->frame_type() == VideoFrameType::THREE_D_RIGHT);
275                 });
276
277
278         if (have_threed) {
279                 _shuffler.reset(new Shuffler());
280                 _shuffler->Video.connect(bind(&Player::video, this, _1, _2));
281         }
282
283         for (auto content: playlist()->content()) {
284
285                 if (!content->paths_valid()) {
286                         continue;
287                 }
288
289                 if (_ignore_video && _ignore_audio && content->text.empty()) {
290                         /* We're only interested in text and this content has none */
291                         continue;
292                 }
293
294                 shared_ptr<Decoder> old_decoder;
295                 for (auto j: old_pieces) {
296                         if (j->content == content) {
297                                 old_decoder = j->decoder;
298                                 break;
299                         }
300                 }
301
302                 auto decoder = decoder_factory(film, content, _fast, _tolerant, old_decoder);
303                 DCPOMATIC_ASSERT (decoder);
304
305                 FrameRateChange frc(film, content);
306
307                 if (decoder->video && _ignore_video) {
308                         decoder->video->set_ignore (true);
309                 }
310
311                 if (decoder->audio && _ignore_audio) {
312                         decoder->audio->set_ignore (true);
313                 }
314
315                 if (_ignore_text) {
316                         for (auto i: decoder->text) {
317                                 i->set_ignore (true);
318                         }
319                 }
320
321                 auto dcp = dynamic_pointer_cast<DCPDecoder> (decoder);
322                 if (dcp) {
323                         dcp->set_decode_referenced (_play_referenced);
324                         if (_play_referenced) {
325                                 dcp->set_forced_reduction (_dcp_decode_reduction);
326                         }
327                 }
328
329                 auto piece = make_shared<Piece>(content, decoder, frc);
330                 _pieces.push_back (piece);
331
332                 if (decoder->video) {
333                         if (have_threed) {
334                                 /* We need a Shuffler to cope with 3D L/R video data arriving out of sequence */
335                                 decoder->video->Data.connect (bind(&Shuffler::video, _shuffler.get(), weak_ptr<Piece>(piece), _1));
336                         } else {
337                                 decoder->video->Data.connect (bind(&Player::video, this, weak_ptr<Piece>(piece), _1));
338                         }
339                 }
340
341                 if (decoder->audio) {
342                         decoder->audio->Data.connect (bind (&Player::audio, this, weak_ptr<Piece> (piece), _1, _2));
343                 }
344
345                 auto j = decoder->text.begin();
346
347                 while (j != decoder->text.end()) {
348                         (*j)->BitmapStart.connect (
349                                 bind(&Player::bitmap_text_start, this, weak_ptr<Piece>(piece), weak_ptr<const TextContent>((*j)->content()), _1)
350                                 );
351                         (*j)->PlainStart.connect (
352                                 bind(&Player::plain_text_start, this, weak_ptr<Piece>(piece), weak_ptr<const TextContent>((*j)->content()), _1)
353                                 );
354                         (*j)->Stop.connect (
355                                 bind(&Player::subtitle_stop, this, weak_ptr<Piece>(piece), weak_ptr<const TextContent>((*j)->content()), _1)
356                                 );
357
358                         ++j;
359                 }
360
361                 if (decoder->atmos) {
362                         decoder->atmos->Data.connect (bind(&Player::atmos, this, weak_ptr<Piece>(piece), _1));
363                 }
364         }
365
366         _stream_states.clear ();
367         for (auto i: _pieces) {
368                 if (i->content->audio) {
369                         for (auto j: i->content->audio->streams()) {
370                                 _stream_states[j] = StreamState(i);
371                         }
372                 }
373         }
374
375         auto ignore_overlap = [](shared_ptr<VideoContent> v) {
376                 return v && v->use() && v->frame_type() != VideoFrameType::THREE_D_LEFT && v->frame_type() != VideoFrameType::THREE_D_RIGHT;
377         };
378
379         for (auto i = _pieces.begin(); i != _pieces.end(); ++i) {
380                 if (ignore_overlap((*i)->content->video)) {
381                         /* Look for content later in the content list with in-use video that overlaps this */
382                         auto const period = DCPTimePeriod((*i)->content->position(), (*i)->content->end(film));
383                         for (auto j = std::next(i); j != _pieces.end(); ++j) {
384                                 if ((*j)->content->video && ignore_overlap((*j)->content->video)) {
385                                         (*i)->ignore_video = DCPTimePeriod((*j)->content->position(), (*j)->content->end(film)).overlap(period);
386                                 }
387                         }
388                 }
389         }
390
391         _black = Empty(film, playlist(), bind(&have_video, _1), _playback_length);
392         _silent = Empty(film, playlist(), bind(&have_audio, _1), _playback_length);
393
394         _next_video_time = boost::none;
395         _next_audio_time = boost::none;
396 }
397
398
399 void
400 Player::playlist_content_change (ChangeType type, int property, bool frequent)
401 {
402         auto film = _film.lock();
403         if (!film) {
404                 return;
405         }
406
407         if (property == VideoContentProperty::CROP) {
408                 if (type == ChangeType::DONE) {
409                         boost::mutex::scoped_lock lm (_mutex);
410                         for (auto const& i: _delay) {
411                                 i.first->reset_metadata(film, _video_container_size);
412                         }
413                 }
414         } else {
415                 if (type == ChangeType::PENDING) {
416                         /* The player content is probably about to change, so we can't carry on
417                            until that has happened and we've rebuilt our pieces.  Stop pass()
418                            and seek() from working until then.
419                         */
420                         ++_suspended;
421                 } else if (type == ChangeType::DONE) {
422                         /* A change in our content has gone through.  Re-build our pieces. */
423                         setup_pieces ();
424                         --_suspended;
425                 } else if (type == ChangeType::CANCELLED) {
426                         --_suspended;
427                 }
428         }
429
430         Change (type, property, frequent);
431 }
432
433
434 void
435 Player::set_video_container_size (dcp::Size s)
436 {
437         ChangeSignaller<Player, int> cc(this, PlayerProperty::VIDEO_CONTAINER_SIZE);
438
439         if (s == _video_container_size) {
440                 cc.abort();
441                 return;
442         }
443
444         _video_container_size = s;
445
446         {
447                 boost::mutex::scoped_lock lm(_black_image_mutex);
448                 _black_image = make_shared<Image>(AV_PIX_FMT_RGB24, _video_container_size, Image::Alignment::PADDED);
449                 _black_image->make_black ();
450         }
451 }
452
453
454 void
455 Player::playlist_change (ChangeType type)
456 {
457         if (type == ChangeType::DONE) {
458                 setup_pieces ();
459         }
460         Change (type, PlayerProperty::PLAYLIST, false);
461 }
462
463
464 void
465 Player::film_change (ChangeType type, Film::Property p)
466 {
467         /* Here we should notice Film properties that affect our output, and
468            alert listeners that our output now would be different to how it was
469            last time we were run.
470         */
471
472         auto film = _film.lock();
473         if (!film) {
474                 return;
475         }
476
477         if (p == Film::Property::CONTAINER) {
478                 Change (type, PlayerProperty::FILM_CONTAINER, false);
479         } else if (p == Film::Property::VIDEO_FRAME_RATE) {
480                 /* Pieces contain a FrameRateChange which contains the DCP frame rate,
481                    so we need new pieces here.
482                 */
483                 if (type == ChangeType::DONE) {
484                         setup_pieces ();
485                 }
486                 Change (type, PlayerProperty::FILM_VIDEO_FRAME_RATE, false);
487         } else if (p == Film::Property::AUDIO_PROCESSOR) {
488                 if (type == ChangeType::DONE && film->audio_processor ()) {
489                         boost::mutex::scoped_lock lm (_mutex);
490                         _audio_processor = film->audio_processor()->clone(film->audio_frame_rate());
491                 }
492         } else if (p == Film::Property::AUDIO_CHANNELS) {
493                 if (type == ChangeType::DONE) {
494                         boost::mutex::scoped_lock lm (_mutex);
495                         _audio_merger.clear ();
496                 }
497         }
498 }
499
500
501 shared_ptr<PlayerVideo>
502 Player::black_player_video_frame (Eyes eyes) const
503 {
504         boost::mutex::scoped_lock lm(_black_image_mutex);
505
506         return std::make_shared<PlayerVideo> (
507                 make_shared<const RawImageProxy>(_black_image),
508                 Crop(),
509                 optional<double>(),
510                 _video_container_size,
511                 _video_container_size,
512                 eyes,
513                 Part::WHOLE,
514                 PresetColourConversion::all().front().conversion,
515                 VideoRange::FULL,
516                 std::weak_ptr<Content>(),
517                 boost::optional<dcpomatic::ContentTime>(),
518                 false
519         );
520 }
521
522
523 Frame
524 Player::dcp_to_content_video (shared_ptr<const Piece> piece, DCPTime t) const
525 {
526         auto film = _film.lock();
527         DCPOMATIC_ASSERT(film);
528
529         auto s = t - piece->content->position ();
530         s = min (piece->content->length_after_trim(film), s);
531         s = max (DCPTime(), s + DCPTime (piece->content->trim_start(), piece->frc));
532
533         /* It might seem more logical here to convert s to a ContentTime (using the FrameRateChange)
534            then convert that ContentTime to frames at the content's rate.  However this fails for
535            situations like content at 29.9978733fps, DCP at 30fps.  The accuracy of the Time type is not
536            enough to distinguish between the two with low values of time (e.g. 3200 in Time units).
537
538            Instead we convert the DCPTime using the DCP video rate then account for any skip/repeat.
539         */
540         return s.frames_floor (piece->frc.dcp) / piece->frc.factor ();
541 }
542
543
544 DCPTime
545 Player::content_video_to_dcp (shared_ptr<const Piece> piece, Frame f) const
546 {
547         /* See comment in dcp_to_content_video */
548         auto const d = DCPTime::from_frames (f * piece->frc.factor(), piece->frc.dcp) - DCPTime(piece->content->trim_start(), piece->frc);
549         return d + piece->content->position();
550 }
551
552
553 Frame
554 Player::dcp_to_resampled_audio (shared_ptr<const Piece> piece, DCPTime t) const
555 {
556         auto film = _film.lock();
557         DCPOMATIC_ASSERT(film);
558
559         auto s = t - piece->content->position ();
560         s = min (piece->content->length_after_trim(film), s);
561         /* See notes in dcp_to_content_video */
562         return max (DCPTime(), DCPTime(piece->content->trim_start(), piece->frc) + s).frames_floor(film->audio_frame_rate());
563 }
564
565
566 DCPTime
567 Player::resampled_audio_to_dcp (shared_ptr<const Piece> piece, Frame f) const
568 {
569         auto film = _film.lock();
570         DCPOMATIC_ASSERT(film);
571
572         /* See comment in dcp_to_content_video */
573         return DCPTime::from_frames(f, film->audio_frame_rate())
574                 - DCPTime (piece->content->trim_start(), piece->frc)
575                 + piece->content->position();
576 }
577
578
579 ContentTime
580 Player::dcp_to_content_time (shared_ptr<const Piece> piece, DCPTime t) const
581 {
582         auto film = _film.lock();
583         DCPOMATIC_ASSERT(film);
584
585         auto s = t - piece->content->position ();
586         s = min (piece->content->length_after_trim(film), s);
587         return max (ContentTime (), ContentTime (s, piece->frc) + piece->content->trim_start());
588 }
589
590
591 DCPTime
592 Player::content_time_to_dcp (shared_ptr<const Piece> piece, ContentTime t) const
593 {
594         return max (DCPTime(), DCPTime(t - piece->content->trim_start(), piece->frc) + piece->content->position());
595 }
596
597
598 vector<shared_ptr<Font>>
599 Player::get_subtitle_fonts ()
600 {
601         boost::mutex::scoped_lock lm (_mutex);
602
603         vector<shared_ptr<Font>> fonts;
604         for (auto piece: _pieces) {
605                 for (auto text: piece->content->text) {
606                         auto text_fonts = text->fonts();
607                         copy (text_fonts.begin(), text_fonts.end(), back_inserter(fonts));
608                 }
609         }
610
611         return fonts;
612 }
613
614
615 /** Set this player never to produce any video data */
616 void
617 Player::set_ignore_video ()
618 {
619         ChangeSignaller<Player, int> cc(this, PlayerProperty::IGNORE_VIDEO);
620         _ignore_video = true;
621         setup_pieces();
622 }
623
624
625 void
626 Player::set_ignore_audio ()
627 {
628         ChangeSignaller<Player, int> cc(this, PlayerProperty::IGNORE_AUDIO);
629         _ignore_audio = true;
630         setup_pieces();
631 }
632
633
634 void
635 Player::set_ignore_text ()
636 {
637         ChangeSignaller<Player, int> cc(this, PlayerProperty::IGNORE_TEXT);
638         _ignore_text = true;
639         setup_pieces();
640 }
641
642
643 /** Set the player to always burn open texts into the image regardless of the content settings */
644 void
645 Player::set_always_burn_open_subtitles ()
646 {
647         ChangeSignaller<Player, int> cc(this, PlayerProperty::ALWAYS_BURN_OPEN_SUBTITLES);
648         _always_burn_open_subtitles = true;
649 }
650
651
652 /** Sets up the player to be faster, possibly at the expense of quality */
653 void
654 Player::set_fast ()
655 {
656         _fast = true;
657         setup_pieces();
658 }
659
660
661 void
662 Player::set_play_referenced ()
663 {
664         ChangeSignaller<Player, int> cc(this, PlayerProperty::PLAY_REFERENCED);
665         _play_referenced = true;
666         setup_pieces();
667 }
668
669
670 bool
671 Player::pass ()
672 {
673         boost::mutex::scoped_lock lm (_mutex);
674
675         if (_suspended) {
676                 /* We can't pass in this state */
677                 LOG_DEBUG_PLAYER_NC ("Player is suspended");
678                 return false;
679         }
680
681         auto film = _film.lock();
682
683         if (_playback_length.load() == DCPTime() || !film) {
684                 /* Special; just give one black frame */
685                 use_video(black_player_video_frame(Eyes::BOTH), DCPTime(), one_video_frame());
686                 return true;
687         }
688
689         /* Find the decoder or empty which is farthest behind where we are and make it emit some data */
690
691         shared_ptr<Piece> earliest_content;
692         optional<DCPTime> earliest_time;
693
694         for (auto i: _pieces) {
695                 if (i->done) {
696                         continue;
697                 }
698
699                 auto const t = content_time_to_dcp (i, max(i->decoder->position(), i->content->trim_start()));
700                 if (t > i->content->end(film)) {
701                         i->done = true;
702                 } else {
703
704                         /* Given two choices at the same time, pick the one with texts so we see it before
705                            the video.
706                         */
707                         if (!earliest_time || t < *earliest_time || (t == *earliest_time && !i->decoder->text.empty())) {
708                                 earliest_time = t;
709                                 earliest_content = i;
710                         }
711                 }
712         }
713
714         bool done = false;
715
716         enum {
717                 NONE,
718                 CONTENT,
719                 BLACK,
720                 SILENT
721         } which = NONE;
722
723         if (earliest_content) {
724                 which = CONTENT;
725         }
726
727         if (!_black.done() && !_ignore_video && (!earliest_time || _black.position() < *earliest_time)) {
728                 earliest_time = _black.position ();
729                 which = BLACK;
730         }
731
732         if (!_silent.done() && !_ignore_audio && (!earliest_time || _silent.position() < *earliest_time)) {
733                 earliest_time = _silent.position ();
734                 which = SILENT;
735         }
736
737         switch (which) {
738         case CONTENT:
739         {
740                 LOG_DEBUG_PLAYER ("Calling pass() on %1", earliest_content->content->path(0));
741                 earliest_content->done = earliest_content->decoder->pass ();
742                 auto dcp = dynamic_pointer_cast<DCPContent>(earliest_content->content);
743                 if (dcp && !_play_referenced) {
744                         if (dcp->reference_video()) {
745                                 _next_video_time = dcp->end(film);
746                         }
747                         if (dcp->reference_audio()) {
748                                 /* We are skipping some referenced DCP audio content, so we need to update _next_audio_time
749                                    to `hide' the fact that no audio was emitted during the referenced DCP (though
750                                    we need to behave as though it was).
751                                 */
752                                 _next_audio_time = dcp->end(film);
753                         }
754                 }
755                 break;
756         }
757         case BLACK:
758                 LOG_DEBUG_PLAYER ("Emit black for gap at %1", to_string(_black.position()));
759                 use_video(black_player_video_frame(Eyes::BOTH), _black.position(), _black.period_at_position().to);
760                 _black.set_position (_black.position() + one_video_frame());
761                 break;
762         case SILENT:
763         {
764                 LOG_DEBUG_PLAYER ("Emit silence for gap at %1", to_string(_silent.position()));
765                 DCPTimePeriod period (_silent.period_at_position());
766                 if (_next_audio_time) {
767                         /* Sometimes the thing that happened last finishes fractionally before
768                            or after this silence.  Bodge the start time of the silence to fix it.
769                            I think this is nothing to worry about since we will just add or
770                            remove a little silence at the end of some content.
771                         */
772                         int64_t const error = labs(period.from.get() - _next_audio_time->get());
773                         /* Let's not worry about less than a frame at 24fps */
774                         int64_t const too_much_error = DCPTime::from_frames(1, 24).get();
775                         if (error >= too_much_error) {
776                                 film->log()->log(String::compose("Silence starting before or after last audio by %1", error), LogEntry::TYPE_ERROR);
777                         }
778                         DCPOMATIC_ASSERT (error < too_much_error);
779                         period.from = *_next_audio_time;
780                 }
781                 if (period.duration() > one_video_frame()) {
782                         period.to = period.from + one_video_frame();
783                 }
784                 fill_audio (period);
785                 _silent.set_position (period.to);
786                 break;
787         }
788         case NONE:
789                 done = true;
790                 break;
791         }
792
793         /* Emit any audio that is ready */
794
795         /* Work out the time before which the audio is definitely all here.  This is the earliest last_push_end of one
796            of our streams, or the position of the _silent.  First, though we choose only streams that are less than
797            ignore_streams_behind seconds behind the furthest ahead (we assume that if a stream has fallen that far
798            behind it has finished).  This is so that we don't withhold audio indefinitely awaiting data from a stream
799            that will never come, causing bugs like #2101.
800         */
801         constexpr int ignore_streams_behind = 5;
802
803         using state_pair = std::pair<AudioStreamPtr, StreamState>;
804
805         /* Find streams that have pushed */
806         std::vector<state_pair> have_pushed;
807         std::copy_if(_stream_states.begin(), _stream_states.end(), std::back_inserter(have_pushed), [](state_pair const& a) { return static_cast<bool>(a.second.last_push_end); });
808
809         /* Find the 'leading' stream (i.e. the one that pushed data most recently) */
810         auto latest_last_push_end = std::max_element(
811                 have_pushed.begin(),
812                 have_pushed.end(),
813                 [](state_pair const& a, state_pair const& b) { return a.second.last_push_end.get() < b.second.last_push_end.get(); }
814                 );
815
816         if (latest_last_push_end != have_pushed.end()) {
817                 LOG_DEBUG_PLAYER("Leading audio stream is in %1 at %2", latest_last_push_end->second.piece->content->path(0), to_string(latest_last_push_end->second.last_push_end.get()));
818         }
819
820         /* Now make a list of those streams that are less than ignore_streams_behind behind the leader */
821         std::map<AudioStreamPtr, StreamState> alive_stream_states;
822         for (auto const& i: _stream_states) {
823                 if (!i.second.last_push_end || (latest_last_push_end->second.last_push_end.get() - i.second.last_push_end.get()) < dcpomatic::DCPTime::from_seconds(ignore_streams_behind)) {
824                         alive_stream_states.insert(i);
825                 } else {
826                         LOG_DEBUG_PLAYER("Ignoring stream %1 because it is too far behind", i.second.piece->content->path(0));
827                 }
828         }
829
830         auto pull_to = _playback_length.load();
831         for (auto const& i: alive_stream_states) {
832                 auto position = i.second.last_push_end.get_value_or(i.second.piece->content->position());
833                 if (!i.second.piece->done && position < pull_to) {
834                         pull_to = position;
835                 }
836         }
837         if (!_silent.done() && _silent.position() < pull_to) {
838                 pull_to = _silent.position();
839         }
840
841         LOG_DEBUG_PLAYER("Emitting audio up to %1", to_string(pull_to));
842         auto audio = _audio_merger.pull (pull_to);
843         for (auto i = audio.begin(); i != audio.end(); ++i) {
844                 if (_next_audio_time && i->second < *_next_audio_time) {
845                         /* This new data comes before the last we emitted (or the last seek); discard it */
846                         auto cut = discard_audio (i->first, i->second, *_next_audio_time);
847                         if (!cut.first) {
848                                 continue;
849                         }
850                         *i = cut;
851                 } else if (_next_audio_time && i->second > *_next_audio_time) {
852                         /* There's a gap between this data and the last we emitted; fill with silence */
853                         fill_audio (DCPTimePeriod (*_next_audio_time, i->second));
854                 }
855
856                 emit_audio (i->first, i->second);
857         }
858
859         if (done) {
860                 emit_video_until(film->length());
861
862                 if (_shuffler) {
863                         _shuffler->flush ();
864                 }
865                 for (auto const& i: _delay) {
866                         emit_video(i.first, i.second);
867                 }
868         }
869
870         return done;
871 }
872
873
874 /** @return Open subtitles for the frame at the given time, converted to images */
875 optional<PositionImage>
876 Player::open_subtitles_for_frame (DCPTime time) const
877 {
878         auto film = _film.lock();
879         if (!film) {
880                 return {};
881         }
882
883         list<PositionImage> captions;
884         int const vfr = film->video_frame_rate();
885
886         for (
887                 auto j:
888                 _active_texts[TextType::OPEN_SUBTITLE].get_burnt(DCPTimePeriod(time, time + DCPTime::from_frames(1, vfr)), _always_burn_open_subtitles)
889                 ) {
890
891                 /* Bitmap subtitles */
892                 for (auto i: j.bitmap) {
893                         if (!i.image) {
894                                 continue;
895                         }
896
897                         /* i.image will already have been scaled to fit _video_container_size */
898                         dcp::Size scaled_size (i.rectangle.width * _video_container_size.load().width, i.rectangle.height * _video_container_size.load().height);
899
900                         captions.push_back (
901                                 PositionImage (
902                                         i.image,
903                                         Position<int> (
904                                                 lrint(_video_container_size.load().width * i.rectangle.x),
905                                                 lrint(_video_container_size.load().height * i.rectangle.y)
906                                                 )
907                                         )
908                                 );
909                 }
910
911                 /* String subtitles (rendered to an image) */
912                 if (!j.string.empty()) {
913                         auto s = render_text(j.string, _video_container_size, time, vfr);
914                         copy (s.begin(), s.end(), back_inserter (captions));
915                 }
916         }
917
918         if (captions.empty()) {
919                 return {};
920         }
921
922         return merge (captions, _subtitle_alignment);
923 }
924
925
926 void
927 Player::emit_video_until(DCPTime time)
928 {
929         auto frame = [this](shared_ptr<PlayerVideo> pv, DCPTime time) {
930                 /* We need a delay to give a little wiggle room to ensure that relevant subtitles arrive at the
931                    player before the video that requires them.
932                 */
933                 _delay.push_back(make_pair(pv, time));
934
935                 if (pv->eyes() == Eyes::BOTH || pv->eyes() == Eyes::RIGHT) {
936                         _next_video_time = time + one_video_frame();
937                 }
938
939                 if (_delay.size() < 3) {
940                         return;
941                 }
942
943                 auto to_do = _delay.front();
944                 _delay.pop_front();
945                 emit_video(to_do.first, to_do.second);
946         };
947
948         auto const age_threshold = one_video_frame() * 2;
949
950         while (_next_video_time.get_value_or({}) < time) {
951                 auto left = _last_video[Eyes::LEFT];
952                 auto right = _last_video[Eyes::RIGHT];
953                 auto both = _last_video[Eyes::BOTH];
954
955                 auto const next = _next_video_time.get_value_or({});
956
957                 if (
958                         left.first &&
959                         right.first &&
960                         (!both.first || (left.second >= both.second && right.second >= both.second)) &&
961                         (left.second - next) < age_threshold &&
962                         (right.second - next) < age_threshold
963                    ) {
964                         frame(left.first, next);
965                         frame(right.first, next);
966                 } else if (both.first && (both.second - next) < age_threshold) {
967                         frame(both.first, next);
968                         LOG_DEBUG_PLAYER("Content %1 selected for DCP %2 (age %3)", to_string(both.second), to_string(next), to_string(both.second - next));
969                 } else {
970                         auto film = _film.lock();
971                         if (film && film->three_d()) {
972                                 frame(black_player_video_frame(Eyes::LEFT), next);
973                                 frame(black_player_video_frame(Eyes::RIGHT), next);
974                         } else {
975                                 frame(black_player_video_frame(Eyes::BOTH), next);
976                         }
977                         LOG_DEBUG_PLAYER("Black selected for DCP %1", to_string(next));
978                 }
979         }
980 }
981
982
983 void
984 Player::video (weak_ptr<Piece> weak_piece, ContentVideo video)
985 {
986         if (_suspended) {
987                 return;
988         }
989
990         auto piece = weak_piece.lock ();
991         if (!piece) {
992                 return;
993         }
994
995         if (!piece->content->video->use()) {
996                 return;
997         }
998
999         auto film = _film.lock();
1000         if (!film) {
1001                 return;
1002         }
1003
1004         vector<Eyes> eyes_to_emit;
1005
1006         if (!film->three_d()) {
1007                 if (video.eyes == Eyes::RIGHT) {
1008                         /* 2D film, 3D content: discard right */
1009                         return;
1010                 } else if (video.eyes == Eyes::LEFT) {
1011                         /* 2D film, 3D content: emit left as "both" */
1012                         video.eyes = Eyes::BOTH;
1013                         eyes_to_emit = { Eyes::BOTH };
1014                 }
1015         } else {
1016                 if (video.eyes == Eyes::BOTH) {
1017                         /* 3D film, 2D content; emit "both" for left and right */
1018                         eyes_to_emit = { Eyes::LEFT, Eyes::RIGHT };
1019                 }
1020         }
1021
1022         if (eyes_to_emit.empty()) {
1023                 eyes_to_emit = { video.eyes };
1024         }
1025
1026         /* Time of the frame we just received within the DCP */
1027         auto const time = content_time_to_dcp(piece, video.time);
1028         LOG_DEBUG_PLAYER("Received video frame %1 %2 eyes %3", to_string(video.time), to_string(time), static_cast<int>(video.eyes));
1029
1030         if (time < piece->content->position()) {
1031                 return;
1032         }
1033
1034         if (piece->ignore_video && piece->ignore_video->contains(time)) {
1035                 return;
1036         }
1037
1038         if (!_next_video_time) {
1039                 _next_video_time = time.round(film->video_frame_rate());
1040         }
1041
1042         auto const content_video = piece->content->video;
1043
1044         for (auto eyes: eyes_to_emit) {
1045                 use_video(
1046                         std::make_shared<PlayerVideo>(
1047                                 video.image,
1048                                 content_video->actual_crop(),
1049                                 content_video->fade(film, video.time),
1050                                 scale_for_display(
1051                                         content_video->scaled_size(film->frame_size()),
1052                                         _video_container_size,
1053                                         film->frame_size(),
1054                                         content_video->pixel_quanta()
1055                                         ),
1056                                 _video_container_size,
1057                                 eyes,
1058                                 video.part,
1059                                 content_video->colour_conversion(),
1060                                 content_video->range(),
1061                                 piece->content,
1062                                 video.time,
1063                                 false
1064                                 ),
1065                         time,
1066                         piece->content->end(film)
1067                         );
1068         }
1069 }
1070
1071 void
1072 Player::use_video(shared_ptr<PlayerVideo> pv, DCPTime time, DCPTime end)
1073 {
1074         _last_video[pv->eyes()] = { pv, time };
1075         if (pv->eyes() != Eyes::LEFT) {
1076                 emit_video_until(std::min(time + one_video_frame() / 2, end));
1077         }
1078 }
1079
1080
1081 void
1082 Player::audio (weak_ptr<Piece> weak_piece, AudioStreamPtr stream, ContentAudio content_audio)
1083 {
1084         if (_suspended) {
1085                 return;
1086         }
1087
1088         DCPOMATIC_ASSERT (content_audio.audio->frames() > 0);
1089
1090         auto piece = weak_piece.lock ();
1091         if (!piece) {
1092                 return;
1093         }
1094
1095         auto film = _film.lock();
1096         if (!film) {
1097                 return;
1098         }
1099
1100         auto content = piece->content->audio;
1101         DCPOMATIC_ASSERT (content);
1102
1103         int const rfr = content->resampled_frame_rate(film);
1104
1105         /* Compute time in the DCP */
1106         auto time = resampled_audio_to_dcp (piece, content_audio.frame);
1107
1108         /* And the end of this block in the DCP */
1109         auto end = time + DCPTime::from_frames(content_audio.audio->frames(), rfr);
1110         LOG_DEBUG_PLAYER("Received audio frame %1 covering %2 to %3 (%4)", content_audio.frame, to_string(time), to_string(end), piece->content->path(0).filename());
1111
1112         /* Remove anything that comes before the start or after the end of the content */
1113         if (time < piece->content->position()) {
1114                 auto cut = discard_audio (content_audio.audio, time, piece->content->position());
1115                 if (!cut.first) {
1116                         /* This audio is entirely discarded */
1117                         return;
1118                 }
1119                 content_audio.audio = cut.first;
1120                 time = cut.second;
1121         } else if (time > piece->content->end(film)) {
1122                 /* Discard it all */
1123                 return;
1124         } else if (end > piece->content->end(film)) {
1125                 Frame const remaining_frames = DCPTime(piece->content->end(film) - time).frames_round(rfr);
1126                 if (remaining_frames == 0) {
1127                         return;
1128                 }
1129                 content_audio.audio = make_shared<AudioBuffers>(content_audio.audio, remaining_frames, 0);
1130         }
1131
1132         DCPOMATIC_ASSERT (content_audio.audio->frames() > 0);
1133
1134         /* Gain and fade */
1135
1136         auto const fade_coeffs = content->fade (stream, content_audio.frame, content_audio.audio->frames(), rfr);
1137         if (content->gain() != 0 || !fade_coeffs.empty()) {
1138                 auto gain_buffers = make_shared<AudioBuffers>(content_audio.audio);
1139                 if (!fade_coeffs.empty()) {
1140                         /* Apply both fade and gain */
1141                         DCPOMATIC_ASSERT (fade_coeffs.size() == static_cast<size_t>(gain_buffers->frames()));
1142                         auto const channels = gain_buffers->channels();
1143                         auto const frames = fade_coeffs.size();
1144                         auto data = gain_buffers->data();
1145                         auto const gain = db_to_linear (content->gain());
1146                         for (auto channel = 0; channel < channels; ++channel) {
1147                                 for (auto frame = 0U; frame < frames; ++frame) {
1148                                         data[channel][frame] *= gain * fade_coeffs[frame];
1149                                 }
1150                         }
1151                 } else {
1152                         /* Just apply gain */
1153                         gain_buffers->apply_gain (content->gain());
1154                 }
1155                 content_audio.audio = gain_buffers;
1156         }
1157
1158         /* Remap */
1159
1160         content_audio.audio = remap(content_audio.audio, film->audio_channels(), stream->mapping());
1161
1162         /* Process */
1163
1164         if (_audio_processor) {
1165                 content_audio.audio = _audio_processor->run(content_audio.audio, film->audio_channels());
1166         }
1167
1168         /* Push */
1169
1170         _audio_merger.push (content_audio.audio, time);
1171         DCPOMATIC_ASSERT (_stream_states.find (stream) != _stream_states.end ());
1172         _stream_states[stream].last_push_end = time + DCPTime::from_frames(content_audio.audio->frames(), film->audio_frame_rate());
1173 }
1174
1175
1176 void
1177 Player::bitmap_text_start (weak_ptr<Piece> weak_piece, weak_ptr<const TextContent> weak_content, ContentBitmapText subtitle)
1178 {
1179         if (_suspended) {
1180                 return;
1181         }
1182
1183         auto piece = weak_piece.lock ();
1184         auto content = weak_content.lock ();
1185         if (!piece || !content) {
1186                 return;
1187         }
1188
1189         PlayerText ps;
1190         for (auto& sub: subtitle.subs)
1191         {
1192                 /* Apply content's subtitle offsets */
1193                 sub.rectangle.x += content->x_offset ();
1194                 sub.rectangle.y += content->y_offset ();
1195
1196                 /* Apply a corrective translation to keep the subtitle centred after the scale that is coming up */
1197                 sub.rectangle.x -= sub.rectangle.width * ((content->x_scale() - 1) / 2);
1198                 sub.rectangle.y -= sub.rectangle.height * ((content->y_scale() - 1) / 2);
1199
1200                 /* Apply content's subtitle scale */
1201                 sub.rectangle.width *= content->x_scale ();
1202                 sub.rectangle.height *= content->y_scale ();
1203
1204                 auto image = sub.image;
1205
1206                 /* We will scale the subtitle up to fit _video_container_size */
1207                 int const width = sub.rectangle.width * _video_container_size.load().width;
1208                 int const height = sub.rectangle.height * _video_container_size.load().height;
1209                 if (width == 0 || height == 0) {
1210                         return;
1211                 }
1212
1213                 dcp::Size scaled_size (width, height);
1214                 ps.bitmap.push_back (BitmapText(image->scale(scaled_size, dcp::YUVToRGB::REC601, image->pixel_format(), Image::Alignment::PADDED, _fast), sub.rectangle));
1215         }
1216
1217         DCPTime from(content_time_to_dcp(piece, subtitle.from()));
1218         _active_texts[content->type()].add_from(weak_content, ps, from);
1219 }
1220
1221
1222 void
1223 Player::plain_text_start (weak_ptr<Piece> weak_piece, weak_ptr<const TextContent> weak_content, ContentStringText subtitle)
1224 {
1225         if (_suspended) {
1226                 return;
1227         }
1228
1229         auto piece = weak_piece.lock ();
1230         auto content = weak_content.lock ();
1231         auto film = _film.lock();
1232         if (!piece || !content || !film) {
1233                 return;
1234         }
1235
1236         PlayerText ps;
1237         DCPTime const from (content_time_to_dcp (piece, subtitle.from()));
1238
1239         if (from > piece->content->end(film)) {
1240                 return;
1241         }
1242
1243         for (auto s: subtitle.subs) {
1244                 s.set_h_position (s.h_position() + content->x_offset());
1245                 s.set_v_position (s.v_position() + content->y_offset());
1246                 float const xs = content->x_scale();
1247                 float const ys = content->y_scale();
1248                 float size = s.size();
1249
1250                 /* Adjust size to express the common part of the scaling;
1251                    e.g. if xs = ys = 0.5 we scale size by 2.
1252                 */
1253                 if (xs > 1e-5 && ys > 1e-5) {
1254                         size *= 1 / min (1 / xs, 1 / ys);
1255                 }
1256                 s.set_size (size);
1257
1258                 /* Then express aspect ratio changes */
1259                 if (fabs (1.0 - xs / ys) > dcp::ASPECT_ADJUST_EPSILON) {
1260                         s.set_aspect_adjust (xs / ys);
1261                 }
1262
1263                 s.set_in (dcp::Time(from.seconds(), 1000));
1264                 ps.string.push_back (s);
1265         }
1266
1267         _active_texts[content->type()].add_from(weak_content, ps, from);
1268 }
1269
1270
1271 void
1272 Player::subtitle_stop (weak_ptr<Piece> weak_piece, weak_ptr<const TextContent> weak_content, ContentTime to)
1273 {
1274         if (_suspended) {
1275                 return;
1276         }
1277
1278         auto content = weak_content.lock ();
1279         if (!content) {
1280                 return;
1281         }
1282
1283         if (!_active_texts[content->type()].have(weak_content)) {
1284                 return;
1285         }
1286
1287         auto piece = weak_piece.lock ();
1288         auto film = _film.lock();
1289         if (!piece || !film) {
1290                 return;
1291         }
1292
1293         DCPTime const dcp_to = content_time_to_dcp (piece, to);
1294
1295         if (dcp_to > piece->content->end(film)) {
1296                 return;
1297         }
1298
1299         auto from = _active_texts[content->type()].add_to(weak_content, dcp_to);
1300
1301         bool const always = (content->type() == TextType::OPEN_SUBTITLE && _always_burn_open_subtitles);
1302         if (content->use() && !always && !content->burn()) {
1303                 Text (from.first, content->type(), content->dcp_track().get_value_or(DCPTextTrack()), DCPTimePeriod(from.second, dcp_to));
1304         }
1305 }
1306
1307
1308 void
1309 Player::seek (DCPTime time, bool accurate)
1310 {
1311         boost::mutex::scoped_lock lm (_mutex);
1312         LOG_DEBUG_PLAYER("Seek to %1 (%2accurate)", to_string(time), accurate ? "" : "in");
1313
1314         if (_suspended) {
1315                 /* We can't seek in this state */
1316                 return;
1317         }
1318
1319         auto film = _film.lock();
1320         if (!film) {
1321                 return;
1322         }
1323
1324         if (_shuffler) {
1325                 _shuffler->clear ();
1326         }
1327
1328         _delay.clear ();
1329
1330         if (_audio_processor) {
1331                 _audio_processor->flush ();
1332         }
1333
1334         _audio_merger.clear ();
1335         std::for_each(_active_texts.begin(), _active_texts.end(), [](ActiveText& a) { a.clear(); });
1336
1337         for (auto i: _pieces) {
1338                 if (time < i->content->position()) {
1339                         /* Before; seek to the start of the content.  Even if this request is for an inaccurate seek
1340                            we must seek this (following) content accurately, otherwise when we come to the end of the current
1341                            content we may not start right at the beginning of the next, causing a gap (if the next content has
1342                            been trimmed to a point between keyframes, or something).
1343                         */
1344                         i->decoder->seek (dcp_to_content_time (i, i->content->position()), true);
1345                         i->done = false;
1346                 } else if (i->content->position() <= time && time < i->content->end(film)) {
1347                         /* During; seek to position */
1348                         i->decoder->seek (dcp_to_content_time (i, time), accurate);
1349                         i->done = false;
1350                 } else {
1351                         /* After; this piece is done */
1352                         i->done = true;
1353                 }
1354         }
1355
1356         if (accurate) {
1357                 _next_video_time = time;
1358                 _next_audio_time = time;
1359         } else {
1360                 _next_video_time = boost::none;
1361                 _next_audio_time = boost::none;
1362         }
1363
1364         _black.set_position (time);
1365         _silent.set_position (time);
1366
1367         _last_video[Eyes::LEFT] = {};
1368         _last_video[Eyes::RIGHT] = {};
1369         _last_video[Eyes::BOTH] = {};
1370
1371         for (auto& state: _stream_states) {
1372                 state.second.last_push_end = boost::none;
1373         }
1374 }
1375
1376
1377 void
1378 Player::emit_video(shared_ptr<PlayerVideo> pv, DCPTime time)
1379 {
1380         if (pv->eyes() == Eyes::BOTH || pv->eyes() == Eyes::RIGHT) {
1381                 std::for_each(_active_texts.begin(), _active_texts.end(), [time](ActiveText& a) { a.clear_before(time); });
1382         }
1383
1384         auto subtitles = open_subtitles_for_frame (time);
1385         if (subtitles) {
1386                 pv->set_text (subtitles.get ());
1387         }
1388
1389         Video (pv, time);
1390 }
1391
1392
1393 void
1394 Player::emit_audio (shared_ptr<AudioBuffers> data, DCPTime time)
1395 {
1396         auto film = _film.lock();
1397         DCPOMATIC_ASSERT(film);
1398
1399         /* Log if the assert below is about to fail */
1400         if (_next_audio_time && labs(time.get() - _next_audio_time->get()) > 1) {
1401                 film->log()->log(String::compose("Out-of-sequence emit %1 vs %2", to_string(time), to_string(*_next_audio_time)), LogEntry::TYPE_WARNING);
1402         }
1403
1404         /* This audio must follow on from the previous, allowing for half a sample (at 48kHz) leeway */
1405         DCPOMATIC_ASSERT (!_next_audio_time || labs(time.get() - _next_audio_time->get()) < 2);
1406         Audio(data, time, film->audio_frame_rate());
1407         _next_audio_time = time + DCPTime::from_frames(data->frames(), film->audio_frame_rate());
1408 }
1409
1410
1411 void
1412 Player::fill_audio (DCPTimePeriod period)
1413 {
1414         auto film = _film.lock();
1415         DCPOMATIC_ASSERT(film);
1416
1417         if (period.from == period.to) {
1418                 return;
1419         }
1420
1421         DCPOMATIC_ASSERT (period.from < period.to);
1422
1423         DCPTime t = period.from;
1424         while (t < period.to) {
1425                 DCPTime block = min (DCPTime::from_seconds (0.5), period.to - t);
1426                 Frame const samples = block.frames_round(film->audio_frame_rate());
1427                 if (samples) {
1428                         auto silence = make_shared<AudioBuffers>(film->audio_channels(), samples);
1429                         silence->make_silent ();
1430                         emit_audio (silence, t);
1431                 }
1432                 t += block;
1433         }
1434 }
1435
1436
1437 DCPTime
1438 Player::one_video_frame () const
1439 {
1440         auto film = _film.lock();
1441         DCPOMATIC_ASSERT(film);
1442
1443         return DCPTime::from_frames(1, film->video_frame_rate ());
1444 }
1445
1446
1447 pair<shared_ptr<AudioBuffers>, DCPTime>
1448 Player::discard_audio (shared_ptr<const AudioBuffers> audio, DCPTime time, DCPTime discard_to) const
1449 {
1450         auto film = _film.lock();
1451         DCPOMATIC_ASSERT(film);
1452
1453         auto const discard_time = discard_to - time;
1454         auto const discard_frames = discard_time.frames_round(film->audio_frame_rate());
1455         auto remaining_frames = audio->frames() - discard_frames;
1456         if (remaining_frames <= 0) {
1457                 return make_pair(shared_ptr<AudioBuffers>(), DCPTime());
1458         }
1459         auto cut = make_shared<AudioBuffers>(audio, remaining_frames, discard_frames);
1460         return make_pair(cut, time + discard_time);
1461 }
1462
1463
1464 void
1465 Player::set_dcp_decode_reduction (optional<int> reduction)
1466 {
1467         ChangeSignaller<Player, int> cc(this, PlayerProperty::DCP_DECODE_REDUCTION);
1468
1469         if (reduction == _dcp_decode_reduction.load()) {
1470                 cc.abort();
1471                 return;
1472         }
1473
1474         _dcp_decode_reduction = reduction;
1475         setup_pieces();
1476 }
1477
1478
1479 optional<DCPTime>
1480 Player::content_time_to_dcp (shared_ptr<const Content> content, ContentTime t) const
1481 {
1482         boost::mutex::scoped_lock lm (_mutex);
1483
1484         for (auto i: _pieces) {
1485                 if (i->content == content) {
1486                         return content_time_to_dcp (i, t);
1487                 }
1488         }
1489
1490         /* We couldn't find this content; perhaps things are being changed over */
1491         return {};
1492 }
1493
1494
1495 optional<ContentTime>
1496 Player::dcp_to_content_time (shared_ptr<const Content> content, DCPTime t) const
1497 {
1498         boost::mutex::scoped_lock lm (_mutex);
1499
1500         for (auto i: _pieces) {
1501                 if (i->content == content) {
1502                         return dcp_to_content_time (i, t);
1503                 }
1504         }
1505
1506         /* We couldn't find this content; perhaps things are being changed over */
1507         return {};
1508 }
1509
1510
1511 shared_ptr<const Playlist>
1512 Player::playlist () const
1513 {
1514         auto film = _film.lock();
1515         if (!film) {
1516                 return {};
1517         }
1518
1519         return _playlist ? _playlist : film->playlist();
1520 }
1521
1522
1523 void
1524 Player::atmos (weak_ptr<Piece> weak_piece, ContentAtmos data)
1525 {
1526         if (_suspended) {
1527                 return;
1528         }
1529
1530         auto film = _film.lock();
1531         DCPOMATIC_ASSERT(film);
1532
1533         auto piece = weak_piece.lock ();
1534         DCPOMATIC_ASSERT (piece);
1535
1536         auto const vfr = film->video_frame_rate();
1537
1538         DCPTime const dcp_time = DCPTime::from_frames(data.frame, vfr) - DCPTime(piece->content->trim_start(), FrameRateChange(vfr, vfr));
1539         if (dcp_time < piece->content->position() || dcp_time >= (piece->content->end(film))) {
1540                 return;
1541         }
1542
1543         Atmos (data.data, dcp_time, data.metadata);
1544 }
1545
1546
1547 void
1548 Player::signal_change(ChangeType type, int property)
1549 {
1550         Change(type, property, false);
1551 }
1552