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 boost::optional<Time> audio_done_up_to;
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.get_value_or (TIME_MAX), (*i)->audio_position);
235 if (audio_done_up_to) {
236 TimedAudioBuffers<Time> tb = _audio_merger.pull (audio_done_up_to.get ());
237 Audio (tb.audio, tb.time);
238 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
245 /** @param extra Amount of extra time to add to the content frame's time (for repeat) */
247 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, Eyes eyes, bool same, VideoContent::Frame frame, Time extra)
249 /* Keep a note of what came in so that we can repeat it if required */
250 _last_incoming_video.weak_piece = weak_piece;
251 _last_incoming_video.image = image;
252 _last_incoming_video.eyes = eyes;
253 _last_incoming_video.same = same;
254 _last_incoming_video.frame = frame;
255 _last_incoming_video.extra = extra;
257 shared_ptr<Piece> piece = weak_piece.lock ();
262 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
265 FrameRateConversion frc (content->video_frame_rate(), _film->video_frame_rate());
266 if (frc.skip && (frame % 2) == 1) {
270 Time const relative_time = (frame * frc.factor() * TIME_HZ / _film->video_frame_rate());
271 if (content->trimmed (relative_time)) {
275 /* Convert to RGB first, as FFmpeg doesn't seem to like handling YUV images with odd widths */
276 shared_ptr<Image> work_image = image->scale (image->size (), _film->scaler(), PIX_FMT_RGB24, true);
278 work_image = work_image->crop (content->crop(), true);
280 float const ratio = content->ratio() ? content->ratio()->ratio() : content->video_size_after_crop().ratio();
281 libdcp::Size image_size = fit_ratio_within (ratio, _video_container_size);
283 work_image = work_image->scale (image_size, _film->scaler(), PIX_FMT_RGB24, true);
285 Time time = content->position() + relative_time + extra - content->trim_start ();
287 if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) {
288 work_image->alpha_blend (_out_subtitle.image, _out_subtitle.position);
291 if (image_size != _video_container_size) {
292 assert (image_size.width <= _video_container_size.width);
293 assert (image_size.height <= _video_container_size.height);
294 shared_ptr<Image> im (new Image (PIX_FMT_RGB24, _video_container_size, true));
296 im->copy (work_image, Position<int> ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
300 #ifdef DCPOMATIC_DEBUG
301 _last_video = piece->content;
304 Video (work_image, eyes, content->colour_conversion(), same, time);
306 time += TIME_HZ / _film->video_frame_rate();
307 _last_emit_was_black = false;
308 _video_position = piece->video_position = time;
310 if (frc.repeat > 1 && !piece->repeating ()) {
311 piece->set_repeat (_last_incoming_video, frc.repeat - 1);
316 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
318 shared_ptr<Piece> piece = weak_piece.lock ();
323 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
327 if (content->audio_gain() != 0) {
328 shared_ptr<AudioBuffers> gain (new AudioBuffers (audio));
329 gain->apply_gain (content->audio_gain ());
334 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
335 shared_ptr<Resampler> r = resampler (content, true);
336 pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
341 Time const relative_time = _film->audio_frames_to_time (frame);
343 if (content->trimmed (relative_time)) {
347 Time time = content->position() + (content->audio_delay() * TIME_HZ / 1000) + relative_time - content->trim_start ();
350 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
351 dcp_mapped->make_silent ();
352 list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
353 for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
354 if (i->first < audio->channels() && i->second < dcp_mapped->channels()) {
355 dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
361 /* We must cut off anything that comes before the start of all time */
363 int const frames = - time * _film->audio_frame_rate() / TIME_HZ;
364 if (frames >= audio->frames ()) {
368 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
369 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
375 _audio_merger.push (audio, time);
376 piece->audio_position += _film->audio_frames_to_time (audio->frames ());
382 TimedAudioBuffers<Time> tb = _audio_merger.flush ();
384 Audio (tb.audio, tb.time);
385 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
388 while (_video_position < _audio_position) {
392 while (_audio_position < _video_position) {
393 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
398 /** Seek so that the next pass() will yield (approximately) the requested frame.
399 * Pass accurate = true to try harder to get close to the request.
400 * @return true on error
403 Player::seek (Time t, bool accurate)
405 if (!_have_valid_pieces) {
407 _have_valid_pieces = true;
410 if (_pieces.empty ()) {
414 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
415 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
420 /* s is the offset of t from the start position of this content */
421 Time s = t - vc->position ();
422 s = max (static_cast<Time> (0), s);
423 s = min (vc->length_after_trim(), s);
425 /* Hence set the piece positions to the `global' time */
426 (*i)->video_position = (*i)->audio_position = vc->position() + s;
428 /* And seek the decoder */
429 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (
430 vc->time_to_content_video_frames (s + vc->trim_start ()), accurate
433 (*i)->reset_repeat ();
436 _video_position = _audio_position = t;
438 /* XXX: don't seek audio because we don't need to... */
442 Player::setup_pieces ()
444 list<shared_ptr<Piece> > old_pieces = _pieces;
448 ContentList content = _playlist->content ();
449 sort (content.begin(), content.end(), ContentSorter ());
451 for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
453 shared_ptr<Piece> piece (new Piece (*i));
455 /* XXX: into content? */
457 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
459 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
461 fd->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, 0));
462 fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
463 fd->Subtitle.connect (bind (&Player::process_subtitle, this, weak_ptr<Piece> (piece), _1, _2, _3, _4));
465 fd->seek (fc->time_to_content_video_frames (fc->trim_start ()), true);
469 shared_ptr<const StillImageContent> ic = dynamic_pointer_cast<const StillImageContent> (*i);
471 shared_ptr<StillImageDecoder> id;
473 /* See if we can re-use an old StillImageDecoder */
474 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
475 shared_ptr<StillImageDecoder> imd = dynamic_pointer_cast<StillImageDecoder> ((*j)->decoder);
476 if (imd && imd->content() == ic) {
482 id.reset (new StillImageDecoder (_film, ic));
483 id->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, 0));
489 shared_ptr<const MovingImageContent> mc = dynamic_pointer_cast<const MovingImageContent> (*i);
491 shared_ptr<MovingImageDecoder> md;
494 md.reset (new MovingImageDecoder (_film, mc));
495 md->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, 0));
501 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
503 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
504 sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
509 _pieces.push_back (piece);
514 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
516 shared_ptr<Content> c = w.lock ();
522 property == ContentProperty::POSITION || property == ContentProperty::LENGTH ||
523 property == ContentProperty::TRIM_START || property == ContentProperty::TRIM_END
526 _have_valid_pieces = false;
529 } else if (property == SubtitleContentProperty::SUBTITLE_OFFSET || property == SubtitleContentProperty::SUBTITLE_SCALE) {
535 property == VideoContentProperty::VIDEO_FRAME_TYPE || property == VideoContentProperty::VIDEO_CROP ||
536 property == VideoContentProperty::VIDEO_RATIO
541 } else if (property == ContentProperty::PATH) {
548 Player::playlist_changed ()
550 _have_valid_pieces = false;
555 Player::set_video_container_size (libdcp::Size s)
557 _video_container_size = s;
558 _black_frame.reset (new Image (PIX_FMT_RGB24, _video_container_size, true));
559 _black_frame->make_black ();
562 shared_ptr<Resampler>
563 Player::resampler (shared_ptr<AudioContent> c, bool create)
565 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
566 if (i != _resamplers.end ()) {
571 return shared_ptr<Resampler> ();
576 "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()
580 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
586 Player::emit_black ()
588 #ifdef DCPOMATIC_DEBUG
589 _last_video.reset ();
592 Video (_black_frame, EYES_BOTH, ColourConversion(), _last_emit_was_black, _video_position);
593 _video_position += _film->video_frames_to_time (1);
594 _last_emit_was_black = true;
598 Player::emit_silence (OutputAudioFrame most)
604 OutputAudioFrame N = min (most, _film->audio_frame_rate() / 2);
605 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), N));
606 silence->make_silent ();
607 Audio (silence, _audio_position);
608 _audio_position += _film->audio_frames_to_time (N);
612 Player::film_changed (Film::Property p)
614 /* Here we should notice Film properties that affect our output, and
615 alert listeners that our output now would be different to how it was
616 last time we were run.
619 if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER) {
625 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
627 _in_subtitle.piece = weak_piece;
628 _in_subtitle.image = image;
629 _in_subtitle.rect = rect;
630 _in_subtitle.from = from;
631 _in_subtitle.to = to;
637 Player::update_subtitle ()
639 shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
644 if (!_in_subtitle.image) {
645 _out_subtitle.image.reset ();
649 shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
652 dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
653 libdcp::Size scaled_size;
655 in_rect.y += sc->subtitle_offset ();
657 /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
658 scaled_size.width = in_rect.width * _video_container_size.width * sc->subtitle_scale ();
659 scaled_size.height = in_rect.height * _video_container_size.height * sc->subtitle_scale ();
661 /* Then we need a corrective translation, consisting of two parts:
663 * 1. that which is the result of the scaling of the subtitle by _video_container_size; this will be
664 * rect.x * _video_container_size.width and rect.y * _video_container_size.height.
666 * 2. that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
667 * (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
668 * (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
670 * Combining these two translations gives these expressions.
673 _out_subtitle.position.x = rint (_video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
674 _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
676 _out_subtitle.image = _in_subtitle.image->scale (
678 Scaler::from_id ("bicubic"),
679 _in_subtitle.image->pixel_format (),
682 _out_subtitle.from = _in_subtitle.from + piece->content->position ();
683 _out_subtitle.to = _in_subtitle.to + piece->content->position ();
686 /** Re-emit the last frame that was emitted, using current settings for crop, ratio, scaler and subtitles.
687 * @return false if this could not be done.
690 Player::repeat_last_video ()
692 if (!_last_incoming_video.image) {
697 _last_incoming_video.weak_piece,
698 _last_incoming_video.image,
699 _last_incoming_video.eyes,
700 _last_incoming_video.same,
701 _last_incoming_video.frame,
702 _last_incoming_video.extra