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