2 Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "ffmpeg_decoder.h"
24 #include "ffmpeg_content.h"
25 #include "image_decoder.h"
26 #include "image_content.h"
27 #include "sndfile_decoder.h"
28 #include "sndfile_content.h"
29 #include "subtitle_content.h"
33 #include "image_proxy.h"
35 #include "resampler.h"
38 #include "player_video_frame.h"
40 #define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
49 using boost::shared_ptr;
50 using boost::weak_ptr;
51 using boost::dynamic_pointer_cast;
53 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
58 , _have_valid_pieces (false)
61 , _audio_merger (f->audio_channels(), bind (&Film::time_to_audio_frames, f.get(), _1), bind (&Film::audio_frames_to_time, f.get(), _1))
62 , _last_emit_was_black (false)
64 _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
65 _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
66 _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
67 set_video_container_size (_film->frame_size ());
71 Player::disable_video ()
77 Player::disable_audio ()
85 if (!_have_valid_pieces) {
89 Time earliest_t = TIME_MAX;
90 shared_ptr<Piece> earliest;
96 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
97 if ((*i)->decoder->done ()) {
101 shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> ((*i)->decoder);
102 shared_ptr<AudioDecoder> ad = dynamic_pointer_cast<AudioDecoder> ((*i)->decoder);
105 if ((*i)->video_position < earliest_t) {
106 earliest_t = (*i)->video_position;
112 if (_audio && ad && ad->has_audio ()) {
113 if ((*i)->audio_position < earliest_t) {
114 earliest_t = (*i)->audio_position;
128 if (earliest_t > _video_position) {
131 if (earliest->repeating ()) {
132 earliest->repeat (this);
134 earliest->decoder->pass ();
140 if (earliest_t > _audio_position) {
141 emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
143 earliest->decoder->pass ();
145 if (earliest->decoder->done()) {
146 shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (earliest->content);
148 shared_ptr<Resampler> re = resampler (ac, false);
150 shared_ptr<const AudioBuffers> b = re->flush ();
152 process_audio (earliest, b, ac->audio_length (), true);
161 boost::optional<Time> audio_done_up_to;
162 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
163 if ((*i)->decoder->done ()) {
167 shared_ptr<AudioDecoder> ad = dynamic_pointer_cast<AudioDecoder> ((*i)->decoder);
168 if (ad && ad->has_audio ()) {
169 audio_done_up_to = min (audio_done_up_to.get_value_or (TIME_MAX), (*i)->audio_position);
173 if (audio_done_up_to) {
174 TimedAudioBuffers<Time> tb = _audio_merger.pull (audio_done_up_to.get ());
175 Audio (tb.audio, tb.time);
176 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
183 /** @param extra Amount of extra time to add to the content frame's time (for repeat) */
185 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const ImageProxy> image, Eyes eyes, Part part, bool same, VideoContent::Frame frame, Time extra)
187 /* Keep a note of what came in so that we can repeat it if required */
188 _last_incoming_video.weak_piece = weak_piece;
189 _last_incoming_video.image = image;
190 _last_incoming_video.eyes = eyes;
191 _last_incoming_video.part = part;
192 _last_incoming_video.same = same;
193 _last_incoming_video.frame = frame;
194 _last_incoming_video.extra = extra;
196 shared_ptr<Piece> piece = weak_piece.lock ();
201 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
204 FrameRateConversion frc (content->video_frame_rate(), _film->video_frame_rate());
205 if (frc.skip && (frame % 2) == 1) {
209 Time const relative_time = (frame * frc.factor() * TIME_HZ / _film->video_frame_rate());
210 if (content->trimmed (relative_time)) {
214 Time const time = content->position() + relative_time + extra - content->trim_start ();
215 libdcp::Size const image_size = content->scale().size (content, _video_container_size, _film->frame_size ());
217 shared_ptr<PlayerVideoFrame> pi (
218 new PlayerVideoFrame (
222 _video_container_size,
226 content->colour_conversion()
230 if (_film->with_subtitles ()) {
231 for (list<Subtitle>::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
232 if (i->covers (time)) {
233 /* This may be true for more than one of _subtitles, but the last (latest-starting)
234 one is the one we want to use, so that's ok.
236 Position<int> const container_offset (
237 (_video_container_size.width - image_size.width) / 2,
238 (_video_container_size.height - image_size.width) / 2
241 pi->set_subtitle (i->out_image(), i->out_position() + container_offset);
246 /* Clear out old subtitles */
247 for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ) {
248 list<Subtitle>::iterator j = i;
251 if (i->ends_before (time)) {
252 _subtitles.erase (i);
258 #ifdef DCPOMATIC_DEBUG
259 _last_video = piece->content;
262 Video (pi, same, time);
264 _last_emit_was_black = false;
265 _video_position = piece->video_position = (time + TIME_HZ / _film->video_frame_rate());
267 if (frc.repeat > 1 && !piece->repeating ()) {
268 piece->set_repeat (_last_incoming_video, frc.repeat - 1);
272 /** @param already_resampled true if this data has already been through the chain up to the resampler */
274 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame, bool already_resampled)
276 shared_ptr<Piece> piece = weak_piece.lock ();
281 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
284 if (!already_resampled) {
286 if (content->audio_gain() != 0) {
287 shared_ptr<AudioBuffers> gain (new AudioBuffers (audio));
288 gain->apply_gain (content->audio_gain ());
293 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
294 shared_ptr<Resampler> r = resampler (content, true);
295 pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
301 Time const relative_time = _film->audio_frames_to_time (frame);
303 if (content->trimmed (relative_time)) {
307 Time time = content->position() + (content->audio_delay() * TIME_HZ / 1000) + relative_time - content->trim_start ();
310 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
311 dcp_mapped->make_silent ();
313 AudioMapping map = content->audio_mapping ();
314 for (int i = 0; i < map.content_channels(); ++i) {
315 for (int j = 0; j < _film->audio_channels(); ++j) {
316 if (map.get (i, static_cast<libdcp::Channel> (j)) > 0) {
317 dcp_mapped->accumulate_channel (
320 static_cast<libdcp::Channel> (j),
321 map.get (i, static_cast<libdcp::Channel> (j))
329 /* We must cut off anything that comes before the start of all time */
331 int const frames = - time * _film->audio_frame_rate() / TIME_HZ;
332 if (frames >= audio->frames ()) {
336 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
337 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
343 _audio_merger.push (audio, time);
344 piece->audio_position += _film->audio_frames_to_time (audio->frames ());
350 TimedAudioBuffers<Time> tb = _audio_merger.flush ();
351 if (_audio && tb.audio) {
352 Audio (tb.audio, tb.time);
353 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
356 while (_video && _video_position < _audio_position) {
360 while (_audio && _audio_position < _video_position) {
361 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
366 /** Seek so that the next pass() will yield (approximately) the requested frame.
367 * Pass accurate = true to try harder to get close to the request.
368 * @return true on error
371 Player::seek (Time t, bool accurate)
373 if (!_have_valid_pieces) {
377 if (_pieces.empty ()) {
381 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
382 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
387 /* s is the offset of t from the start position of this content */
388 Time s = t - vc->position ();
389 s = max (static_cast<Time> (0), s);
390 s = min (vc->length_after_trim(), s);
392 /* Hence set the piece positions to the `global' time */
393 (*i)->video_position = (*i)->audio_position = vc->position() + s;
395 /* And seek the decoder */
396 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (
397 vc->time_to_content_video_frames (s + vc->trim_start ()), accurate
400 (*i)->reset_repeat ();
403 _video_position = _audio_position = t;
405 /* XXX: don't seek audio because we don't need to... */
409 Player::setup_pieces ()
411 list<shared_ptr<Piece> > old_pieces = _pieces;
415 ContentList content = _playlist->content ();
416 sort (content.begin(), content.end(), ContentSorter ());
418 for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
420 if (!(*i)->paths_valid ()) {
424 shared_ptr<Piece> piece (new Piece (*i));
426 /* XXX: into content? */
428 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
430 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
432 fd->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, _5, 0));
433 fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2, false));
434 fd->Subtitle.connect (bind (&Player::process_subtitle, this, weak_ptr<Piece> (piece), _1, _2, _3, _4));
436 fd->seek (fc->time_to_content_video_frames (fc->trim_start ()), true);
440 shared_ptr<const ImageContent> ic = dynamic_pointer_cast<const ImageContent> (*i);
442 bool reusing = false;
444 /* See if we can re-use an old ImageDecoder */
445 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
446 shared_ptr<ImageDecoder> imd = dynamic_pointer_cast<ImageDecoder> ((*j)->decoder);
447 if (imd && imd->content() == ic) {
454 shared_ptr<ImageDecoder> id (new ImageDecoder (_film, ic));
455 id->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, _5, 0));
460 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
462 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
463 sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2, false));
468 _pieces.push_back (piece);
471 _have_valid_pieces = true;
475 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
477 shared_ptr<Content> c = w.lock ();
483 property == ContentProperty::POSITION || property == ContentProperty::LENGTH ||
484 property == ContentProperty::TRIM_START || property == ContentProperty::TRIM_END ||
485 property == VideoContentProperty::VIDEO_FRAME_TYPE
488 _have_valid_pieces = false;
492 property == SubtitleContentProperty::SUBTITLE_X_OFFSET ||
493 property == SubtitleContentProperty::SUBTITLE_Y_OFFSET ||
494 property == SubtitleContentProperty::SUBTITLE_SCALE
497 for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
498 i->update (_film, _video_container_size);
504 property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_SCALE ||
505 property == VideoContentProperty::VIDEO_FRAME_RATE
510 } else if (property == ContentProperty::PATH) {
512 _have_valid_pieces = false;
518 Player::playlist_changed ()
520 _have_valid_pieces = false;
525 Player::set_video_container_size (libdcp::Size s)
527 _video_container_size = s;
529 shared_ptr<Image> im (new Image (PIX_FMT_RGB24, _video_container_size, true));
533 new PlayerVideoFrame (
534 shared_ptr<ImageProxy> (new RawImageProxy (im, _film->log ())),
536 _video_container_size,
537 _video_container_size,
538 Scaler::from_id ("bicubic"),
546 shared_ptr<Resampler>
547 Player::resampler (shared_ptr<AudioContent> c, bool create)
549 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
550 if (i != _resamplers.end ()) {
555 return shared_ptr<Resampler> ();
559 "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()
562 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
568 Player::emit_black ()
570 #ifdef DCPOMATIC_DEBUG
571 _last_video.reset ();
574 Video (_black_frame, _last_emit_was_black, _video_position);
575 _video_position += _film->video_frames_to_time (1);
576 _last_emit_was_black = true;
580 Player::emit_silence (OutputAudioFrame most)
586 OutputAudioFrame N = min (most, _film->audio_frame_rate() / 2);
587 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), N));
588 silence->make_silent ();
589 Audio (silence, _audio_position);
590 _audio_position += _film->audio_frames_to_time (N);
594 Player::film_changed (Film::Property p)
596 /* Here we should notice Film properties that affect our output, and
597 alert listeners that our output now would be different to how it was
598 last time we were run.
601 if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER || p == Film::VIDEO_FRAME_RATE) {
607 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
610 /* A null image means that we should stop any current subtitles at `from' */
611 for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
615 _subtitles.push_back (Subtitle (_film, _video_container_size, weak_piece, image, rect, from, to));
619 /** Re-emit the last frame that was emitted, using current settings for crop, ratio, scaler and subtitles.
620 * @return false if this could not be done.
623 Player::repeat_last_video ()
625 if (!_last_incoming_video.image || !_have_valid_pieces) {
630 _last_incoming_video.weak_piece,
631 _last_incoming_video.image,
632 _last_incoming_video.eyes,
633 _last_incoming_video.part,
634 _last_incoming_video.same,
635 _last_incoming_video.frame,
636 _last_incoming_video.extra