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"
47 using boost::shared_ptr;
48 using boost::weak_ptr;
49 using boost::dynamic_pointer_cast;
51 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
56 , _have_valid_pieces (false)
59 , _audio_merger (f->audio_channels(), bind (&Film::time_to_audio_frames, f.get(), _1), bind (&Film::audio_frames_to_time, f.get(), _1))
60 , _last_emit_was_black (false)
62 _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
63 _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
64 _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
65 set_video_container_size (_film->frame_size ());
69 Player::disable_video ()
75 Player::disable_audio ()
83 if (!_have_valid_pieces) {
87 Time earliest_t = TIME_MAX;
88 shared_ptr<Piece> earliest;
94 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
95 if ((*i)->decoder->done ()) {
99 shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> ((*i)->decoder);
100 shared_ptr<AudioDecoder> ad = dynamic_pointer_cast<AudioDecoder> ((*i)->decoder);
103 if ((*i)->video_position < earliest_t) {
104 earliest_t = (*i)->video_position;
110 if (_audio && ad && ad->has_audio ()) {
111 if ((*i)->audio_position < earliest_t) {
112 earliest_t = (*i)->audio_position;
126 if (earliest_t > _video_position) {
129 if (earliest->repeating ()) {
130 earliest->repeat (this);
132 earliest->decoder->pass ();
138 if (earliest_t > _audio_position) {
139 emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
141 earliest->decoder->pass ();
143 if (earliest->decoder->done()) {
144 shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (earliest->content);
146 shared_ptr<Resampler> re = resampler (ac, false);
148 shared_ptr<const AudioBuffers> b = re->flush ();
150 process_audio (earliest, b, ac->audio_length ());
159 boost::optional<Time> audio_done_up_to;
160 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
161 if ((*i)->decoder->done ()) {
165 shared_ptr<AudioDecoder> ad = dynamic_pointer_cast<AudioDecoder> ((*i)->decoder);
166 if (ad && ad->has_audio ()) {
167 audio_done_up_to = min (audio_done_up_to.get_value_or (TIME_MAX), (*i)->audio_position);
171 if (audio_done_up_to) {
172 TimedAudioBuffers<Time> tb = _audio_merger.pull (audio_done_up_to.get ());
173 Audio (tb.audio, tb.time);
174 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
181 /** @param extra Amount of extra time to add to the content frame's time (for repeat) */
183 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const ImageProxy> image, Eyes eyes, Part part, bool same, VideoContent::Frame frame, Time extra)
185 /* Keep a note of what came in so that we can repeat it if required */
186 _last_incoming_video.weak_piece = weak_piece;
187 _last_incoming_video.image = image;
188 _last_incoming_video.eyes = eyes;
189 _last_incoming_video.part = part;
190 _last_incoming_video.same = same;
191 _last_incoming_video.frame = frame;
192 _last_incoming_video.extra = extra;
194 shared_ptr<Piece> piece = weak_piece.lock ();
199 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
202 FrameRateConversion frc (content->video_frame_rate(), _film->video_frame_rate());
203 if (frc.skip && (frame % 2) == 1) {
207 Time const relative_time = (frame * frc.factor() * TIME_HZ / _film->video_frame_rate());
208 if (content->trimmed (relative_time)) {
212 Time const time = content->position() + relative_time + extra - content->trim_start ();
213 libdcp::Size const image_size = content->scale().size (content, _video_container_size, _film->frame_size ());
215 shared_ptr<PlayerVideoFrame> pi (
216 new PlayerVideoFrame (
220 _video_container_size,
224 content->colour_conversion()
228 if (_film->with_subtitles ()) {
229 for (list<Subtitle>::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
230 if (i->covers (time)) {
231 /* This may be true for more than one of _subtitles, but the last (latest-starting)
232 one is the one we want to use, so that's ok.
234 Position<int> const container_offset (
235 (_video_container_size.width - image_size.width) / 2,
236 (_video_container_size.height - image_size.width) / 2
239 pi->set_subtitle (i->out_image(), i->out_position() + container_offset);
244 /* Clear out old subtitles */
245 for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ) {
246 list<Subtitle>::iterator j = i;
249 if (i->ends_before (time)) {
250 _subtitles.erase (i);
256 #ifdef DCPOMATIC_DEBUG
257 _last_video = piece->content;
260 Video (pi, same, time);
262 _last_emit_was_black = false;
263 _video_position = piece->video_position = (time + TIME_HZ / _film->video_frame_rate());
265 if (frc.repeat > 1 && !piece->repeating ()) {
266 piece->set_repeat (_last_incoming_video, frc.repeat - 1);
271 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
273 shared_ptr<Piece> piece = weak_piece.lock ();
278 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
282 if (content->audio_gain() != 0) {
283 shared_ptr<AudioBuffers> gain (new AudioBuffers (audio));
284 gain->apply_gain (content->audio_gain ());
289 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
290 shared_ptr<Resampler> r = resampler (content, true);
291 pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
296 Time const relative_time = _film->audio_frames_to_time (frame);
298 if (content->trimmed (relative_time)) {
302 Time time = content->position() + (content->audio_delay() * TIME_HZ / 1000) + relative_time - content->trim_start ();
305 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
306 dcp_mapped->make_silent ();
308 AudioMapping map = content->audio_mapping ();
309 for (int i = 0; i < map.content_channels(); ++i) {
310 for (int j = 0; j < _film->audio_channels(); ++j) {
311 if (map.get (i, static_cast<libdcp::Channel> (j)) > 0) {
312 dcp_mapped->accumulate_channel (
315 static_cast<libdcp::Channel> (j),
316 map.get (i, static_cast<libdcp::Channel> (j))
324 /* We must cut off anything that comes before the start of all time */
326 int const frames = - time * _film->audio_frame_rate() / TIME_HZ;
327 if (frames >= audio->frames ()) {
331 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
332 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
338 _audio_merger.push (audio, time);
339 piece->audio_position += _film->audio_frames_to_time (audio->frames ());
345 TimedAudioBuffers<Time> tb = _audio_merger.flush ();
346 if (_audio && tb.audio) {
347 Audio (tb.audio, tb.time);
348 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
351 while (_video && _video_position < _audio_position) {
355 while (_audio && _audio_position < _video_position) {
356 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
361 /** Seek so that the next pass() will yield (approximately) the requested frame.
362 * Pass accurate = true to try harder to get close to the request.
363 * @return true on error
366 Player::seek (Time t, bool accurate)
368 if (!_have_valid_pieces) {
372 if (_pieces.empty ()) {
376 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
377 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
382 /* s is the offset of t from the start position of this content */
383 Time s = t - vc->position ();
384 s = max (static_cast<Time> (0), s);
385 s = min (vc->length_after_trim(), s);
387 /* Hence set the piece positions to the `global' time */
388 (*i)->video_position = (*i)->audio_position = vc->position() + s;
390 /* And seek the decoder */
391 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (
392 vc->time_to_content_video_frames (s + vc->trim_start ()), accurate
395 (*i)->reset_repeat ();
398 _video_position = _audio_position = t;
400 /* XXX: don't seek audio because we don't need to... */
404 Player::setup_pieces ()
406 list<shared_ptr<Piece> > old_pieces = _pieces;
410 ContentList content = _playlist->content ();
411 sort (content.begin(), content.end(), ContentSorter ());
413 for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
415 if (!(*i)->paths_valid ()) {
419 shared_ptr<Piece> piece (new Piece (*i));
421 /* XXX: into content? */
423 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
425 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
427 fd->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, _5, 0));
428 fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
429 fd->Subtitle.connect (bind (&Player::process_subtitle, this, weak_ptr<Piece> (piece), _1, _2, _3, _4));
431 fd->seek (fc->time_to_content_video_frames (fc->trim_start ()), true);
435 shared_ptr<const ImageContent> ic = dynamic_pointer_cast<const ImageContent> (*i);
437 bool reusing = false;
439 /* See if we can re-use an old ImageDecoder */
440 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
441 shared_ptr<ImageDecoder> imd = dynamic_pointer_cast<ImageDecoder> ((*j)->decoder);
442 if (imd && imd->content() == ic) {
449 shared_ptr<ImageDecoder> id (new ImageDecoder (_film, ic));
450 id->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, _5, 0));
455 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
457 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
458 sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
463 _pieces.push_back (piece);
466 _have_valid_pieces = true;
470 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
472 shared_ptr<Content> c = w.lock ();
478 property == ContentProperty::POSITION || property == ContentProperty::LENGTH ||
479 property == ContentProperty::TRIM_START || property == ContentProperty::TRIM_END ||
480 property == VideoContentProperty::VIDEO_FRAME_TYPE
483 _have_valid_pieces = false;
487 property == SubtitleContentProperty::SUBTITLE_X_OFFSET ||
488 property == SubtitleContentProperty::SUBTITLE_Y_OFFSET ||
489 property == SubtitleContentProperty::SUBTITLE_SCALE
492 for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
493 i->update (_film, _video_container_size);
499 property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_SCALE ||
500 property == VideoContentProperty::VIDEO_FRAME_RATE
505 } else if (property == ContentProperty::PATH) {
507 _have_valid_pieces = false;
513 Player::playlist_changed ()
515 _have_valid_pieces = false;
520 Player::set_video_container_size (libdcp::Size s)
522 _video_container_size = s;
524 shared_ptr<Image> im (new Image (PIX_FMT_RGB24, _video_container_size, true));
528 new PlayerVideoFrame (
529 shared_ptr<ImageProxy> (new RawImageProxy (im)),
531 _video_container_size,
532 _video_container_size,
533 Scaler::from_id ("bicubic"),
541 shared_ptr<Resampler>
542 Player::resampler (shared_ptr<AudioContent> c, bool create)
544 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
545 if (i != _resamplers.end ()) {
550 return shared_ptr<Resampler> ();
555 "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()
559 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
565 Player::emit_black ()
567 #ifdef DCPOMATIC_DEBUG
568 _last_video.reset ();
571 Video (_black_frame, _last_emit_was_black, _video_position);
572 _video_position += _film->video_frames_to_time (1);
573 _last_emit_was_black = true;
577 Player::emit_silence (OutputAudioFrame most)
583 OutputAudioFrame N = min (most, _film->audio_frame_rate() / 2);
584 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), N));
585 silence->make_silent ();
586 Audio (silence, _audio_position);
587 _audio_position += _film->audio_frames_to_time (N);
591 Player::film_changed (Film::Property p)
593 /* Here we should notice Film properties that affect our output, and
594 alert listeners that our output now would be different to how it was
595 last time we were run.
598 if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER || p == Film::VIDEO_FRAME_RATE) {
604 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
607 /* A null image means that we should stop any current subtitles at `from' */
608 for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
612 _subtitles.push_back (Subtitle (_film, _video_container_size, weak_piece, image, rect, from, to));
616 /** Re-emit the last frame that was emitted, using current settings for crop, ratio, scaler and subtitles.
617 * @return false if this could not be done.
620 Player::repeat_last_video ()
622 if (!_last_incoming_video.image || !_have_valid_pieces) {
627 _last_incoming_video.weak_piece,
628 _last_incoming_video.image,
629 _last_incoming_video.eyes,
630 _last_incoming_video.part,
631 _last_incoming_video.same,
632 _last_incoming_video.frame,
633 _last_incoming_video.extra