2 Copyright (C) 2013 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"
34 #include "resampler.h"
45 using boost::shared_ptr;
46 using boost::weak_ptr;
47 using boost::dynamic_pointer_cast;
52 Piece (shared_ptr<Content> c)
54 , video_position (c->position ())
55 , audio_position (c->position ())
60 Piece (shared_ptr<Content> c, shared_ptr<Decoder> d)
63 , video_position (c->position ())
64 , audio_position (c->position ())
67 /** Set this piece to repeat a video frame a given number of times */
68 void set_repeat (IncomingVideo video, int num)
77 repeat_video.image.reset ();
82 bool repeating () const
84 return repeat_done != repeat_to_do;
87 void repeat (Player* player)
89 player->process_video (
90 repeat_video.weak_piece,
95 (repeat_done + 1) * (TIME_HZ / player->_film->video_frame_rate ())
101 shared_ptr<Content> content;
102 shared_ptr<Decoder> decoder;
103 /** Time of the last video we emitted relative to the start of the DCP */
105 /** Time of the last audio we emitted relative to the start of the DCP */
108 IncomingVideo repeat_video;
113 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
118 , _have_valid_pieces (false)
119 , _video_position (0)
120 , _audio_position (0)
121 , _audio_merger (f->audio_channels(), bind (&Film::time_to_audio_frames, f.get(), _1), bind (&Film::audio_frames_to_time, f.get(), _1))
122 , _last_emit_was_black (false)
124 _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
125 _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
126 _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
127 set_video_container_size (fit_ratio_within (_film->container()->ratio (), _film->full_frame ()));
131 Player::disable_video ()
137 Player::disable_audio ()
145 if (!_have_valid_pieces) {
147 _have_valid_pieces = true;
150 Time earliest_t = TIME_MAX;
151 shared_ptr<Piece> earliest;
157 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
158 if ((*i)->decoder->done ()) {
162 shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> ((*i)->decoder);
163 shared_ptr<AudioDecoder> ad = dynamic_pointer_cast<AudioDecoder> ((*i)->decoder);
166 if ((*i)->video_position < earliest_t) {
167 earliest_t = (*i)->video_position;
173 if (_audio && ad && ad->has_audio ()) {
174 if ((*i)->audio_position < earliest_t) {
175 earliest_t = (*i)->audio_position;
189 if (earliest_t > _video_position) {
192 if (earliest->repeating ()) {
193 earliest->repeat (this);
195 earliest->decoder->pass ();
201 if (earliest_t > _audio_position) {
202 emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
204 earliest->decoder->pass ();
206 if (earliest->decoder->done()) {
207 shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (earliest->content);
209 shared_ptr<Resampler> re = resampler (ac, false);
211 shared_ptr<const AudioBuffers> b = re->flush ();
213 process_audio (earliest, b, ac->audio_length ());
222 boost::optional<Time> audio_done_up_to;
223 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
224 if ((*i)->decoder->done ()) {
228 if (dynamic_pointer_cast<AudioDecoder> ((*i)->decoder)) {
229 audio_done_up_to = min (audio_done_up_to.get_value_or (TIME_MAX), (*i)->audio_position);
233 if (audio_done_up_to) {
234 TimedAudioBuffers<Time> tb = _audio_merger.pull (audio_done_up_to.get ());
235 Audio (tb.audio, tb.time);
236 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
243 /** @param extra Amount of extra time to add to the content frame's time (for repeat) */
245 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, Eyes eyes, bool same, VideoContent::Frame frame, Time extra)
247 /* Keep a note of what came in so that we can repeat it if required */
248 _last_incoming_video.weak_piece = weak_piece;
249 _last_incoming_video.image = image;
250 _last_incoming_video.eyes = eyes;
251 _last_incoming_video.same = same;
252 _last_incoming_video.frame = frame;
253 _last_incoming_video.extra = extra;
255 shared_ptr<Piece> piece = weak_piece.lock ();
260 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
263 FrameRateConversion frc (content->video_frame_rate(), _film->video_frame_rate());
264 if (frc.skip && (frame % 2) == 1) {
268 Time const relative_time = (frame * frc.factor() * TIME_HZ / _film->video_frame_rate());
269 if (content->trimmed (relative_time)) {
273 /* Convert to RGB first, as FFmpeg doesn't seem to like handling YUV images with odd widths */
274 shared_ptr<Image> work_image = image->scale (image->size (), _film->scaler(), PIX_FMT_RGB24, true);
276 work_image = work_image->crop (content->crop(), true);
278 float const ratio = content->ratio() ? content->ratio()->ratio() : content->video_size_after_crop().ratio();
279 libdcp::Size image_size = fit_ratio_within (ratio, _video_container_size);
281 work_image = work_image->scale (image_size, _film->scaler(), PIX_FMT_RGB24, true);
283 Time time = content->position() + relative_time + extra - content->trim_start ();
285 if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) {
286 work_image->alpha_blend (_out_subtitle.image, _out_subtitle.position);
289 if (image_size != _video_container_size) {
290 assert (image_size.width <= _video_container_size.width);
291 assert (image_size.height <= _video_container_size.height);
292 shared_ptr<Image> im (new Image (PIX_FMT_RGB24, _video_container_size, true));
294 im->copy (work_image, Position<int> ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
298 #ifdef DCPOMATIC_DEBUG
299 _last_video = piece->content;
302 Video (work_image, eyes, content->colour_conversion(), same, time);
304 time += TIME_HZ / _film->video_frame_rate();
305 _last_emit_was_black = false;
306 _video_position = piece->video_position = time;
308 if (frc.repeat > 1 && !piece->repeating ()) {
309 piece->set_repeat (_last_incoming_video, frc.repeat - 1);
314 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
316 shared_ptr<Piece> piece = weak_piece.lock ();
321 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
325 if (content->audio_gain() != 0) {
326 shared_ptr<AudioBuffers> gain (new AudioBuffers (audio));
327 gain->apply_gain (content->audio_gain ());
332 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
333 shared_ptr<Resampler> r = resampler (content, true);
334 pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
339 Time const relative_time = _film->audio_frames_to_time (frame);
341 if (content->trimmed (relative_time)) {
345 Time time = content->position() + (content->audio_delay() * TIME_HZ / 1000) + relative_time - content->trim_start ();
348 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
349 dcp_mapped->make_silent ();
350 list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
351 for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
352 if (i->first < audio->channels() && i->second < dcp_mapped->channels()) {
353 dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
359 /* We must cut off anything that comes before the start of all time */
361 int const frames = - time * _film->audio_frame_rate() / TIME_HZ;
362 if (frames >= audio->frames ()) {
366 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
367 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
373 _audio_merger.push (audio, time);
374 piece->audio_position += _film->audio_frames_to_time (audio->frames ());
380 TimedAudioBuffers<Time> tb = _audio_merger.flush ();
382 Audio (tb.audio, tb.time);
383 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
386 while (_video_position < _audio_position) {
390 while (_audio_position < _video_position) {
391 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
396 /** Seek so that the next pass() will yield (approximately) the requested frame.
397 * Pass accurate = true to try harder to get close to the request.
398 * @return true on error
401 Player::seek (Time t, bool accurate)
403 if (!_have_valid_pieces) {
405 _have_valid_pieces = true;
408 if (_pieces.empty ()) {
412 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
413 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
418 /* s is the offset of t from the start position of this content */
419 Time s = t - vc->position ();
420 s = max (static_cast<Time> (0), s);
421 s = min (vc->length_after_trim(), s);
423 /* Hence set the piece positions to the `global' time */
424 (*i)->video_position = (*i)->audio_position = vc->position() + s;
426 /* And seek the decoder */
427 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (
428 vc->time_to_content_video_frames (s + vc->trim_start ()), accurate
431 (*i)->reset_repeat ();
434 _video_position = _audio_position = t;
436 /* XXX: don't seek audio because we don't need to... */
440 Player::setup_pieces ()
442 list<shared_ptr<Piece> > old_pieces = _pieces;
446 ContentList content = _playlist->content ();
447 sort (content.begin(), content.end(), ContentSorter ());
449 for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
451 shared_ptr<Piece> piece (new Piece (*i));
453 /* XXX: into content? */
455 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
457 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
459 fd->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, 0));
460 fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
461 fd->Subtitle.connect (bind (&Player::process_subtitle, this, weak_ptr<Piece> (piece), _1, _2, _3, _4));
463 fd->seek (fc->time_to_content_video_frames (fc->trim_start ()), true);
467 shared_ptr<const ImageContent> ic = dynamic_pointer_cast<const ImageContent> (*i);
469 bool reusing = false;
471 /* See if we can re-use an old ImageDecoder */
472 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
473 shared_ptr<ImageDecoder> imd = dynamic_pointer_cast<ImageDecoder> ((*j)->decoder);
474 if (imd && imd->content() == ic) {
481 shared_ptr<ImageDecoder> id (new ImageDecoder (_film, ic));
482 id->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, 0));
487 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
489 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
490 sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
495 _pieces.push_back (piece);
500 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
502 shared_ptr<Content> c = w.lock ();
508 property == ContentProperty::POSITION || property == ContentProperty::LENGTH ||
509 property == ContentProperty::TRIM_START || property == ContentProperty::TRIM_END
512 _have_valid_pieces = false;
515 } else if (property == SubtitleContentProperty::SUBTITLE_OFFSET || property == SubtitleContentProperty::SUBTITLE_SCALE) {
521 property == VideoContentProperty::VIDEO_FRAME_TYPE || property == VideoContentProperty::VIDEO_CROP ||
522 property == VideoContentProperty::VIDEO_RATIO
527 } else if (property == ContentProperty::PATH) {
534 Player::playlist_changed ()
536 _have_valid_pieces = false;
541 Player::set_video_container_size (libdcp::Size s)
543 _video_container_size = s;
544 _black_frame.reset (new Image (PIX_FMT_RGB24, _video_container_size, true));
545 _black_frame->make_black ();
548 shared_ptr<Resampler>
549 Player::resampler (shared_ptr<AudioContent> c, bool create)
551 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
552 if (i != _resamplers.end ()) {
557 return shared_ptr<Resampler> ();
562 "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()
566 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
572 Player::emit_black ()
574 #ifdef DCPOMATIC_DEBUG
575 _last_video.reset ();
578 Video (_black_frame, EYES_BOTH, ColourConversion(), _last_emit_was_black, _video_position);
579 _video_position += _film->video_frames_to_time (1);
580 _last_emit_was_black = true;
584 Player::emit_silence (OutputAudioFrame most)
590 OutputAudioFrame N = min (most, _film->audio_frame_rate() / 2);
591 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), N));
592 silence->make_silent ();
593 Audio (silence, _audio_position);
594 _audio_position += _film->audio_frames_to_time (N);
598 Player::film_changed (Film::Property p)
600 /* Here we should notice Film properties that affect our output, and
601 alert listeners that our output now would be different to how it was
602 last time we were run.
605 if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER) {
611 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
613 _in_subtitle.piece = weak_piece;
614 _in_subtitle.image = image;
615 _in_subtitle.rect = rect;
616 _in_subtitle.from = from;
617 _in_subtitle.to = to;
623 Player::update_subtitle ()
625 shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
630 if (!_in_subtitle.image) {
631 _out_subtitle.image.reset ();
635 shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
638 dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
639 libdcp::Size scaled_size;
641 in_rect.y += sc->subtitle_offset ();
643 /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
644 scaled_size.width = in_rect.width * _video_container_size.width * sc->subtitle_scale ();
645 scaled_size.height = in_rect.height * _video_container_size.height * sc->subtitle_scale ();
647 /* Then we need a corrective translation, consisting of two parts:
649 * 1. that which is the result of the scaling of the subtitle by _video_container_size; this will be
650 * rect.x * _video_container_size.width and rect.y * _video_container_size.height.
652 * 2. that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
653 * (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
654 * (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
656 * Combining these two translations gives these expressions.
659 _out_subtitle.position.x = rint (_video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
660 _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
662 _out_subtitle.image = _in_subtitle.image->scale (
664 Scaler::from_id ("bicubic"),
665 _in_subtitle.image->pixel_format (),
668 _out_subtitle.from = _in_subtitle.from + piece->content->position ();
669 _out_subtitle.to = _in_subtitle.to + piece->content->position ();
672 /** Re-emit the last frame that was emitted, using current settings for crop, ratio, scaler and subtitles.
673 * @return false if this could not be done.
676 Player::repeat_last_video ()
678 if (!_last_incoming_video.image) {
683 _last_incoming_video.weak_piece,
684 _last_incoming_video.image,
685 _last_incoming_video.eyes,
686 _last_incoming_video.same,
687 _last_incoming_video.frame,
688 _last_incoming_video.extra