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 "still_image_decoder.h"
26 #include "still_image_content.h"
27 #include "moving_image_decoder.h"
28 #include "moving_image_content.h"
29 #include "sndfile_decoder.h"
30 #include "sndfile_content.h"
31 #include "subtitle_content.h"
36 #include "resampler.h"
47 using boost::shared_ptr;
48 using boost::weak_ptr;
49 using boost::dynamic_pointer_cast;
54 Piece (shared_ptr<Content> c)
56 , video_position (c->position ())
57 , audio_position (c->position ())
62 Piece (shared_ptr<Content> c, shared_ptr<Decoder> d)
65 , video_position (c->position ())
66 , audio_position (c->position ())
69 /** Set this piece to repeat a video frame a given number of times */
70 void set_repeat (IncomingVideo video, int num)
79 repeat_video.image.reset ();
84 bool repeating () const
86 return repeat_done != repeat_to_do;
89 void repeat (Player* player)
91 player->process_video (
92 repeat_video.weak_piece,
97 (repeat_done + 1) * (TIME_HZ / player->_film->video_frame_rate ())
103 shared_ptr<Content> content;
104 shared_ptr<Decoder> decoder;
105 /** Time of the last video we emitted relative to the start of the DCP */
107 /** Time of the last audio we emitted relative to the start of the DCP */
110 IncomingVideo repeat_video;
115 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
120 , _have_valid_pieces (false)
121 , _video_position (0)
122 , _audio_position (0)
123 , _audio_merger (f->audio_channels(), bind (&Film::time_to_audio_frames, f.get(), _1), bind (&Film::audio_frames_to_time, f.get(), _1))
124 , _last_emit_was_black (false)
126 _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
127 _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
128 _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
129 set_video_container_size (fit_ratio_within (_film->container()->ratio (), _film->full_frame ()));
133 Player::disable_video ()
139 Player::disable_audio ()
147 if (!_have_valid_pieces) {
149 _have_valid_pieces = true;
152 Time earliest_t = TIME_MAX;
153 shared_ptr<Piece> earliest;
159 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
160 if ((*i)->decoder->done ()) {
164 shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> ((*i)->decoder);
165 shared_ptr<AudioDecoder> ad = dynamic_pointer_cast<AudioDecoder> ((*i)->decoder);
168 if ((*i)->video_position < earliest_t) {
169 earliest_t = (*i)->video_position;
175 if (_audio && ad && ad->has_audio ()) {
176 if ((*i)->audio_position < earliest_t) {
177 earliest_t = (*i)->audio_position;
191 if (earliest_t > _video_position) {
194 if (earliest->repeating ()) {
195 earliest->repeat (this);
197 earliest->decoder->pass ();
203 if (earliest_t > _audio_position) {
204 emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
206 earliest->decoder->pass ();
208 if (earliest->decoder->done()) {
209 shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (earliest->content);
211 shared_ptr<Resampler> re = resampler (ac, false);
213 shared_ptr<const AudioBuffers> b = re->flush ();
215 process_audio (earliest, b, ac->audio_length ());
224 Time audio_done_up_to = TIME_MAX;
225 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
226 if ((*i)->decoder->done ()) {
230 if (dynamic_pointer_cast<AudioDecoder> ((*i)->decoder)) {
231 audio_done_up_to = min (audio_done_up_to, (*i)->audio_position);
235 TimedAudioBuffers<Time> tb = _audio_merger.pull (audio_done_up_to);
236 Audio (tb.audio, tb.time);
237 _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 StillImageContent> ic = dynamic_pointer_cast<const StillImageContent> (*i);
469 shared_ptr<StillImageDecoder> id;
471 /* See if we can re-use an old StillImageDecoder */
472 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
473 shared_ptr<StillImageDecoder> imd = dynamic_pointer_cast<StillImageDecoder> ((*j)->decoder);
474 if (imd && imd->content() == ic) {
480 id.reset (new StillImageDecoder (_film, ic));
481 id->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, 0));
487 shared_ptr<const MovingImageContent> mc = dynamic_pointer_cast<const MovingImageContent> (*i);
489 shared_ptr<MovingImageDecoder> md;
492 md.reset (new MovingImageDecoder (_film, mc));
493 md->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, 0));
499 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
501 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
502 sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
507 _pieces.push_back (piece);
512 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
514 shared_ptr<Content> c = w.lock ();
520 property == ContentProperty::POSITION || property == ContentProperty::LENGTH ||
521 property == ContentProperty::TRIM_START || property == ContentProperty::TRIM_END
524 _have_valid_pieces = false;
527 } else if (property == SubtitleContentProperty::SUBTITLE_OFFSET || property == SubtitleContentProperty::SUBTITLE_SCALE) {
533 property == VideoContentProperty::VIDEO_FRAME_TYPE || property == VideoContentProperty::VIDEO_CROP ||
534 property == VideoContentProperty::VIDEO_RATIO
539 } else if (property == ContentProperty::PATH) {
546 Player::playlist_changed ()
548 _have_valid_pieces = false;
553 Player::set_video_container_size (libdcp::Size s)
555 _video_container_size = s;
556 _black_frame.reset (new Image (PIX_FMT_RGB24, _video_container_size, true));
557 _black_frame->make_black ();
560 shared_ptr<Resampler>
561 Player::resampler (shared_ptr<AudioContent> c, bool create)
563 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
564 if (i != _resamplers.end ()) {
569 return shared_ptr<Resampler> ();
574 "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()
578 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
584 Player::emit_black ()
586 #ifdef DCPOMATIC_DEBUG
587 _last_video.reset ();
590 Video (_black_frame, EYES_BOTH, ColourConversion(), _last_emit_was_black, _video_position);
591 _video_position += _film->video_frames_to_time (1);
592 _last_emit_was_black = true;
596 Player::emit_silence (OutputAudioFrame most)
602 OutputAudioFrame N = min (most, _film->audio_frame_rate() / 2);
603 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), N));
604 silence->make_silent ();
605 Audio (silence, _audio_position);
606 _audio_position += _film->audio_frames_to_time (N);
610 Player::film_changed (Film::Property p)
612 /* Here we should notice Film properties that affect our output, and
613 alert listeners that our output now would be different to how it was
614 last time we were run.
617 if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER) {
623 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
625 _in_subtitle.piece = weak_piece;
626 _in_subtitle.image = image;
627 _in_subtitle.rect = rect;
628 _in_subtitle.from = from;
629 _in_subtitle.to = to;
635 Player::update_subtitle ()
637 shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
642 if (!_in_subtitle.image) {
643 _out_subtitle.image.reset ();
647 shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
650 dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
651 libdcp::Size scaled_size;
653 in_rect.y += sc->subtitle_offset ();
655 /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
656 scaled_size.width = in_rect.width * _video_container_size.width * sc->subtitle_scale ();
657 scaled_size.height = in_rect.height * _video_container_size.height * sc->subtitle_scale ();
659 /* Then we need a corrective translation, consisting of two parts:
661 * 1. that which is the result of the scaling of the subtitle by _video_container_size; this will be
662 * rect.x * _video_container_size.width and rect.y * _video_container_size.height.
664 * 2. that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
665 * (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
666 * (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
668 * Combining these two translations gives these expressions.
671 _out_subtitle.position.x = rint (_video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
672 _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
674 _out_subtitle.image = _in_subtitle.image->scale (
676 Scaler::from_id ("bicubic"),
677 _in_subtitle.image->pixel_format (),
680 _out_subtitle.from = _in_subtitle.from + piece->content->position ();
681 _out_subtitle.to = _in_subtitle.to + piece->content->position ();
684 /** Re-emit the last frame that was emitted, using current settings for crop, ratio, scaler and subtitles.
685 * @return false if this could not be done.
688 Player::repeat_last_video ()
690 if (!_last_incoming_video.image) {
695 _last_incoming_video.weak_piece,
696 _last_incoming_video.image,
697 _last_incoming_video.eyes,
698 _last_incoming_video.same,
699 _last_incoming_video.frame,
700 _last_incoming_video.extra