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"
39 #include "frame_rate_change.h"
41 #define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
50 using boost::shared_ptr;
51 using boost::weak_ptr;
52 using boost::dynamic_pointer_cast;
54 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
59 , _have_valid_pieces (false)
62 , _audio_merger (f->audio_channels(), bind (&Film::time_to_audio_frames, f.get(), _1), bind (&Film::audio_frames_to_time, f.get(), _1))
63 , _last_emit_was_black (false)
65 _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
66 _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
67 _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
68 set_video_container_size (_film->frame_size ());
72 Player::disable_video ()
78 Player::disable_audio ()
86 if (!_have_valid_pieces) {
90 Time earliest_t = TIME_MAX;
91 shared_ptr<Piece> earliest;
97 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
98 if ((*i)->decoder->done () || (*i)->content->length_after_trim() == 0) {
102 shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> ((*i)->decoder);
103 shared_ptr<AudioDecoder> ad = dynamic_pointer_cast<AudioDecoder> ((*i)->decoder);
106 if ((*i)->video_position < earliest_t) {
107 earliest_t = (*i)->video_position;
113 if (_audio && ad && ad->has_audio ()) {
114 if ((*i)->audio_position < earliest_t) {
115 earliest_t = (*i)->audio_position;
129 if (earliest_t > _video_position) {
132 if (earliest->repeating ()) {
133 earliest->repeat (this);
135 earliest->decoder->pass ();
141 if (earliest_t > _audio_position) {
142 emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
144 earliest->decoder->pass ();
146 if (earliest->decoder->done()) {
147 shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (earliest->content);
149 shared_ptr<Resampler> re = resampler (ac, false);
151 shared_ptr<const AudioBuffers> b = re->flush ();
156 ac->audio_length() * ac->output_audio_frame_rate() / ac->content_audio_frame_rate(),
167 boost::optional<Time> audio_done_up_to;
168 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
169 if ((*i)->decoder->done ()) {
173 shared_ptr<AudioDecoder> ad = dynamic_pointer_cast<AudioDecoder> ((*i)->decoder);
174 if (ad && ad->has_audio ()) {
175 audio_done_up_to = min (audio_done_up_to.get_value_or (TIME_MAX), (*i)->audio_position);
179 if (audio_done_up_to) {
180 TimedAudioBuffers<Time> tb = _audio_merger.pull (audio_done_up_to.get ());
181 Audio (tb.audio, tb.time);
182 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
189 /** @param extra Amount of extra time to add to the content frame's time (for repeat) */
191 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const ImageProxy> image, Eyes eyes, Part part, bool same, VideoContent::Frame frame, Time extra)
193 /* Keep a note of what came in so that we can repeat it if required */
194 _last_incoming_video.weak_piece = weak_piece;
195 _last_incoming_video.image = image;
196 _last_incoming_video.eyes = eyes;
197 _last_incoming_video.part = part;
198 _last_incoming_video.same = same;
199 _last_incoming_video.frame = frame;
200 _last_incoming_video.extra = extra;
202 shared_ptr<Piece> piece = weak_piece.lock ();
207 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
210 FrameRateChange frc (content->video_frame_rate(), _film->video_frame_rate());
211 if (frc.skip && (frame % 2) == 1) {
215 Time const relative_time = (frame * frc.factor() * TIME_HZ / _film->video_frame_rate());
216 if (content->trimmed (relative_time)) {
220 Time const time = content->position() + relative_time + extra - content->trim_start ();
221 libdcp::Size const image_size = content->scale().size (content, _video_container_size, _film->frame_size ());
223 shared_ptr<PlayerVideoFrame> pi (
224 new PlayerVideoFrame (
228 _video_container_size,
232 content->colour_conversion()
236 if (_film->with_subtitles ()) {
237 for (list<Subtitle>::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
238 if (i->covers (time)) {
239 /* This may be true for more than one of _subtitles, but the last (latest-starting)
240 one is the one we want to use, so that's ok.
242 Position<int> const container_offset (
243 (_video_container_size.width - image_size.width) / 2,
244 (_video_container_size.height - image_size.width) / 2
247 pi->set_subtitle (i->out_image(), i->out_position() + container_offset);
252 /* Clear out old subtitles */
253 for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ) {
254 list<Subtitle>::iterator j = i;
257 if (i->ends_before (time)) {
258 _subtitles.erase (i);
264 #ifdef DCPOMATIC_DEBUG
265 _last_video = piece->content;
268 Video (pi, same, time);
270 _last_emit_was_black = false;
271 _video_position = piece->video_position = (time + TIME_HZ / _film->video_frame_rate());
273 if (frc.repeat > 1 && !piece->repeating ()) {
274 piece->set_repeat (_last_incoming_video, frc.repeat - 1);
278 /** @param already_resampled true if this data has already been through the chain up to the resampler */
280 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame, bool already_resampled)
282 shared_ptr<Piece> piece = weak_piece.lock ();
287 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
290 if (!already_resampled) {
292 if (content->audio_gain() != 0) {
293 shared_ptr<AudioBuffers> gain (new AudioBuffers (audio));
294 gain->apply_gain (content->audio_gain ());
299 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
300 shared_ptr<Resampler> r = resampler (content, true);
301 pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
307 Time const relative_time = _film->audio_frames_to_time (frame);
309 if (content->trimmed (relative_time)) {
313 Time time = content->position() + (content->audio_delay() * TIME_HZ / 1000) + relative_time - content->trim_start ();
316 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
317 dcp_mapped->make_silent ();
319 AudioMapping map = content->audio_mapping ();
320 for (int i = 0; i < map.content_channels(); ++i) {
321 for (int j = 0; j < _film->audio_channels(); ++j) {
322 if (map.get (i, static_cast<libdcp::Channel> (j)) > 0) {
323 dcp_mapped->accumulate_channel (
326 static_cast<libdcp::Channel> (j),
327 map.get (i, static_cast<libdcp::Channel> (j))
335 /* We must cut off anything that comes before the start of all time */
337 int const frames = - time * _film->audio_frame_rate() / TIME_HZ;
338 if (frames >= audio->frames ()) {
342 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
343 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
349 _audio_merger.push (audio, time);
350 piece->audio_position += _film->audio_frames_to_time (audio->frames ());
356 TimedAudioBuffers<Time> tb = _audio_merger.flush ();
357 if (_audio && tb.audio) {
358 Audio (tb.audio, tb.time);
359 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
362 while (_video && _video_position < _audio_position) {
366 while (_audio && _audio_position < _video_position) {
367 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
372 /** Seek so that the next pass() will yield (approximately) the requested frame.
373 * Pass accurate = true to try harder to get close to the request.
374 * @return true on error
377 Player::seek (Time t, bool accurate)
379 if (!_have_valid_pieces) {
383 if (_pieces.empty ()) {
387 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
388 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
393 /* s is the offset of t from the start position of this content */
394 Time s = t - vc->position ();
395 s = max (static_cast<Time> (0), s);
396 s = min (vc->length_after_trim(), s);
398 /* Hence set the piece positions to the `global' time */
399 (*i)->video_position = (*i)->audio_position = vc->position() + s;
401 /* And seek the decoder */
402 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (
403 vc->time_to_content_video_frames (s + vc->trim_start ()), accurate
406 (*i)->reset_repeat ();
409 _video_position = _audio_position = t;
411 /* XXX: don't seek audio because we don't need to... */
415 Player::setup_pieces ()
417 list<shared_ptr<Piece> > old_pieces = _pieces;
421 ContentList content = _playlist->content ();
422 sort (content.begin(), content.end(), ContentSorter ());
424 for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
426 if (!(*i)->paths_valid ()) {
430 shared_ptr<Piece> piece (new Piece (*i));
432 /* XXX: into content? */
434 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
436 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
438 fd->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, _5, 0));
439 fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2, false));
440 fd->Subtitle.connect (bind (&Player::process_subtitle, this, weak_ptr<Piece> (piece), _1, _2, _3, _4));
442 fd->seek (fc->time_to_content_video_frames (fc->trim_start ()), true);
446 shared_ptr<const ImageContent> ic = dynamic_pointer_cast<const ImageContent> (*i);
448 bool reusing = false;
450 /* See if we can re-use an old ImageDecoder */
451 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
452 shared_ptr<ImageDecoder> imd = dynamic_pointer_cast<ImageDecoder> ((*j)->decoder);
453 if (imd && imd->content() == ic) {
460 shared_ptr<ImageDecoder> id (new ImageDecoder (_film, ic));
461 id->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, _5, 0));
466 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
468 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
469 sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2, false));
474 _pieces.push_back (piece);
477 _have_valid_pieces = true;
481 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
483 shared_ptr<Content> c = w.lock ();
489 property == ContentProperty::POSITION || property == ContentProperty::LENGTH ||
490 property == ContentProperty::TRIM_START || property == ContentProperty::TRIM_END ||
491 property == VideoContentProperty::VIDEO_FRAME_TYPE
494 _have_valid_pieces = false;
498 property == SubtitleContentProperty::SUBTITLE_X_OFFSET ||
499 property == SubtitleContentProperty::SUBTITLE_Y_OFFSET ||
500 property == SubtitleContentProperty::SUBTITLE_X_SCALE ||
501 property == SubtitleContentProperty::SUBTITLE_Y_SCALE
504 for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
505 i->update (_film, _video_container_size);
511 property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_SCALE ||
512 property == VideoContentProperty::VIDEO_FRAME_RATE
517 } else if (property == ContentProperty::PATH) {
519 _have_valid_pieces = false;
525 Player::playlist_changed ()
527 _have_valid_pieces = false;
532 Player::set_video_container_size (libdcp::Size s)
534 _video_container_size = s;
536 shared_ptr<Image> im (new Image (PIX_FMT_RGB24, _video_container_size, true));
540 new PlayerVideoFrame (
541 shared_ptr<ImageProxy> (new RawImageProxy (im, _film->log ())),
543 _video_container_size,
544 _video_container_size,
545 Scaler::from_id ("bicubic"),
553 shared_ptr<Resampler>
554 Player::resampler (shared_ptr<AudioContent> c, bool create)
556 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
557 if (i != _resamplers.end ()) {
562 return shared_ptr<Resampler> ();
566 "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()
569 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
575 Player::emit_black ()
577 #ifdef DCPOMATIC_DEBUG
578 _last_video.reset ();
581 Video (_black_frame, _last_emit_was_black, _video_position);
582 _video_position += _film->video_frames_to_time (1);
583 _last_emit_was_black = true;
587 Player::emit_silence (OutputAudioFrame most)
593 OutputAudioFrame N = min (most, _film->audio_frame_rate() / 2);
594 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), N));
595 silence->make_silent ();
596 Audio (silence, _audio_position);
597 _audio_position += _film->audio_frames_to_time (N);
601 Player::film_changed (Film::Property p)
603 /* Here we should notice Film properties that affect our output, and
604 alert listeners that our output now would be different to how it was
605 last time we were run.
608 if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER || p == Film::VIDEO_FRAME_RATE) {
614 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
617 /* A null image means that we should stop any current subtitles at `from' */
618 for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
622 _subtitles.push_back (Subtitle (_film, _video_container_size, weak_piece, image, rect, from, to));
626 /** Re-emit the last frame that was emitted, using current settings for crop, ratio, scaler and subtitles.
627 * @return false if this could not be done.
630 Player::repeat_last_video ()
632 if (!_last_incoming_video.image || !_have_valid_pieces) {
637 _last_incoming_video.weak_piece,
638 _last_incoming_video.image,
639 _last_incoming_video.eyes,
640 _last_incoming_video.part,
641 _last_incoming_video.same,
642 _last_incoming_video.frame,
643 _last_incoming_video.extra