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;
51 //#define DEBUG_PLAYER 1
56 Piece (shared_ptr<Content> c)
58 , video_position (c->position ())
59 , 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 shared_ptr<Content> content;
70 shared_ptr<Decoder> decoder;
76 std::ostream& operator<<(std::ostream& s, Piece const & p)
78 if (dynamic_pointer_cast<FFmpegContent> (p.content)) {
80 } else if (dynamic_pointer_cast<StillImageContent> (p.content)) {
82 } else if (dynamic_pointer_cast<SndfileContent> (p.content)) {
86 s << " at " << p.content->position() << " until " << p.content->end();
92 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
97 , _have_valid_pieces (false)
100 , _audio_merger (f->audio_channels(), bind (&Film::time_to_audio_frames, f.get(), _1), bind (&Film::audio_frames_to_time, f.get(), _1))
101 , _last_emit_was_black (false)
103 _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
104 _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
105 _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
106 set_video_container_size (_film->container()->size (_film->full_frame ()));
110 Player::disable_video ()
116 Player::disable_audio ()
124 if (!_have_valid_pieces) {
126 _have_valid_pieces = true;
133 Time earliest_t = TIME_MAX;
134 shared_ptr<Piece> earliest;
140 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
141 if ((*i)->decoder->done ()) {
145 if (_video && dynamic_pointer_cast<VideoDecoder> ((*i)->decoder)) {
146 if ((*i)->video_position < earliest_t) {
147 earliest_t = (*i)->video_position;
153 if (_audio && dynamic_pointer_cast<AudioDecoder> ((*i)->decoder)) {
154 if ((*i)->audio_position < earliest_t) {
155 earliest_t = (*i)->audio_position;
164 cout << "no earliest piece.\n";
173 if (earliest_t > _video_position) {
175 cout << "no video here; emitting black frame (earliest=" << earliest_t << ", video_position=" << _video_position << ").\n";
180 cout << "Pass video " << *earliest << "\n";
182 earliest->decoder->pass ();
187 if (earliest_t > _audio_position) {
189 cout << "no audio here (none until " << earliest_t << "); emitting silence.\n";
191 emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
194 cout << "Pass audio " << *earliest << "\n";
196 earliest->decoder->pass ();
198 if (earliest->decoder->done()) {
199 shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (earliest->content);
201 shared_ptr<Resampler> re = resampler (ac, false);
203 shared_ptr<const AudioBuffers> b = re->flush ();
205 process_audio (earliest, b, ac->audio_length ());
213 Time audio_done_up_to = TIME_MAX;
214 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
215 if (dynamic_pointer_cast<AudioDecoder> ((*i)->decoder)) {
216 audio_done_up_to = min (audio_done_up_to, (*i)->audio_position);
220 TimedAudioBuffers<Time> tb = _audio_merger.pull (audio_done_up_to);
221 Audio (tb.audio, tb.time);
222 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
225 cout << "\tpost pass _video_position=" << _video_position << " _audio_position=" << _audio_position << "\n";
232 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, Eyes eyes, bool same, VideoContent::Frame frame)
234 shared_ptr<Piece> piece = weak_piece.lock ();
239 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
242 FrameRateConversion frc (content->video_frame_rate(), _film->video_frame_rate());
243 if (frc.skip && (frame % 2) == 1) {
247 Time const relative_time = (frame * frc.factor() * TIME_HZ / _film->video_frame_rate());
248 if (content->trimmed (relative_time)) {
252 shared_ptr<Image> work_image = image->crop (content->crop(), true);
254 libdcp::Size const image_size = content->ratio()->size (_video_container_size);
256 work_image = work_image->scale_and_convert_to_rgb (image_size, _film->scaler(), true);
258 Time time = content->position() + relative_time - content->trim_start ();
260 if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) {
261 work_image->alpha_blend (_out_subtitle.image, _out_subtitle.position);
264 if (image_size != _video_container_size) {
265 assert (image_size.width <= _video_container_size.width);
266 assert (image_size.height <= _video_container_size.height);
267 shared_ptr<Image> im (new Image (PIX_FMT_RGB24, _video_container_size, true));
269 im->copy (work_image, Position<int> ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
273 #ifdef DCPOMATIC_DEBUG
274 _last_video = piece->content;
277 Video (work_image, eyes, same, time);
278 time += TIME_HZ / _film->video_frame_rate();
281 Video (work_image, eyes, true, time);
282 time += TIME_HZ / _film->video_frame_rate();
285 _last_emit_was_black = false;
287 _video_position = piece->video_position = time;
291 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
293 shared_ptr<Piece> piece = weak_piece.lock ();
298 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
302 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
303 shared_ptr<Resampler> r = resampler (content, true);
304 pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
309 Time const relative_time = _film->audio_frames_to_time (frame);
311 if (content->trimmed (relative_time)) {
315 Time time = content->position() + (content->audio_delay() * TIME_HZ / 1000) + relative_time;
318 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
319 dcp_mapped->make_silent ();
320 list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
321 for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
322 if (i->first < audio->channels() && i->second < dcp_mapped->channels()) {
323 dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
329 /* We must cut off anything that comes before the start of all time */
331 int const frames = - time * _film->audio_frame_rate() / TIME_HZ;
332 if (frames >= audio->frames ()) {
336 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
337 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
343 _audio_merger.push (audio, time);
344 piece->audio_position += _film->audio_frames_to_time (audio->frames ());
350 TimedAudioBuffers<Time> tb = _audio_merger.flush ();
352 Audio (tb.audio, tb.time);
353 _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
356 while (_video_position < _audio_position) {
360 while (_audio_position < _video_position) {
361 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
366 /** Seek so that the next pass() will yield (approximately) the requested frame.
367 * Pass accurate = true to try harder to get close to the request.
368 * @return true on error
371 Player::seek (Time t, bool accurate)
373 if (!_have_valid_pieces) {
375 _have_valid_pieces = true;
378 if (_pieces.empty ()) {
382 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
383 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
388 Time s = t - vc->position ();
389 s = max (static_cast<Time> (0), s);
390 s = min (vc->length_after_trim(), s);
392 (*i)->video_position = (*i)->audio_position = vc->position() + s;
394 FrameRateConversion frc (vc->video_frame_rate(), _film->video_frame_rate());
395 /* Here we are converting from time (in the DCP) to a frame number in the content.
396 Hence we need to use the DCP's frame rate and the double/skip correction, not
399 VideoContent::Frame f = (s + vc->trim_start ()) * _film->video_frame_rate() / (frc.factor() * TIME_HZ);
400 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f, accurate);
403 _video_position = _audio_position = t;
405 /* XXX: don't seek audio because we don't need to... */
409 Player::setup_pieces ()
411 list<shared_ptr<Piece> > old_pieces = _pieces;
415 ContentList content = _playlist->content ();
416 sort (content.begin(), content.end(), ContentSorter ());
418 for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
420 shared_ptr<Piece> piece (new Piece (*i));
422 /* XXX: into content? */
424 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
426 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
428 fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
429 fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
430 fd->Subtitle.connect (bind (&Player::process_subtitle, this, piece, _1, _2, _3, _4));
435 shared_ptr<const StillImageContent> ic = dynamic_pointer_cast<const StillImageContent> (*i);
437 shared_ptr<StillImageDecoder> id;
439 /* See if we can re-use an old StillImageDecoder */
440 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
441 shared_ptr<StillImageDecoder> imd = dynamic_pointer_cast<StillImageDecoder> ((*j)->decoder);
442 if (imd && imd->content() == ic) {
448 id.reset (new StillImageDecoder (_film, ic));
449 id->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
455 shared_ptr<const MovingImageContent> mc = dynamic_pointer_cast<const MovingImageContent> (*i);
457 shared_ptr<MovingImageDecoder> md;
460 md.reset (new MovingImageDecoder (_film, mc));
461 md->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
467 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
469 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
470 sd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
475 _pieces.push_back (piece);
479 cout << "=== Player setup:\n";
480 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
481 cout << *(i->get()) << "\n";
487 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
489 shared_ptr<Content> c = w.lock ();
495 property == ContentProperty::POSITION || property == ContentProperty::LENGTH ||
496 property == ContentProperty::TRIM_START || property == ContentProperty::TRIM_END ||
497 property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_RATIO
500 _have_valid_pieces = false;
503 } else if (property == SubtitleContentProperty::SUBTITLE_OFFSET || property == SubtitleContentProperty::SUBTITLE_SCALE) {
506 } else if (property == VideoContentProperty::VIDEO_FRAME_TYPE) {
512 Player::playlist_changed ()
514 _have_valid_pieces = false;
519 Player::set_video_container_size (libdcp::Size s)
521 _video_container_size = s;
522 _black_frame.reset (new Image (PIX_FMT_RGB24, _video_container_size, true));
523 _black_frame->make_black ();
526 shared_ptr<Resampler>
527 Player::resampler (shared_ptr<AudioContent> c, bool create)
529 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
530 if (i != _resamplers.end ()) {
535 return shared_ptr<Resampler> ();
538 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
544 Player::emit_black ()
546 #ifdef DCPOMATIC_DEBUG
547 _last_video.reset ();
550 Video (_black_frame, EYES_BOTH, _last_emit_was_black, _video_position);
551 _video_position += _film->video_frames_to_time (1);
552 _last_emit_was_black = true;
556 Player::emit_silence (OutputAudioFrame most)
558 OutputAudioFrame N = min (most, _film->audio_frame_rate() / 2);
559 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), N));
560 silence->make_silent ();
561 Audio (silence, _audio_position);
562 _audio_position += _film->audio_frames_to_time (N);
566 Player::film_changed (Film::Property p)
568 /* Here we should notice Film properties that affect our output, and
569 alert listeners that our output now would be different to how it was
570 last time we were run.
573 if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER) {
579 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
581 _in_subtitle.piece = weak_piece;
582 _in_subtitle.image = image;
583 _in_subtitle.rect = rect;
584 _in_subtitle.from = from;
585 _in_subtitle.to = to;
591 Player::update_subtitle ()
593 shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
598 if (!_in_subtitle.image) {
599 _out_subtitle.image.reset ();
603 shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
606 dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
607 libdcp::Size scaled_size;
609 in_rect.y += sc->subtitle_offset ();
611 /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
612 scaled_size.width = in_rect.width * _video_container_size.width * sc->subtitle_scale ();
613 scaled_size.height = in_rect.height * _video_container_size.height * sc->subtitle_scale ();
615 /* Then we need a corrective translation, consisting of two parts:
617 * 1. that which is the result of the scaling of the subtitle by _video_container_size; this will be
618 * rect.x * _video_container_size.width and rect.y * _video_container_size.height.
620 * 2. that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
621 * (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
622 * (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
624 * Combining these two translations gives these expressions.
627 _out_subtitle.position.x = rint (_video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
628 _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
630 _out_subtitle.image = _in_subtitle.image->scale (libdcp::Size (scaled_size.width, scaled_size.height), Scaler::from_id ("bicubic"), true);
631 _out_subtitle.from = _in_subtitle.from + piece->content->position ();
632 _out_subtitle.to = _in_subtitle.to + piece->content->position ();